0

I have designed a program in c program to count the number of rows but it shows the garbage values. My file contains the data as follows

2,8,10
3,5,7
4,5,1
3,6,8
3,7,8
3,8,4

for counting the number of rows i have written the program as

int count_lines =0;
char sample_char;
FILE *fptr;
fptr = fopen("demo3.txt", "r");
sample_chr = getc(fptr);
while (sample_chr != EOF)
{
        if (sample_chr == '\n')
         count_lines = count_lines +1;

        sample_chr = getc(fptr);
}
printf("\n\n\n The number of lines are %d",count_lines);

but the garbage values are being printed here. Where i am going wrong???

when i am writing the below code it works perfectly

typedef struct ratings {
    int userId;
    int movieId;
    int rating;
}Ratings;
  int i, n=65;
  FILE *fptr;
    fptr = fopen("demo3.txt", "r");

/*  *//counting the number of lines present in the above file
    sample_chr = getc(fptr);
    while (sample_chr != EOF)
    {
        if (sample_chr == '\n')
         count_lines = count_lines +1;

        sample_chr = getc(fptr);
    }* */
    printf("\n\n\n The number of lines are %d",count_lines);
    //storing the values in array of structures
    for(i=0;i<n;i++)
    fscanf(fptr, "%d,%d,%d", &REC1[i].userId, &REC1[i].movieId, &REC1[i].rating);

now if i am printing the contents i am getting the output. If i remove the comment lines then garbage value appears

Sam
  • 13
  • 5
  • 1
    `char sample_char;` --> `int sample_chr;` – BLUEPIXY Oct 24 '17 at 22:18
  • 1
    I don't reproduce it. Check return value of `fopen`. – BLUEPIXY Oct 24 '17 at 22:22
  • I guess you are probably watching the output of another program. – BLUEPIXY Oct 24 '17 at 22:25
  • No same program only – Sam Oct 24 '17 at 22:28
  • 2
    Do `n=count_lines; rewind(fptr);` before reading data from file. – BLUEPIXY Oct 24 '17 at 22:39
  • Nothing going on I am trying to create the array of structure dynamically so i need the number of rows present in the file – Sam Oct 24 '17 at 22:39
  • @BLUEPIXY didn't get you. what you are trying to say – Sam Oct 24 '17 at 22:40
  • Check the return value of fscanf, in the second snippet it will be EOF because you have already read the whole file. So, as BLUEPIXY commented, you have to rewind. – Bob__ Oct 24 '17 at 22:41
  • Possible duplicate of [Difference between int and char in getchar/fgetc and putchar/fputc?](https://stackoverflow.com/questions/35356322/difference-between-int-and-char-in-getchar-fgetc-and-putchar-fputc) – n. m. could be an AI Oct 25 '17 at 06:46
  • when calling `fopen()` always check (!=NULL) the returned value to assure the operation was successful. If not successful, call `perror()` to have your message and the system text regarding the error output to `stderr`. – user3629249 Oct 26 '17 at 07:56
  • when calling `fscanf()`, always check the returned value (not the parameter values) to assure the operation was successful. In the posted code, a returned value other than 3 indicates an error occurred. – user3629249 Oct 26 '17 at 07:57
  • suggest researching the meaning of 'the current file pointer' or 'current position in a file'. – user3629249 Oct 26 '17 at 08:04
  • there is a logic problem in the code for obtaining a line count. Not every file is terminated via a new line, ('\n') so would be better to keep a flag that indicates when inside a line, reset the flag each time a '\n' is read and set the flag when any other character is read. After reaching EOF, check the flag, if it is set, then add 1 to the line count – user3629249 Oct 26 '17 at 08:08

2 Answers2

1

You forgot to check whether the file opened.

fptr = fopen("demo3.txt", "r");

Every file operation, especially opening a file, should be error checked. Here's an example.

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

...

char filename[] = "demo3.txt";
FILE *fptr = fopen(filename, "r");
if( fptr == NULL ) {
    fprintf( stderr, "Could not open %s for reading: %s\n",
             filename, strerror(errno)
    );
    exit(1);
}

//storing the values in array of structures
    for(i=0;i<n;i++)
    fscanf(fptr, "%d,%d,%d", &REC1[i].userId, &REC1[i].movieId, &REC1[i].rating);

This would be what is producing the garbage. Because it comes after getc is done reading the file, calls to fscanf will try to read past the end of the file and fail (again, check every file operation). Nothing will be put into REC1, it will contain the garbage it had when it was declared.

Think of fptr like a cursor in an editor. Every time you read from it, the cursor moves forward. Every call to getc moves the cursor forward one character. By the time you call fscanf, it's reached the end of the file.

You can move the cursor around with fseek. Use it to move fptr back to the beginning of the file. And, yup, check to make sure it worked.

if( fseek(fptr, 0, SEEK_SET) != 0 ) {
    fprintf( stderr, "Could not rewind %s: %s\n", filename, strerror(errno) );
}

Note that you'll still get garbage because you're reading n times rather than count_lines times.

Note that you can't display the offending line. This, and many other reasons, is why it's best to avoid fscanf and instead read the line with fgets and use sscanf to parse the line. This also does away with the need to read n times, just read until all the lines are done.

// A line buffer
char line[1024];
int i = 0;

// Read a line
while( fgets( line, sizeof(line), fptr) != NULL ) {
    // Parse the line
    if( sscanf(line, "%d,%d,%d", &REC1[i].userId, &REC1[i].movieId, &REC1[i].rating) < 3 ) {
        fprintf( stderr, "Could not understand '%s' from %s\n", line, filename );
        continue;
    }

    // Print what we got
    printf("uid: %d, mid: %d, rating: %d\n", REC1[i].userId, REC1[i].movieId, REC1[i].rating);
    i++;
}

As for making sure REC1 is big enough to hold all the lines, look into realloc.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Well file is opening and operations are being performed. but when i am writing the above codes garbage values appear on the screen – Sam Oct 24 '17 at 22:22
  • @Sam How do you know the file opened successfully if you don't check? Your code works for me, except for some obvious typos, if demo3.txt exists, and segfaults if not. – Schwern Oct 24 '17 at 22:24
  • As when i skipping the counting for row codes and printing the contents of the files i am getting the same values that means file is opening correctly and the file pointer is pointing to the exact file which i had mentioned – Sam Oct 24 '17 at 22:27
  • @Sam Really, do the explicit check. It will save you so many headaches. Are showing us your real code? If not, something else you're not showing us is interfering. – Schwern Oct 24 '17 at 22:28
  • i have added my real codes. have a look – Sam Oct 24 '17 at 22:33
  • @Sam I've edited my answer. – Schwern Oct 25 '17 at 06:47
0

after walking through the file, counting the number of lines,

Then need to rewind() or lseek() the file back to the beginning before extracting the data

user3629249
  • 16,402
  • 1
  • 16
  • 17