char and '0' comparison in c++ not giving wanted results - c++

i am having a binary value read from file and have to make comparison whether its a 1 or 0
but when i try to compare
char ch;
while(!in.eof()){
in.get(ch);
if(ch=='0') count0++;
}
The above code is not executing even when ch='0'
if(ch=='1') count1++;
that too is not giving me correct answer
how these can be compared?
it has to do something with the ascii coding or something?
From a comment:
The content of the file is 01101111111111111100000000 just like that. It's a .txt file

Your question leaves some space for interpretation.
You say that your file contains '1' and '0'. All files contain ones and zeros. Computers contain nothing more than ones and zeros (joke!).
Since you say that you have a binary file, I assume that what you try to ask is how to read the contents of the file bit by bit. Is that what you are asking?
If not, then you already have answers in the comments. Discard the rest of this message.
If yes, you'd want to first read byte by byte (i.e.: char by char) as you are doing and then iteratively apply some masks upon the byte to see whether at the given position in the byte there is a one or a zero ( this - how to convert a char to binary? - might help ).

Never use eof() as an alternative for checking whether the reading from the file was successful or not.
It could look the following way:
std::ifstream in("test.txt", std::ifstream::in);
if (!in.is_open()) {
std::cout << "Error opening file";
return -1;
}
int count0 = 0,
count1 = 0;
char ch;
while (in.get(ch)) {
if (ch == '0')
count0++;
else if (ch == '1')
count1++;
}

Related

How to read just before EOF from a file and put it into a string? [duplicate]

This question already has answers here:
How do I read an entire file into a std::string in C++?
(23 answers)
Closed 3 years ago.
My function reads a file and puts it into a string in order for me to process it. I need to read just before EOF, obviously. The problem is that the EOF character is also put inside the string and I can't find a way to bypass it, since it leds other parts of the program to fail. I link the function below.
string name_to_open, ret = string();
ifstream in;
getline(cin, name_to_open);
in.open(name_to_open.c_str());
if (!in.is_open()) {
cout << "Error." << endl;
return string();
}
else {
ret += in.get();
while (in.good()) {
ret += in.get();
};
};
in.close();
return ret;
The function reads fine until the end of the file, then appends EOF and \0. How can I solve the problem? Does the EOF character work fine in controls? I also tried to put a line ret[ret.size() - 1] = '\0'; at the end of the cycle, but this doesn't seem to work either.
ret += in.get(); appends the character read from the tile to the string whether the value read was good or not. You need to 1) read, 2) test that the read is valid and the value read is safe to use, 3) use the value read. Currently your code reads, uses, and then tests whether or not the value read was safe to use.
Possible solution:
int temp;
while ((temp = in.get()) != EOF) // read and test. Enter if not EOF
{
ret += static_cast<char>(temp); // add the character
};
Note: get returns an int, not a char. This is to be able to insert out-of-band codes such as EOF without colliding with an existing valid character. Immediately treating the return value as a char could result in bugs because a special code may be mishandled.
Note: there are many better ways to read an entire file into a string: How do I read an entire file into a std::string in C++?

Check scanf formating without conversions

