Thread: junk display while accessing a .txt files throug c standard i/o calls

  1. #1
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147

    junk display while accessing a .txt files throug c standard i/o calls

    Hello friends,


    in my below program iam opening doing add,display operations on .txt file.

    Add operation is done properly , and in file also the data is storing as expected .

    But while displaying records some garbage comes , and it doesnot print in a record by record format.

    Iam using strtok here.

    For debug purpose i print the buffer before strtok and after strtok , it shows some malfunction there.

    Friends please guide if iam missing any thing here.

    thanks in advance.


    Code:
    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    #define SUCCESS 0
    #define DATA_BASE_ERR 1
    #define ID_NOT_FOUND_ERR 2
    
    #define REC_SIZE 28
    
    typedef struct
    {
      int studentId;
      char name[20];
      int phoneNum;
    }student_t;
    
    void strip_newline(char *name);
    void disp_help();
    int addNewStudentRec(FILE *fp,student_t *pS);
    int dispAllStudentRecs(FILE *fp);
    #if 0
    int deleteStudentRec(FILE fp,int studentId);
    #endif
    
    
    int main()
    {
      int option = 0,fd = 0,id = 0;
      student_t nRec;
      FILE *fp;
    
      memset(&nRec,0,sizeof(nRec));
    
      fp = fopen("student.txt","r+");
    
      if (!fp)
        {
          printf("Creating the file \n");
          fp = fopen("student.txt","w+");
          if (!fp)
            {
              printf("Could not create file \n");
              exit(1);
            }
        }
    
      disp_help();
    
      while(1)
        {
          printf("\n Enter Option: ");
          __fpurge(stdin);
          scanf("%d",&option);
          switch(option)
            {
              case 1:
                dispAllStudentRecs(fp);
                break;
            case 2:
              printf("Enter id name and phone \n");
              scanf("%d",&nRec.studentId);
              __fpurge(stdin);
              fgets(nRec.name,20,stdin);
              strip_newline(nRec.name);
              scanf("%d",&nRec.phoneNum);
              if(addNewStudentRec(fp,&nRec) != SUCCESS)
                printf("Record add operation failed \n");
              break;
    #if 0
            case 3:
              printf("Enter id of record to delete :");
              scanf("%d",&id);
              if(deleteStudentRec(fd,id)!= SUCCESS)
                printf("Record delete operation failed \n");
              break;
    #endif
            case 4:
              printf("Good bye \n");
              return SUCCESS;
            default:
              printf("Invalid option.Use the following \n");
              disp_help();
              break;
            }//switch
        }//while
      return SUCCESS;
    }
    
    
    void strip_newline(char *name)
    {
      int len;
    
      len = strlen(name);
      if (name[len-1] == '\n')
        name[len-1] = 0;
    }
    
    
    void disp_help()
    {
      printf("Enter 1 to display all records \n");
      printf("Enter 2 to add a record \n");
      printf("Enter 3 to delete a record \n");
      printf("Enter 4 to exit \n");
    }
    
    
    void line2rec(char *lbuf,student_t *pr)
    {
      char *str;
      int len;
      str = (char *)strtok(lbuf,",\n");
      sscanf(str,"%d",&pr->studentId);
      str = (char *)strtok(0,",\n");
      len = strlen(str);
      str[len] = '\0';
      strcpy(pr->name,str);
      printf("before strtok line 2 rec %s\n",pr->name);
      str = (char *)strtok(0,",\n");
      sscanf(str,"%d",&pr->phoneNum);
      printf("after strtok line 2 rec %s\n",pr->name);
    
    }
    
    
    
    
    int dispAllStudentRecs(FILE *fp)
    {
      int len;
      student_t rec;
      char lbuf[100];
    
      memset(&rec,0,sizeof(rec));
      memset(&lbuf,0,sizeof(lbuf));
    
      fseek(fp,0,SEEK_SET);
      len = fread(&lbuf,1,REC_SIZE,fp);
      if (len != REC_SIZE)
        {
          printf("No record to print \n");
          return ;
        }//if
    
    
      while(len == REC_SIZE)
        {
          line2rec(lbuf,&rec);
          if (rec.studentId != -1)
            {
              printf("%d,%20s,%d\n",rec.studentId,rec.name,rec.phoneNum);
            }//if
          memset(&lbuf,0,sizeof(lbuf));
          memset(&rec,0,sizeof(rec));
          len = 0;
          len = fread(&lbuf,1,REC_SIZE,fp);
        }//while
    
      return SUCCESS;
    }//dispAllStudentRecs
    
    int addNewStudentRec(FILE *fp,student_t *rec)
    {
      int len;
      student_t trec;
      char lbuf[100];
    
      fseek(fp,0,SEEK_SET);
      while(1)
        {
          len = fread(lbuf,1,REC_SIZE,fp);
          if (len != REC_SIZE)
            {
              break;
            }
          line2rec(lbuf,&trec);
          if(trec.studentId == -1)
            {
              fseek(fp,REC_SIZE * -1,SEEK_CUR);
              fprintf(fp,"%d,%20s,%d\n",rec->studentId,rec->name,rec->phoneNum);
              return SUCCESS;
            }
        }
      fprintf(fp,"%d,%20s,%d\n",rec->studentId,rec->name,rec->phoneNum);
    
      return SUCCESS;
    }

    file student.txt :

    # cat student.txt
    101, Rama,101
    102, Ravi,102


    output :
    -----------

    ./ex9.o
    Enter 1 to display all records
    Enter 2 to add a record
    Enter 3 to delete a record
    Enter 4 to exit

    Enter Option: 1
    before strtok line 2 rec Rama
    after strtok line 2 rec Ramae
    101, Ramae,101
    before strtok line 2 rec Ravi
    after strtok line 2 rec Ravi

    102, Ravi
    ,10

  2. #2
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    First things first: If you're using gcc, always build with at least the -Wall flag. With your code, that should tell you that you have lots of functions implicitly declared, which means you forgot some headers. __fpurge() is nonstandard, so I'm not sure what header you'd need for that; but memset(), exit(), strlen(), and strcpy() are all missing declarations. Once you include stdlib.h and string.h, those warnings will disappear. As a result, you can remove the casts from your strtok() calls which, I presume, were added to silence the compiler.

    The source of your problem might lie in how you're using fread(). fread() will not add a null character to the end of what it reads unless one happened to be present in the file. That means that fread() will not create strings! You must do that yourself by adding the null character—you know where to add it, because fread() tells you how many bytes it read.
    EDIT: I just noticed that while you're not terminating the fread() in addNewStudentRec(), you are in dispAllStudentRecs() which appears to be the source of your problem; so you can probably disregard the above as not pertaining to the issue at hand, although you'll still want to terminate in addNewStudentRec().

    I would also recommend using (void) when declaring functions that take no arguments. () means that a function takes an unspecified number of arguments, so the compiler won't complain if you pass it some.
    Last edited by cas; 11-24-2008 at 12:11 AM. Reason: I'm blind.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You're reading the file using fread(), but writing to the file using fprintf().
    Be consistent!

    fread / fwrite or fprintf / fscanf

    If you do that, then you can get rid of that line2rec thing.
    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.

  4. #4
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147
    Salem,

    Iam folliwng your guidelines and using only fsacnf and fprintf.

    Here i could not able to add the newline character to the file "\n".

    next record always go to the first line it self.

    And i could not display any records , every time it prints as if "No records present"

    While adding the record it updates the data to .txt file only when i come out of the program.

    Here is the program.


    # cat ex9.c
    Code:
    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio_ext.h>
    
    #define SUCCESS 0
    #define DATA_BASE_ERR 1
    #define ID_NOT_FOUND_ERR 2
    
    #define REC_SIZE 30
    
    typedef struct
    {
      int studentId;
      char name[20];
      int phoneNum;
    }student_t;
    
    void strip_newline(char *name);
    void disp_help(void);
    int addNewStudentRec(FILE *fp,student_t *pS);
    int dispAllStudentRecs(FILE *fp);
    
    int main()
    {
      int option = 0;
      student_t nRec;
      FILE *fp;
    
      memset(&nRec,0,sizeof(nRec));
    
      fp = fopen("student.txt","r+");
    
      if (!fp)
        {
          printf("Creating the file \n");
          fp = fopen("student.txt","w+");
          if (!fp)
            {
              printf("Could not create file \n");
              exit(1);
            }
        }
    
      disp_help();
    
      while(1)
        {
          printf("\n Enter Option: ");
          __fpurge(stdin);
          scanf("%d",&option);
          switch(option)
            {
              case 1:
                dispAllStudentRecs(fp);
                break;
            case 2:
              printf("Enter id name and phone \n");
              scanf("%d",&nRec.studentId);
              __fpurge(stdin);
              fgets(nRec.name,20,stdin);
              strip_newline(nRec.name);
              scanf("%d",&nRec.phoneNum);
              if(addNewStudentRec(fp,&nRec) != SUCCESS)
                printf("Record add operation failed \n");
              break;
            case 4:
              printf("Good bye \n");
              return SUCCESS;
            default:
              printf("Invalid option.Use the following \n");
              disp_help();
              break;
            }//switch
        }//while
      return SUCCESS;
    }
    
    
    void strip_newline(char *name)
    {
      int len;
    
      len = strlen(name);
      if (name[len-1] == '\n')
        name[len-1] = 0;
    }
    
    
    void disp_help()
    {
      printf("Enter 1 to display all records \n");
      printf("Enter 2 to add a record \n");
      printf("Enter 3 to delete a record \n");
      printf("Enter 4 to exit \n");
    }
    
    int dispAllStudentRecs(FILE *fp)
    {
      int len;
      student_t rec;
      char lbuf[100];
    
      memset(&rec,0,sizeof(rec));
      memset(&lbuf,0,sizeof(lbuf));
    
      fseek(fp,0,SEEK_SET);
      len = fscanf(fp,"%d,%20s,%d",&rec.studentId,rec.name,&rec.phoneNum);
    
      if (len != REC_SIZE - 1)
        {
          printf("No record to print \n");
          return DATA_BASE_ERR;
        }//if
    
      while(len == REC_SIZE)
        {
         if (rec.studentId != -1)
            {
              printf("%d,%20s,%d\n",rec.studentId,rec.name,rec.phoneNum);
            }//if
          memset(&lbuf,0,sizeof(lbuf));
          memset(&rec,0,sizeof(rec));
          len = 0;
          len = fscanf(fp,"%d,%20s,%d",&rec.studentId,rec.name,&rec.phoneNum);
        }//while
    
      return SUCCESS;
    }//dispAllStudentRecs
    
    int addNewStudentRec(FILE *fp,student_t *rec)
    {
      int len;
      student_t trec;
      char lbuf[100];
      char strRec[100];
    
      fseek(fp,0,SEEK_SET);
      memset(&lbuf,0,sizeof(lbuf));
      memset(&strRec,0,sizeof(strRec));
    
      while(1)
        {
         len = fscanf(fp,"%d,%20s,%d",&trec.studentId,trec.name,&trec.phoneNum);
          if (len != REC_SIZE)
              break;
          if(trec.studentId == -1)
              fseek(fp,REC_SIZE * -1,SEEK_CUR);
        }
        fprintf(fp,"%d,%20s,%d \n",rec->studentId,rec->name,rec->phoneNum);
      return SUCCESS;
    }

    cat student.txt
    -------------------
    101, Rehman,101102, Rashid,102

  5. #5
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    I think you have purge and scanf backwards here:
    Code:
    case 2:
              printf("Enter id name and phone \n");
              scanf("&#37;d",&nRec.studentId);
              __fpurge(stdin);
    Try flushing your fp output stream after each write.

    (And, you never close your fp output file. Shame, shame.)
    Mainframe assembler programmer by trade. C coder when I can.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Dino View Post
    I think you have purge and scanf backwards here:
    Code:
    case 2:
              printf("Enter id name and phone \n");
              scanf("%d",&nRec.studentId);
              __fpurge(stdin);
    Try flushing your fp output stream after each write.

    (And, you never close your fp output file. Shame, shame.)
    I'm pretty sure the __fpurge() is a "clean up anything left behind by scanf" rather than a flush operation.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    Quote Originally Posted by matsp View Post
    I'm pretty sure the __fpurge() is a "clean up anything left behind by scanf" rather than a flush operation.

    --
    Mats
    OK, I'll buy that. Then this code is backwards!!

    Code:
     while(1)
        {
          printf("\n Enter Option: ");
          __fpurge(stdin);
          scanf("&#37;d",&option);
    Mainframe assembler programmer by trade. C coder when I can.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Dino View Post
    OK, I'll buy that. Then this code is backwards!!

    Code:
     while(1)
        {
          printf("\n Enter Option: ");
          __fpurge(stdin);
          scanf("%d",&option);
    Maybe, but:
    Code:
             fgets(nRec.name,20,stdin);
    is the line immediately after the fpurge you posted about earlier. And fgets will "fail" if you leave the newline behind, like scanf does.

    In the code reading the option, I presume it's just clearing out any rubbish left behind by any other input (e.g. someone entered "a" as the answer for option).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You also need to read the manual to find out what fscanf returns.
    It isn't what you think.
    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.

  10. #10
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147
    salem & dino thanks for your suggestions,

    now iam taking care of fscanf returntype , using fflush onthe file stream to stroe the records and closeing the file stream while exiting from the program.

    Here i face a one problem with fscanf like below.

    My record format is "101, Jhon,101"
    Now when i do the fscnaf . like

    fscanf(fp,"%d,%s,%d",&rec.studentId,rec.name,&rec. phoneNum);

    Here it returns the number of items it read as only 2 , i.e rec.studenId = 101
    and rec.name = "Jhone,101".
    So no phoneNum, i feel even phone number is considered as string and its taking into rec.name argument.

    Do i need to change the record format like "studentId,phoneNum,name" or else do i have any option of getting the arguments correctly .

    thanks guys

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by vlrk View Post
    salem & dino thanks for your suggestions,

    now iam taking care of fscanf returntype , using fflush onthe file stream to stroe the records and closeing the file stream while exiting from the program.

    Here i face a one problem with fscanf like below.

    My record format is "101, Jhon,101"
    Now when i do the fscnaf . like

    fscanf(fp,"%d,%s,%d",&rec.studentId,rec.name,&rec. phoneNum);

    Here it returns the number of items it read as only 2 , i.e rec.studenId = 101
    and rec.name = "Jhone,101".
    So no phoneNum, i feel even phone number is considered as string and its taking into rec.name argument.

    Do i need to change the record format like "studentId,phoneNum,name" or else do i have any option of getting the arguments correctly .

    thanks guys
    If I'm reading your question correctly, the answer is "just because you put a comma in the format string doesn't mean that %s is going to stop at a comma -- it will stop at a space (or tab, or enter-key) because that's how %s works". If you want to really stop at a comma, you can either (1) get the whole line with fgets and parse it yourself or (2) use a scanset (like %[^,]) to read up to a comma.

  12. #12
    Registered User
    Join Date
    Mar 2008
    Location
    India
    Posts
    147
    scanset worked for me now my fscanf looks like below

    Code:
    fscanf(fp,"%d,%[^,],%d",&trec.studentId,trec.name,&trec.phoneNum);
    thans tabstop

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 26
    Last Post: 07-05-2010, 10:43 AM
  2. Storing and accessing data from and to .txt files.
    By Glauber in forum C++ Programming
    Replies: 9
    Last Post: 05-27-2008, 02:59 PM
  3. question: i/o data form .txt or .xls files ??
    By camelman in forum C++ Programming
    Replies: 21
    Last Post: 11-17-2007, 03:48 PM
  4. Using c++ standards
    By subdene in forum C++ Programming
    Replies: 4
    Last Post: 06-06-2002, 09:15 AM