1

I got stuck in some basic file handling code in C. Basically I want to parse an input file to get some information, and then put it in another file (more information is in the input file). I used an online gcc compiler for that and all was great. When Ienter code here compile the code in cmd with gcc command output file is empty.

#include <stdio.h>
#include <string.h>

int main() {
    char c[1000];
    FILE *fptr,*resultfp;
    if ((fptr = fopen("inputfile.txt", "r")) == NULL) {
        printf("can't be opened");
    }
    if ((resultfp = fopen("outputfile.txt", "w")) == NULL) {
        printf("can't be opened");
    }
    while(strcmp(c,"END OF FILE")){
 fscanf(fptr, "%[^\n]", c);
 fseek(fptr, 1,SEEK_CUR);
 if(strstr(c,"Example name") || strstr(c,"Example description") )
 {
    fscanf(fptr, "%[^\n]", c);
    fprintf(resultfp,"%s\n", c);
 }

    }

    fclose(fptr);
    fclose(resultfp);
    return 0;
}

and this is input file:

This is an example
Example name:
example1
Example description:
description1
Example name:
example2
Example description:
description2
I want to parse this file
In order to get example name and example description
END OF FILE
  • You check the contents of `c` before you have read anything into it. The contents will be *indeterminate* and you could have *undefined behavior*. – Some programmer dude Feb 07 '20 at 13:50
  • I also suggest you check what [`strcmp` *returns*](https://en.cppreference.com/w/c/string/byte/strcmp#Return_value). – Some programmer dude Feb 07 '20 at 13:51
  • Lastly, the `%[` format specifier doesn't skip leading white-space. That means that all reading will stop at the newline from the first line. – Some programmer dude Feb 07 '20 at 13:54
  • ... and check the return value of fscanf –  Feb 07 '20 at 13:54
  • ... and should not go happily on after any of the fopens failed; your program will probably crash before being being able to flush out the no new-line terminated `can't be opened`. I think you should re-do all that program from scratch ;-) –  Feb 07 '20 at 14:00
  • and last but not least: your program is looking for "Example descrip**tion**", but your sample file says "Example descrip**ton**". –  Feb 07 '20 at 14:43

2 Answers2

1

First, even if OP code worked without problem, the input file has a problem. Neither instance of the second criteria in the input file would never be read, or posted into the output file. i.e the search criteria in the code is:

"Example description"

But the inputfile.txt line is:

"Example descripton:"//mis-spelled

Next, the lines...

char c[1000];
...
while(strcmp(c,"END OF FILE")){

...result in accessing the variable c before it is initialized. This in turn results in undefined behavior. The fix is simple, always initialize variables before using them the first time: `char c[1000] = {0};

Also, this line...

 while(strcmp(c,"END OF FILE")){

will have different results depending on the contents of c. Read about strcmp here.

Finally, this line:

fseek(fptr, 1,SEEK_CUR);

When using fseek with text files, one of the following must be true:

  • offset must be zero.
  • offset is the value returned by a previous call to ftell and origin is set to beginning-of-file.

The value of 1 for offset does not meet either of these criteria.

If you are open to trying a simpler read/parse method, using a while(fgets(...)){...} construct takes advantage of simpler parsing than can be done using variations of fscanf. The following loops until it finds the specified tag, then reads the next line in the file for the value. When fgets sees EOF, it will exit the loop. (Note, EOF is inherent to text files, negating the need for the last line in your inputfile.txt)

int main() {
    char c[1000] = {0};//always initialize before using
    FILE *fptr,*resultfp;
    if ((fptr = fopen("inputfile.txt", "r")) == NULL) {
        printf("can't be opened");
        return 0;
    }
    if ((resultfp = fopen("outputfile.txt", "w")) == NULL) {
        printf("can't be opened");
        fclose(fptr);
        return 0;
    }
    // all is well so far, continue

    while(fgets(c, sizeof(c), fptr))
    {
         if(strstr(c,"Example name") || 
            strstr(c,"Example description") )
         {
            fgets(c, sizeof(c), fptr);
            fprintf(resultfp,"%s\n", c);
         }
     }

    fclose(fptr);
    fclose(resultfp);
    return 0;
}   

Because of the way the input file is specified, it is sufficient, and simple to inspect each full line for the various tag-value pairs, in this case presented on separate lines, this method simplifies the parsing and testing of each pair.

ryyker
  • 22,849
  • 3
  • 43
  • 87
  • I tried this but parse is not as expected, I suppose this is because c[] has a fixed value. – Catalin Diaconu Feb 07 '20 at 14:33
  • @CatalinDiaconu- in your input file `Example descripton:` is used, but in your code `Example description:` is used. – ryyker Feb 07 '20 at 14:45
  • Good remark, i will correct that, i tried again and it seems the while loop never ends. I also get this warning: comparison between pointer and integer while(fgets(c, sizeof(c), fptr) != EOF) – Catalin Diaconu Feb 07 '20 at 14:54
  • @CatalinDiaconu - The code I posted runs through the loop, then closes the files, then exits. Try copy and pasting it directly from my example code if all else fails... – ryyker Feb 07 '20 at 15:06
  • it works :) thanks a lot! I have one more question: I have another input file, 8000 lines size, and if I run this code I get strange values in output file. I must say that this input file has a lot of spaces,tabs and new lines.Do you know what the problem might be? – Catalin Diaconu Feb 07 '20 at 15:22
  • @CatalinDiaconu - LOL, not without seeing the input file. If the input lines are not uniformly formatted, or have non-uniform content and syntax, then parsing becomes exponentially complicated. If you are designing the input file, then define these attributes to be consistent. If you are attempting to read in random input, then other parsing tools are needed. – ryyker Feb 07 '20 at 15:26
  • I see.. but if I use online gcc compiler, your code works perfectly fine, even with that input file! the only difference is that input file extension is file, not text file – Catalin Diaconu Feb 07 '20 at 15:33
  • @CatalinDiaconu - are you saying the online works, but your local compiler does not? – ryyker Feb 07 '20 at 15:36
  • 1
    I found the problem, in this file there are many tabs characters, if I manually delete them, it works.Thanks a lot for your help and for your time! – Catalin Diaconu Feb 07 '20 at 15:42
1

Your program has a lot of problems, but the one that kills it is the fact that it assumes that the newline is a single character, that

fseek(fptr, 1,SEEK_CUR);

will skip over.

But that's actually not the case on Windows: the stdio library will translate \r\n into \n for the sake of compatibility, but the fseek will skip just a single byte.

If you change that to

fseek(fptr, 2,SEEK_CUR);

your program will work -- for a VERY broad definition of "work".