Binary to Decimal Converter

Having read the preliminary stuff, I understand that you guys do not provide help with homework problems. However, I am not paying money to an institution; I'm using a college-level book to try to teach myself programming. But I also understand you guys probably wouldn't want to help me with this problem anyway simply because other people who are getting college credit for this would be able to take advantage of the help.

So with that in mind, I'm not going to ask anyone to solve the problem for me, but I would like to know how to go about troubleshooting this issue. Here's the issue: I'm trying to write a program that reads in binary data from a file (ignoring white spaces) and translating it into decimal numbers, printing out both (this is from chapter 7 problem 2 in the book "Programming and Problem Solving...). The first thing the program is supposed to do is print out the header. This is before it enters any loop. However, upon execution, I don't get the header, but I do get the number 1 printed infinitely.

Note: the chapter is on functions, and I haven't even written any. It's just a straight program. I figured I'd try getting it to work w/o functions first, then add them in later (to test my skill with functions once I get the program working).

The code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>

using namespace std;

int main()
{
    ifstream inFile;
    char bin1;
    char bin2;
    int sum = 0;
    
    inFile.open("Binary.dat");
    if (!inFile)
    {
          cout << "Error, this file could not be opened." << endl;
          system ("PAUSE");
          return 1;
    }
    cout << "Binary Number            Decimal Equivalent" << endl;
    while(inFile)
    {
          inFile.ignore(10, '1');
          inFile.get(bin1);
          inFile.get(bin2);
          while(bin2 != '\n')
          {
               if (bin1 == '0')
               sum = sum + 0;
               else if (bin1 == '1')
               sum = sum + 1;
               else cout << "Bad digit on input.";
               sum = sum * 2;
               cout << bin1;
               bin1 = bin2;
               inFile.get(bin2);
          }
          if (bin1 == '0')
          sum = sum + 0;
          else if (bin1 == '1')
          sum = sum + 1;
          else cout << "Bad digit on input.";
          cout << bin1 << "             " << sum << endl;
    }
          
               
        
    
    system("PAUSE");
    return EXIT_SUCCESS;
}


My data file:
1
1001
11011
10101
111101
11100011

Since it's printing a never-ending series of 1's before printing the header, I'm stymied as to where the error lies. Also, please know that this is my first post, so any constructive criticism would be welcome. (OK, it won't print spaces at the beginning of lines, but I do have some in my data file.)
Last edited on
I think you've misinterpreted the output, probably because it is scrolling so rapidly that you never get chance to read the start.

When I run it, this is the beginning of the output:
Binary Number Decimal Equivalent
Bad digit on input.
1001 9
1011 83
0101 669
11101 10733
1100011111111111111111111111111111111111111

The repeating output of the digit "1" occurs because the end of the file is reached within this loop:
 
while (bin2 != '\n')

When the statement inFile.get(bin2); is executed, when the get() eventually fails, the variable bin2 retains its previous value, thus the loop never terminates.

If you make sure that the input file ends with a newline character, that issue may be resolved, but it is clearly a fragile design.

I've a few overall comments. I'm not sure of the purpose of inFile.ignore(10, '1'); and I'm also not sure why there are two separate variables bin1 and bin2. I'm pretty sure it could be simplified.

Just a suggestion, I'd tend to read a complete number as a string, and then process the characters of the string. I think that would probably result in a simpler design.
Chervil, thanks for the quick response. I did insert a "system ("PAUSE")" at the end of the loop and found what you're referring to, though I still wasn't sure why until I read your comments. I will definitely try that.

You also should notice that the first number (being a '1' by itself) was cut off, and I'm wondering how to get around that. The chapter problem calls for a program that ignores preceding spaces, thus the "inFile.ignore()" command. The problem also calls for reading in each number (character) individually, so your solution about reading in a whole string wouldn't comply with the requirements. Even though I'm not doing this for credit, I still want to do the problem the way it's described in the book. But if you can point me to information that would make it simpler, by all means...I'd be happy to listen.

Also, as for why there are two character inputs: If I only had one, then what happens when that character becomes '\n'? Obviously I can't do anything with it, but I still have to add something at the end to make the decimal value correct. So I have one value that is added to the sum, and another value for sentinel purposes only. It seems to work O.K. most of the time, so I use it. I'm still pretty new at this, so if there's a better way, I'd be happy to learn.
Last edited on
i found some flaws in your coding, i'll try to demonstrate each:
1- to check if the file is open, the ifstream class has this function called is_open(), this function returns true if a file is opened by the stream,
you should use this function instead of using ( !inFile ).

2- ifstream has a function called eof(), this function returns true if end-of-file is reached, why use this function?:
your file might contain an integer value that equals the EOF macro, so reading this value might be interpreted as end-of-file, eof() works the right way, and checks for a "real" end of file.
i'm not sure of what you meant with this line:
1
2
3
...
while(inFile)
...

