6

I have started learning C (via Youtube and K&R) some time ago and I am trying to write some programs as practice. Currently I want to create a program that reads words from a file and compares the beginning of it with the input from the user. The program successfully compares the first word and gives me a result, but I just can't get the fseek() to move correctly to the next line! (This is the current version of the part that seeks for words.)

fp= fopen("final.txt", "r");
for (i=0; i<8; i++){

    fseek(fp, fileCount, SEEK_CUR);

    fgets(strFile, 20, fp);

    fileCount= strlen(strFile);

    printf("Strlen %d. is: %d\n", i+1, fileCount);
    printf("String is %s", strFile);

    compareStr(strUser, strFile);
};

fclose(fp);

fileCount is set to 0 and strlen() should return the length of the string srtFile, but it doesn't quite well. I even tried setting fseek() manually, but it just wouldn't move. The words from my file are: First, Last, Index, Field, ID, Number, Fire, Film. (each is in a new line). When I run the program and type in F (to search for a word that has a capital f), the output is :

Type in the letters: F
Strlen 1. is: 6
String is First
Match found: First

Strlen 2. is: 6
String is Index
Strlen 3. is: 1
String is
Strlen 4. is: 2
String is D
Strlen 5. is: 5
String is mber
Strlen 6. is: 1
String is
Strlen 7. is: 3
String is ilmStrlen 8. is: 3
String is ilm
Process returned 0 (0x0)   execution time : 2.218 s
Press any key to continue.

I am desperate. Any ideas/clues?

[EDIT] A big thank to everyone who helped me with this!

Milan Todorovic
  • 155
  • 1
  • 8
  • 3
    Don't you want to increase `fileCount`? If you're in Windows, you might want to open with "rb" because of the CRLF convention. If you're reading through the file sequentially, why bother with `fseek` at all? – Mike Dunlavey Apr 27 '15 at 15:16
  • 1
    Your filepointer is already at the next word, fgets moves the file pointer as it reads, so the fseek is superfluous. – phil Apr 27 '15 at 15:28
  • 1
    BTW `fseek` may be dangerous for files opened in text mode; explained [here](http://arstechnica.com/civis/viewtopic.php?t=420490). Summary: because of `\n` <-> `\r\n` conversion, the parameter to `fseek` should either be 0 or come from an earlier `ftell` call. So you should use both `fseek` and `ftell` in your program (or none? Maybe you don't need `fseek` at all?). – anatolyg Apr 27 '15 at 15:44
  • calls to the system functions fopen, fseek, fgets when used in code should have have the returned value checked to assure not error occurs (and/or to enable the code to recognize an error event and have a chance to fix it. – user3629249 Apr 27 '15 at 23:00
  • in the posted code, there is absolutely no need for the call to fseek, as the call will step the file pointer (which after the call to fgets is already moved forward the amount of characters read by fgets) – user3629249 Apr 27 '15 at 23:02
  • for this code to have any hope of working, strFile has to be an array of (at least) 20 characters and fileCount must be initialized to 0. Those details are not revealed in the posted code. – user3629249 Apr 27 '15 at 23:04
  • in reality, lets' assume that 19 characters (fgets) always allows room and appends a NUL string termination char) are read at each call to fgets() Unless each word begins at some multiple of 19 characters into the file, the word will be missed. to avoid missing a word, perhaps use the fseek() to step backward (AFTER a call to fgets()) by 18 bytes so every possible starting position is checked for the word – user3629249 Apr 27 '15 at 23:11
  • however, an even better way would be to read one word at a time then make the comparison. that way, no word would be missed and fseek would not be needed – user3629249 Apr 27 '15 at 23:14

2 Answers2

3

The issue here appears because of the fseek SEEK_CUR parameter.

You are moving the cursor twice.

One move is done by fgets (it reads and then moves the cursor forward). And the second move is done manually by fseek.

A solution may be to completely remove the fseek call.

Another solution is to use SEEK_SET instead of SEEK_CUR, but with a counter that holds the total number of character read (including new line character). For this solution to work you also need to change

fileCount= strlen(strFile);

to

fileCount += strlen(strFile) + 1;

SEEK_SET moves the cursor from the beginning of file.

SEEK_CUR moves the cursor from the current position.

  • 1
    Thanks a lot! I didn't find anywhere that fgets moves the cursor, else I wouldn't have put that fseek(). I put fseek() outside the for-loop and it works! – Milan Todorovic Apr 27 '15 at 16:33
2

Your problem is that you are not using fseek() correctly.

In your code,

fseek(fp, fileCount, SEEK_CUR);

sets the pointer to where its current at plus the filecount(the offset). That's why it skipped Last and reads Index as string 2.

To fix this, simply remove the fseek() statement.

Thomas Hsieh
  • 731
  • 1
  • 6
  • 26