Thread: Help reading a text file and adding new lines depending on value in line

  1. #1
    Registered User
    Join Date
    Jun 2017
    Posts
    7

    Help reading a text file and adding new lines depending on value in line

    I need to code to read in text files and write a new line between lines where the value of the first column is different to the next. Any guidance on my current code would be greatly appreciated.

    Code:
    int main()
    {
        float *doub1, *doub2;
        char *line, *rest, lines, *line2, filename[100], ch;
        FILE * newfile;
        printf("enter file name: ");
        scanf("%s", filename);
        newfile = fopen(filename, "r+");
        while (ch = fgetc(newfile) !=EOF)
        {
            if (ch == '\n')
            {
                lines++;
            }
        }
        for (int i = 0; i < lines/2; i++)
        {
            fgets(line, 100, newfile);
            sscanf(line, "%e %s", doub1, rest);
            fgets(line2, 100, newfile);
            sscanf(line, "%f %s", doub2, rest);
            if (doub2>doub1)
            {
                fputs( "\n", newfile);
            }
            doub2=doub1;
            line2=line;
        }
        return 0;
    }
    Last edited by aengland643; 06-21-2017 at 08:27 AM. Reason: update the code. now compiles, does nothing

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Yes, the first thing is use a compiler with lots of warnings, and enable those warnings.
    Code:
    $ gcc -Wall -Wextra foo.c
    foo.c: In function ‘main’:
    foo.c:8:11: warning: format not a string literal and no format arguments [-Wformat-security]
         scanf(filename);
               ^
    foo.c:10:23: warning: passing argument 1 of ‘fgetc’ from incompatible pointer type [-Wincompatible-pointer-types]
         while (ch = fgetc(filename) !=EOF)
                           ^
    In file included from foo.c:1:0:
    /usr/include/stdio.h:531:12: note: expected ‘FILE * {aka struct _IO_FILE *}’ but argument is of type ‘char *’
     extern int fgetc (FILE *__stream);
                ^
    foo.c:10:5: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
         while (ch = fgetc(filename) !=EOF)
         ^
    foo.c:12:16: warning: comparison between pointer and integer
             if (ch == "\n")
                    ^
    foo.c:12:16: warning: comparison with string literal results in unspecified behavior [-Waddress]
    foo.c:19:26: warning: passing argument 3 of ‘fgets’ from incompatible pointer type [-Wincompatible-pointer-types]
             fgets(line, 100, filename);
                              ^
    In file included from foo.c:1:0:
    /usr/include/stdio.h:622:14: note: expected ‘FILE * restrict {aka struct _IO_FILE * restrict}’ but argument is of type ‘char *’
     extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
                  ^
    foo.c:20:22: warning: format ‘%f’ expects argument of type ‘float *’, but argument 3 has type ‘double’ [-Wformat=]
             sscanf(line, "%f %s", doub, rest);
                          ^
    foo.c:22:27: warning: passing argument 3 of ‘fgets’ from incompatible pointer type [-Wincompatible-pointer-types]
             fgets(line2, 100, filename);
                               ^
    In file included from foo.c:1:0:
    /usr/include/stdio.h:622:14: note: expected ‘FILE * restrict {aka struct _IO_FILE * restrict}’ but argument is of type ‘char *’
     extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
                  ^
    foo.c:23:22: warning: format ‘%f’ expects argument of type ‘float *’, but argument 3 has type ‘double’ [-Wformat=]
             sscanf(line, "%f %s", doub2, rest);
                          ^
    foo.c:26:26: warning: passing argument 2 of ‘fputs’ from incompatible pointer type [-Wincompatible-pointer-types]
                 fputs( "\n", filename);
                              ^
    In file included from foo.c:1:0:
    /usr/include/stdio.h:689:12: note: expected ‘FILE * restrict {aka struct _IO_FILE * restrict}’ but argument is of type ‘char *’
     extern int fputs (const char *__restrict __s, FILE *__restrict __stream);
                ^
    foo.c:6:12: warning: variable ‘newfile’ set but not used [-Wunused-but-set-variable]
         FILE * newfile;
                ^
    foo.c:19:9: warning: ‘line’ may be used uninitialized in this function [-Wmaybe-uninitialized]
             fgets(line, 100, filename);
             ^
    foo.c:20:9: warning: ‘doub’ may be used uninitialized in this function [-Wmaybe-uninitialized]
             sscanf(line, "%f %s", doub, rest);
             ^
    foo.c:20:9: warning: ‘rest’ may be used uninitialized in this function [-Wmaybe-uninitialized]
    $
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jun 2017
    Posts
    7
    thanks, I've updated the code. it now compiles, but seems to do nothing to the files

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Better, but there are still things to fix.
    Code:
    $ gcc -Wall -Wextra foo.c
    foo.c: In function ‘main’:
    foo.c:10:5: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
         while (ch = fgetc(newfile) !=EOF)
         ^
    foo.c:19:9: warning: ‘line’ may be used uninitialized in this function [-Wmaybe-uninitialized]
             fgets(line, 100, newfile);
             ^
    foo.c:20:9: warning: ‘doub1’ may be used uninitialized in this function [-Wmaybe-uninitialized]
             sscanf(line, "%e %s", doub1, rest);
             ^
    foo.c:20:9: warning: ‘rest’ may be used uninitialized in this function [-Wmaybe-uninitialized]
    Also, omitting the single line of #include <stdio.h> really doesn't save anything and p....es people off because it's extra steps to actually test.
    We like to copy/paste/compile/go. If there is more work than that, you'll get comments or ignored.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jun 2017
    Posts
    7
    So on the compiler i found online, this updated code gets rid of any warnings. however, i am sure that it is not reading in my file that I type after "enter file name:"

    Code:
    #include <stdio.h>
    #include <math.h>
    #include <string>
    
    int main()
    {
        int lines=0;
        float *doub[lines] ;
        char *line[lines], *rest[lines], filename[100], ch;
        FILE * newfile;
        printf("enter file name: ");
        scanf("%s", filename);
        newfile = fopen(filename, "r+");
        while (ch = fgetc(newfile) !=EOF)
        {
            if (ch == '\n')
            {
                lines++;
            }
        }
        for (int i = 1; i < lines; i++)
        {
            fgets(line[i], 100, newfile);
            sscanf(line[i], "%f %s", doub[i], rest[i]);
            if (doub[i]>doub[i-1])
            {
                fputs( "\n", newfile);
            }
        }
            return 0;
    }

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    You need a better compiler.

    > while (ch = fgetc(newfile) !=EOF)
    > warning: suggest parentheses around assignment used as truth value [-Wparentheses]
    != has higher precedence than =, so what you've written is this

    while (ch = (fgetc(newfile) !=EOF))
    Which translates as read a char, compare with EOF and then assign the boolean result (0 or 1) to ch.

    whereas what you probably intended was this
    while ((ch = fgetc(newfile)) !=EOF)
    Which translates as read a char, assign to ch and then compare with EOF.


    > char *line[lines], *rest[lines], filename[100], ch;
    These arrays do not magically get larger simply by doing lines++ later on in the code.

    > fgets(line[i], 100, newfile);
    Nor does line[i] point to 100 bytes of memory.

    You only need a single line buffer to read the file one line at a time. Nothing you've posted suggests that you need to hold ALL the lines in memory at the same time.


    > #include <string>
    This is a C++ header file.
    Try to make sure you're compiling C with a C compiler.
    Not any old mish-mash of syntax.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    So many errors. Yikes. (*deep breath*) Here we go.

    You are allocating 0 length arrays for some reason (i.e., lines is 0 when you define line, rest, and doub). You need to move those allocations to after you've determined the number of lines.

    You didn't fix the first warning Salem mentioned in his last post. You MUST have parens around the assignment or it won't do what you want.

    After you go through the file counting newlines, you need to rewind the file to the beginning before you try to read the lines again.

    Your line array is an array of pointers, not strings. So you have no storage space to read the lines into. You can either strdup the lines to the pointers or provide space in the array for the characters.

    You start your loop to read the lines with i = 1. What about array element 0? But note that starting at 0 means you can't access element i - 1, so you would have to include an extra check that i > 0.

    You seem to be trying to write extra newlines into the file. The way you are trying to do it won't work, and even if it did, the newline character would overwrite whatever other character happened to be at that spot in the file. The newline is not "inserted" into the file, with all the other file data magically moving over for you. If you really want to insert newlines into the file you should read from the original file, write to a temporary file, then replace the original with the temporary (delete the original, rename the temporary).

  8. #8
    Registered User
    Join Date
    Jun 2017
    Posts
    7
    thanks for the help folks, I am new to C and new to this website, so sorry for being an inconvenience. Can I ask my updated code to be critiqued, it's still wrong, though I think I may have tackled the errors mentioned above. I think the whole thing is just wrong tbh
    Code:
    int main()
    {
        int lines=0;
        char filename[100], ch;
        FILE * newfile;
        printf("enter file name: ");
        scanf("%s", filename);
        newfile = fopen(filename, "r+");
        FILE * tempfile;    
        tempfile =fopen("tempfile", "w");     
        while ((ch = fgetc(newfile)) !=EOF)
        {
            if (ch == '\n')
            {
                lines++;
            }
        }
        float *doub[lines];
        char line[lines][100], rest[lines][100];
        for (int i = 0; i < lines; i++)
        {
            fgets(line[i], 100, newfile);
            sscanf(line[i], "%f %s", doub[i], rest[i]);
            if ((i=0))
            {
                fputs( line[i], tempfile);
                fputs( "\n", tempfile);
            }
            else if (i>0)
            {
                fputs(line[i], tempfile);
                fputs("\n", tempfile);
                if (doub[i] > doub[i-1])
                {
                    fputs( "\n", tempfile);
                }
            }
        }
        fclose(newfile);
        fclose(tempfile);
        return 0;
    }

  9. #9
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    You've fixed a lot of things, but a few problems remain.

    You should remove the + from "r+" (you don't need it).

    You should define a macro constant for the value 100, something like #define MAXLINE 100

    ch needs to be an int, not a char. fgetc returns an int (so that the special EOF value will be outside the range of a char).

    You've accidentally said i=0. You mean i==0.

    doub should be an array of floats, not pointers to floats (and you need to put & in front when used as a parameter to sscanf).

    And you've forgotten to rewind the file again! Just put rewind(newfile) after you count the lines.

    As Salem mentioned, it doesn't seem like you really need to store all the lines themselves since you are storing the information that you presumably want from them anyway. So a single line buffer would do.

    To make things clear, here's a rewrite.
    Code:
    #include <stdio.h>
    
    #define MAXLINE 200
    
    int main() {
        printf("enter file name: ");
        char filename[MAXLINE];
        scanf("%s", filename);
    
        FILE *newfile = fopen(filename, "r");
        FILE *tempfile = fopen("tempfile", "w");     
    
        int ch, nlines = 0;
        while ((ch = fgetc(newfile)) != EOF)
            if (ch == '\n')
                nlines++;
    
        float doub[nlines];
        char line[MAXLINE], rest[nlines][MAXLINE];
    
        rewind(newfile);
     
        for (int i = 0; i < nlines; i++) {
            fgets(line, MAXLINE, newfile);
            sscanf(line, "%f %s", &doub[i], rest[i]);
    
            if (i > 0 && doub[i] > doub[i-1])
                fputc('\n', tempfile);
    
            fputs(line, tempfile);
        }
    
        fclose(newfile);
        fclose(tempfile);
    
        return 0;
    }

  10. #10
    Registered User
    Join Date
    Jun 2017
    Posts
    7
    Amazing, thanks for the help!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 03-28-2017, 08:57 AM
  2. Reading lines of a text file
    By george7378 in forum C++ Programming
    Replies: 3
    Last Post: 04-20-2011, 08:39 AM
  3. Read text file line by line and write lines to other files
    By magische_vogel in forum C Programming
    Replies: 10
    Last Post: 01-23-2011, 10:51 AM
  4. Replies: 7
    Last Post: 12-13-2010, 02:13 PM

Tags for this Thread