I can't figure out why my while loop won't work. The code works fine without it... The purpose of the code is to find a secret message in a bin file. So I got the code to find the letters, but now when I try to get it to loop until the end of the file, it doesn't work. I'm new at this. What am I doing wrong?
main(){
FILE* message;
int i, start;
long int size;
char keep[1];
message = fopen("c:\\myFiles\\Message.dat", "rb");
if(message == NULL){
printf("There was a problem reading the file. \n");
exit(-1);
}
//the first 4 bytes contain an int that tells how many subsequent bytes you can throw away
fread(&start, sizeof(int), 1, message);
printf("%i \n", start); //#of first 4 bytes was 280
fseek(message, start, SEEK_CUR); //skip 280 bytes
keep[0] = fgetc(message); //get next character, keep it
printf("%c", keep[0]); //print character
while( (keep[0] = getc(message)) != EOF) {
fread(&start, sizeof(int), 1, message);
fseek(message, start, SEEK_CUR);
keep[0] = fgetc(message);
printf("%c", keep[0]);
}
fclose(message);
system("pause");
}
EDIT:
After looking at my code in the debugger, it looks like having "getc" in the while loop threw everything off. I fixed it by creating a new char called letter, and then replacing my code with this:
fread(&start, sizeof(int), 1, message);
fseek(message, start, SEEK_CUR);
while( (letter = getc(message)) != EOF) {
printf("%c", letter);
fread(&start, sizeof(int), 1, message);
fseek(message, start, SEEK_CUR);
}
It works like a charm now. Any more suggestions are certainly welcome. Thanks everyone.
The return value from
getc()
and its relatives is anint
, not achar
.If you assign the result of
getc()
to achar
, one of two things happens when it returnsEOF
:char
is unsigned, then EOF is converted to 0xFF, and 0xFF != EOF, so the loop never terminates.char
is signed, then EOF is equivalent to a valid character (in the 8859-1 code set, that's ÿ, y-umlaut, U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS), and your loop may terminate early.Given the problem you face, we can tentatively guess you have plain
char
as an unsigned type.The reason that
getc()
et al return anint
is that they have to return every possible value that can fit in achar
and also a distinct value, EOF. In the C standard, it says:Similar wording applies to the
getc()
function and thegetchar()
function: they are defined to behave like thefgetc()
function except that ifgetc()
is implemented as a macro, it may take liberties with the file stream argument that are not normally granted to standard macros — specifically, the stream argument expression may be evaluated more than once, so callinggetc()
with side-effects (getc(fp++)
) is very silly (but change tofgetc()
and it would be safe, but still eccentric).In your loop, you could use:
This preserves the assignment to
keep[0]
; I'm not sure you truly need it.You should be checking the other calls to
fgets()
,getc()
,fread()
to make sure you are getting what you expect as input. Especially on input, you cannot really afford to skip those checks. Sooner, rather than later, something will go wrong and if you aren't religiously checking the return statuses, your code is likely to crash, or simply 'go wrong'.There are 256 different
char
values that might be returned bygetc()
and stored in achar
variable likekeep[0]
(yes, I'm oversummarising wildly). To detect end-of-file reliably,EOF
has to have a value different from all of them. That's whygetc()
returnsint
rather thanchar
: because a 257th distinct value forEOF
wouldn't fit into achar
.Thus you need to store the value returned by
getc()
in anint
at least until you check it againstEOF
: