-1

I'm trying to read from a file in C, and feed the data into 5 different fields of a structure using spaces as a delimiter. I have a list of over 70 different patients, each formatted as such,

Mark Cruz 5627 193.0 3.0

Joseph Feminella 4328 194.0 3.5

Eriverto Lopez 7899 195.0 7.9

Austin Duarte 3056 196.0 12.4

Jacob England 1453 197.0 6.7

There aren't new lines between each, they are all on after the other. When I run this program it seems to start about halfway through the file each time, prints a ')' before 'First Name:' every time, and ends with a patient having zeros for every field.

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

typedef struct node{
    char pln[30];
    char pfn[20];
    int pid;
    float pwt;
    float phgnum;
    struct node* next;
    struct node* back;
}node;

int main(){

    FILE *fp;
    char c;
    node* newptr;
     fp = fopen("info.txt","r");

    if(fp == NULL){
        printf("ERROR File Doesn't exist\n");
    }

    while(c != EOF){

        newptr = (node*)malloc(sizeof(node));
        newptr->back = NULL;
        newptr->next = NULL;
        newptr->phgnum = 0;
        newptr->pid = 0;
        newptr->pwt = 0;
        fscanf(fp,"%s %s %i %f %f",newptr->pfn,newptr->pln,&newptr->pid,&newptr->pwt,&newptr->phgnum);
        c = getc(fp);
        printf("First Name: %s\n",newptr->pfn);
        printf("Last Name: %s\n",newptr->pln);
        printf("PID: %i\n",newptr->pid);
        printf("Weight: %f\n",newptr->pwt);
        printf("HG1AC: %f\n",newptr->phgnum);

        printf("\n\n\n)");
    }
}
DeiDei
  • 10,205
  • 6
  • 55
  • 80
Adam
  • 39
  • 1
  • 1
  • 8

2 Answers2

4

The extra paren is from the printf itself.

    printf("\n\n\n)");
                  ^ right here!  :)

Also, as noted in the comments: you have an uninitialized variable:

$ clang -Wall rfic.c 
rfic.c:18:8: warning: variable 'c' is used uninitialized whenever function 'main' is called
      [-Wsometimes-uninitialized]
  char c;
  ~~~~~^
rfic.c:26:10: note: uninitialized use occurs here
  while (c != EOF) {
         ^
rfic.c:18:9: note: initialize the variable 'c' to silence this warning
  char c;
        ^
         = '\0'
1 warning generated.

You also have a memory leak. newptr is assigned the result of an allocation and this pointer is overwritten with each iteration of this loop.

Brian Cain
  • 14,403
  • 3
  • 50
  • 88
  • Thank you so much! i've fixed the problems you've pointed out, but it still seems that it doesn't read from the beginning of the file, instead a few lines down – Adam May 07 '18 at 13:48
3

There are many problems here.

  • You consistently allocate a new node for each line, and immediately leak the pointer: that is what is called a memory leak. Is you want to use a doubly linked list, what node let assume, you should:

    • keep a pointer to first and last node
    • consistently manage those pointers and the next and back members of each node
  • while (c != EOF) is plain wrong (that's for your current question). First, is a FAQ in SO: Why is “while ( !feof (file) )” always wrong?, so you should avoid that kind of pattern. Even if in you case, you read an extra character after each line, the last line is likely to be ended by an end of line, so fgetc will successfully return the '\n', and next scanf will fail. As you do not test their return value, you process unspecified values. In addition, you store the return value of fgetc in a char, when you should use an int to differentiate between EOF and any possible char. Stick to the normal pattern:

    for(;;) {         // infinite loop
        ...
        if (5 != fscanf(...)) {
            // process error
            ...
            break;    // exit loop
        }
    }
    
  • You print the extra paren as explained by Brian Cain

    printf("\n\n\n)");
                  ^
    
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • 1
    Thank you so much! Excuse my ignorance but, what would I use as the break condition for the infinite loop, I see you have ( 5 != fscanf(...)), I tried it out and it works! Thank you again, but why do I have to use 5? EDIT: I figured it out thank you very much – Adam May 07 '18 at 14:16
  • 1
    @Adam: do use cpp reference, `man` on Linux, help on Windows, or whatever, but please always read the documentation for the functions of the standard library when you use them. I have been using C for more than 20 years, and still use `man func` when I want to be sure of a detail... – Serge Ballesta May 07 '18 at 14:42
  • Thank you for the advice i'll definitely start doing that in the future, I just have one last question if you don't mind. when I use the != scanf, it appears to skip every other line in the file – Adam May 07 '18 at 15:06
  • @Adam: It should not... As it is a different problem (more exactly different code in the question) you should ask a new question, optionaly refering this one. – Serge Ballesta May 07 '18 at 15:09