Is there a way how to check if some specific characters were given on input using scanf without using character conversions?
int main(void)
{
if(scanf("{ ["))
printf("GOOD INPUT\n");
else
printf("BAD INPUT\n");
return 0;
}
This code always gives the bad input option (it expects scanf return value to be 1) but interestingly if I enter other than the desired characters it gives the bad input imediately but if I enter it as its specified in the scanf it blows the bad input at me AFTER I enter the whole input.
So it must be awaiting the input to be in that specified format but my question is: How can I check it, without any conversions, and make according action depending on wether the input was entered correctly or not?
You might use the %n conversion of scanf (it sets below into pos the number of characters read so far)
int pos= -1;
if (scanf("{ [%n", &pos) >=0 && pos>0)
printf("GOOD INPUT\n");
else
printf("BAD INPUT");
Beware, the return count of scanf might be implementation specific (it probably stays at 0). But pos get assigned to a positive offset of scanf did get { followed by some (zero or more) space-like characters followed by a [.
However, what you probably want is some lexical analysis and parsing, then scanf is not a good solution. You'll better read the entire line (e.g. with fgets or getline) and parse it later.
See also the man page of scanf(3)
scanf (and cousins) returns a count of the number of successful conversions. If you specify 0 conversions, then its return value will always be 0.
To use scanf for this task, I'd probably use a couple of scanset conversions:
char a[2], b[2];
if (scanf("%1[{] %1[[]", &a, &b) == 2)
printf("Matched");
Or, you could simplify this a little bit:
char a[2];
if (scanf("{ %1[[]", &a) == 1)
Either way, we've specified each scan set to match only one specified character, but it's still a conversion, so we can see whether it succeeded or failed.
Unfortunately, we still have to assign the result somewhere. scanf does support using * like this: "%*s", to tell it to read a string, but not store the result anywhere--but when you do so, that conversion doesn't get counted in the return value, so (much like before) we can't use it to determine whether we got a match or not.
If good input needs to exactly 3 characters: { space [, use "%*1[ ]" to scan a space and "%n", which saves the scan character count, to insure scanning reach the expected end.
int main(void) {
int n = -1;
scanf("{%*1[ ][%n", *n);
if (n >= 0) {
printf("GOOD INPUT\n");
} else {
printf("BAD INPUT\n");
}
return 0;
}
I'd recommend to read a line of input with fgets() first and then parse the buffer. That can leave stdin in a better known state when bad input happens.

using getchar() and getting stuck in loop [duplicate]

For my homework assignment, I need to implement Horners Algorithm for converting between bases.
I have been told to use getchar() for this assignment. But I am having a problem where when I hit enter, the program doesn't terminate and just takes in more chars.
Example:
bryce> ./pa1
Enter the fromRadix:16
Enter the toRadix:2
abc
abc
^C
bryce>
Code:
int readRadixA(int radixA)
{
char myChar = getchar();
int result = 0;
int run = 0;
while(myChar != EOF)
{
if(myChar == "\n")
break;
Horners();
myChar = getchar();
}
return result;
}
I am not asking for help implementing Horners; I am asking for help to terminate the getchar() correctly.
if(myChar=="\n")
^ ^
You're comparing myChar wrong. Try this instead:
if(myChar == '\n')
^ ^
A second problem is that getchar returns int, not char. Maybe you can rewrite it like this:
int myChar;
while((myChar = getchar()) != EOF && myChar != '\n')
{
/* Your stuff. */
}
EDIT
In light of comments, I think some stdio operation before that while is leaving a \n in the buffer.
Instead of scanf("%d", &radix) try:
scanf("%d ", &radix);
^
That space will make scanf eat the remaining blanks (including the newline).
Check the return type of getchar(). Yes, it's an int. That's because EOF must have a value that can be distinguished from a valid character. myChar must actually be made to be int.
Try this code
int readRadixA(int radixA)
{
char myChar;
int result = 0;
int run = 0;
do
{
myChar = getchar();
// implement horners here
}while(myChar != 13);
return result;
}
I checked your code I think you are leaving a '\n' in the input keyboard buffer after the toRadix.
And their is one more thing that
getchar()
reads all the characters in one go till a '\n' is received.
And there is one more mistake you have committed by comparing a
char to a pointer e.g mychar=="\n"
further information about your implementation of toRadix can be really helpful to answer your question
On linux, to end the standard input, you have to type  Ctrl-D. The kernel and tty layers makes that an end-of-file mark or condition. Then getchar gives EOF (which is not a valid char, for example on systems where char are unsigned bytes between 0 and 255, EOF could be -1).
Notice that feof(3) is valid only after a read operation (e.g. getchar, fgets, etc...) so coding while(feof(stdin)) is generally wrong (contrarily to what I wrote in the previous version of this answer). You'll better test that getchar is returning EOF so your myChar should be an int (not a char).

Simple C++ not reading EOF

I'm having a hard time understanding why while (cin.get(Ch)) doesn't see the EOF. I read in a text file with 3 words, and when I debug my WordCount is at 3 (just what I hoped for). Then it goes back to the while loop and gets stuck. Ch then has no value. I thought that after the newline it would read the EOF and break out. I am not allowed to use <fstream>, I have to use redirection in DOS. Thank you so much.
#include <iostream>
using namespace std;
int main()
{
char Ch = ' ';
int WordCount = 0;
int LetterCount = 0;
cout << "(Reading file...)" << endl;
while (cin.get(Ch))
{
if ((Ch == '\n') || (Ch == ' '))
{
++WordCount;
LetterCount = 0;
}
else
++LetterCount;
}
cout << "Number of words => " << WordCount << endl;
return 0;
}
while (cin >> Ch)
{ // we get in here if, and only if, the >> was successful
if ((Ch == '\n') || (Ch == ' '))
{
++WordCount;
LetterCount = 0;
}
else
++LetterCount;
}
That's the safe, and common, way to rewrite your code safely and with minimal changes.
(Your code is unusual, trying to scan all characters and count whitespace and newlines. I'll give a more general answer to a slightly different question - how to read in all the words.)
The safest way to check if a stream is finished if if(stream). Beware of if(stream.good()) - it doesn't always work as expected and will sometimes quit too early. The last >> into a char will not take us to EOF, but the last >> into an int or string will take us to EOF. This inconsistency can be confusing. Therefore, it is not correct to use good(), or any other test that tests EOF.
string word;
while(cin >> word) {
++word_count;
}
There is an important difference between if(cin) and if(cin.good()). The former is the operator bool conversion. Usually, in this context, you want to test:
"did the last extraction operation succeed or fail?"
This is not the same as:
"are we now at EOF?"
After the last word has been read by cin >> word, the string is at EOF. But the word is still valid and contains the last word.
TLDR: The eof bit is not important. The bad bit is. This tells us that the last extraction was a failure.
The Counting
The program counts newline and space characters as words. In your file contents "this if fun!" I see two spaces and no newline. This is consistent with the observed output indicating two words.
Have you tried looking at your file with a hex editor or something similar to be sure of the exact contents?
You could also change your program to count one more word if the last character read in the loop was a letter. This way you don't have to have newline terminated input files.
Loop Termination
I have no explanation for your loop termination issues. The while-condition looks fine to me. istream::get(char&) returns a stream reference. In a while-condition, depending on the C++ level your compiler implements, operator bool or operator void* will be applied to the reference to indicate if further reading is possible.
Idiom
The standard idiom for reading from a stream is
char c = 0;
while( cin >> c )
process(c);
I do not deviate from it without serious reason.
you input file is
this is fun!{EOF}
two spaces make WordCount increase to 2
and then EOF, exit loop! if you add a new line, you input file is
this is fun!\n{EOF}
I took your program loaded it in to visual studio 2013, changed cin to an fstream object that opened a file called stuff.txt which contains the exact characters "This is fun!/n/r" and the program worked. As previous answers have indicated, be careful because if there's not a /n at the end of the text the program will miss the last word. However, I wasn't able to replicate the application hanging in an infinite loop. The code as written looks correct to me.
cin.get(char) returns a reference to an istream object which then has it's operator bool() called which returns false when any of the error bits are set. There are some better ways to write this code to deal with other error conditions... but this code works for me.
In your case, the correct way to bail out of the loop is:
while (cin.good()) {
char Ch = cin.get();
if (cin.good()) {
// do something with Ch
}
}
That said, there are probably better ways to do what you're trying to do.

Reading file byte by byte with ifstream::get

I wrote this binary reader after a tutorial on the internet. (I'm trying to find the link...)
The code reads the file byte by byte and the first 4 bytes are together the magic word. (Let's say MAGI!) My code looks like this:
std::ifstream in(fileName, std::ios::in | std::ios::binary);
char *magic = new char[4];
while( !in.eof() ){
// read the first 4 bytes
for (int i=0; i<4; i++){
in.get(magic[i]);
}
// compare it with the magic word "MAGI"
if (strcmp(magic, "MAGI") != 0){
std::cerr << "Something is wrong with the magic word: "
<< magic << ", couldn't read the file further! "
<< std::endl;
exit(1);
}
// read the rest ...
}
Now here comes the problem, when I open my file, I get this error output:
Something is wrong with the magic word: MAGI?, couldn't read the file further! So there is always one (mostly random) character after the word MAGI, like in this example the character ?!
I do think that it has something to do with how a string in C++ is stored and compared with each other. Am I right and how can I avoid this?
PS: this implementation is included in another program and works totally fine ... weird.
strcmp assumes that both strings are nul-terminated (end with a nul-character). When you want to compare strings which are not terminated, like in this case, you need to use strncmp and tell it how many characters to compare (4 in this case).
if (strncmp(magic, "MAGI", 4) != 0){
When you try to use strcmp to compare not null-terminated char arrays, it can't tell how long the arrays are (you can't tell the length of an array in C/C++ just by looking at the array itself - you need to know the length it was allocated with. The standard library is not exempt from this limitation). So it reads any data which happens to be stored in memory after the char array until it hits a 0-byte.
By the way: Note the comment to your question by Lightness Races in Orbit, which is unrelated to the issue you are having now, but which hints a different bug which might cause you some problems later on.