i'm just sure it's wrong, try this one to go through the entire file:
1
2
3
...
while( ! inFile.eof() )
...

and last, streams read at least a whole byte of data, so i'd advice for this approach:
define a char variable that will contain the input byte.
that variable will hold an int, don't deal with this integer as decimal, deal with it as hex.
mapping hex to string is your job, i'll just give you a hint: use logical operators ( & , | , << , >> ), i used them in a similar project i'm working on.
3- the std function system() was demonstrated to be insecure, check this for pausing your program:
http://www.cplusplus.com/forum/beginner/103201/

a friend of mine wrote this program, it does exactly what yours does, but input is from console:
http://notes.io/ad6

for more info:
http://www.cplusplus.com/doc/tutorial/files/

one last thing, use code tags:
http://www.cplusplus.com/articles/jEywvCM9/

hope that was useful.
Last edited on
The problem with this inFile.ignore(10, '1'); is that it keeps ignoring characters until it finds a '1; - which is then ignored. That means the first digit of all the values is discarded. Instead of that, try inFile >> ws;
http://www.cplusplus.com/reference/istream/ws/

Sometimes it's easier to just post some code than to try to explain. So I'm posting a complete program here, but I'm not suggesting it is an ideal or model solution. It's loosely based on the same concepts as the original code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <fstream>

    using namespace std;

int main()
{
    ifstream inFile("Binary.dat");
    if (!inFile)
    {
        cout << "input file not open" << endl;
        cout << " -- Press return to exit --" << endl;
        cin.get(); // wait for user
        return 1;
    }

    char bin;
    int sum = 0;

    inFile >> ws;

    while (inFile.get(bin))
    {
        if (bin == '\n')
        {
            cout << " " << sum << endl;
            sum = 0;
            inFile >> ws;
            continue;   // go back to start of while loop
        }

        sum *= 2;

        cout << bin;

        if (bin == '1')
            sum++;
        else if (bin != '0')
            cout << "bad input char " << bin << endl;

    }

    if (bin != '\n')   // catch situation where file does not end with '\n'
    {
        cout << " " << sum << endl;
    }

    cout << " -- Press return to exit --" << endl;
    cin.get(); // wait for user

    return 0;
}

@Rechard3
I've not been through your entire post, however this part stands out, quote:
i'm not sure of what you meant with this line: while(inFile)

That's a pretty standard way to handle looping through a file. When the ifstream is tested as a boolean (true or false) value, it is effectively the same as testing while (!inFile.fail()) but is more concise and versatile.

For example it can also be used like this:
1
2
char ch;
while (inFile >> ch)

or
while (inFile.get(ch))
in these examples, the input is attempted and then the fail bit of the stream is tested. This is a very convenient way to handle input, and is generally a better and safer solution than testing eof().

There are many situations where the input can fail but the eof() flag is not set, and the program can get caught in an infinite loop. Also a common mistake is to test eof() before the input is done, instead of afterwards, which is bound to be incorrect.

My recommendation is to avoid testing eof() except in some very specific and limited situations.
i'm sorry if i provided false information, but i actually read a book by Herbert Schildt, one of the standardization committee of the c++ language.
he recommended using the eof() function, and claimed it to be a safe way for testing eof.
i'll do some searches about it, just to make sure,
there's a chance that you are an experienced programmer and have trusted expertise.
Well, I don't want to sound too harsh or critical. I've read one or two books by Herbert Schildt, and found them reasonably useful, though I don't have them to hand right now.

All I'd like to add is it's a matter of using whichever tool is most appropriate for the task, without seeing the specific example and the circumstances from Schildt it's hard to comment further.

I'd place myself somewhere in the middle when it comes to C++. (I've worked a lot with other languages). I'm not a beginner but there are plenty of people around here with better knowledge of C++ than myself. For example if you come across posts by Cubbi they are a valuable and trusted source.
Thanks for all the info. I did update my original post to make the code easier to read (thanks, Rechard3). I can also see where "cin.get()" would be useful in pausing a program to wait for user input before exiting. As for ignoring white spaces, the book (chapter 4) actually says the >> operator does a fine job of that. I had forgotten that, which is why I tried the "cin.ignore()" function. Now that I reverted back, that part of it is working fine.

I'm still working on the rest of it. If I have more questions, I'll let you know. Otherwise I'll post again once I get it working. Thanks again!
As for ignoring white spaces, the book (chapter 4) actually says the >> operator does a fine job of that.

Yes it does. However, remember that the newline character '\n' is also considered whitespace, so you won't be able to test for that character if it is skipped.
Topic archived. No new replies allowed.