Thread: Opening, Reading and Updating a text file.

  1. #1
    Registered User
    Join Date
    Dec 2011
    Posts
    20

    Opening, Reading and Updating a text file.

    Hi guys,

    I have a slight problem on how can I read from a text file in order to use the stored data. Later on if a purchase is made I would like the 'Amount of Money' which is stored in the text file to be updated together with the 'Number of Bees'.

    This is what is stored in the text file:
    Total number of Bees: 15
    Total number of Infected Bees: 5
    Total amount of Money: 1500
    Total amount of Honey Jars: 65
    Total amount of Beeswax: 0

    Below is the program I have written which requires the above data:

    Code:
    #include<stdio.h>
    #include <iostream>
    
    
    int main()
    {
        int numofbees;
        float price = 5;
        char query;
    
    
        printf("How many bees would you like to purchase?\n");
            scanf("%d", &numofbees);
        printf("That will be $%f, confirm? (Y/N)\n", price*numofbees);
            scanf(" %c", &query);
    
    
            if(query == 'y'|| query == 'Y') {
                printf("Transaction completed.");
        }
            else {
                printf("Transaction cancelled.");
        }
            getchar();
            getchar();
            return 0;
    }
    The following is a piece of code I have written in order to open the file:

    Code:
    #include <stdio.h>
    #define MAX 20
    char string[20];
    
    
    int main()
    {
        FILE *f;
        int x;
    
        f=fopen("Inventory.txt","r");
        if (!f)
        {   printf("Couldn't open file. Please try again.\n");
            return 1;
        }
        while(fgets(string, 20, f))
        {
            printf("%s", string);
        }
    
    
        fclose(f);
        getchar();
        getchar();
        return 0;
    }
    Overall, my question is how can I read from a text file in order to use the data and later on to update the text file itself.

    Any help or tips would be greatly appreciated.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    First: don't use floats for money -- money is fixed precision, and errors can occur. Eg, imagine this is supposed to be an account balance accumulating dimes:

    Code:
    #include <stdio.h>
    
    int main() {
            float i;
            for (i=0.0f; i<20; i+=0.1f) {
                    printf("%f\n",i);
            }
            return 0;
    }
    Now compile and run it to see what actually happens, because it isn't what you think. Floats can only accurately reflect inverse power of two numbers (0.5, 0.25, 0.125, 0.0625, ...). For money, use cents as an integer and when you want to report in a human friendly way:

    Code:
    	int cents = 507;
    	printf("$%d.%02d\n", cents/100, cents%100);
    Next, here's another common newbie misunderstanding: you want to keep your static arrays as small as possible. Sort of true, but this:

    Code:
    char string[20];
    is ridiculously small. Unless you are programming an old digital watch, it's fine to use a KB (1024) or something here even if you aren't going to use most of it. Operating systems dole out memory in "page" size chunks anyway (usually, 4096 bytes) so asking for less than that won't save you anything. This is even more true if the variable is a local one (which that does not need to be global -- you should try and avoid globals as much as possible), because the "stack" in which they are put already exists and is mostly empty because it is relatively huge (4-8 megabytes).

    WRT your question, you need to parse the text you read from the file. There's lots of ways to do that. Try replacing the printf("%s", string) in the file read with:

    Code:
    // outside the while loop
    char field[256]; //plenty
    int val, count = 1;
    //inside the while loop
    sscanf(string, "%[^:]:%d", field, val);
    printf("#%d '%s' has a value of %d\n", count, field, val);
    count++;
    Hopefully, it's not too hard to see how if the file is always in the same order, you can assign those values to more specific variables by keeping a count of which line you are on in the loop. If it isn't, you may want to use a more robust method with strcmp() on the field and if/else.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Dec 2011
    Posts
    20
    I understood most of what you said, except the use of the code that is at the bottom. It outputs the following "#1 'Total number of Bee' has a value of 3023424 #1 's' has a value of 3023424" and so on for the rest giving the same value throughout.

    Are there any links instead how I can store the data found in the inventory so it can be used and later updated?

    Thanks

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    If you are working with multiple customers you will be wise to stop using text files and get yourself set up with "random access" records based fileing... In that scenario you read and write structs (records) in a binary file and you access them by a record number.

    Based on your information, the data struct will probably look something like...
    Code:
    struct t_CUSTDATA
      {
         char Name[32];
         char Street[64];
         char City[32];
         char PCode[10];
         char Phone[16];
         int    BeesTotal;
         int    BeesInfected;
         int    MoneysPaid;
         int    JarsTotal;
         int    BeesWax; 
      } CUSTOMER;
    One customer per record... as many records in the file as you need.

    Here's an demonstration example of a simple inventory program you can copy and compile to play with...

    Take particular note of how the file is read and written. From that insight you should be able to devlop a proper application for your task.

    Code:
    //random access file demo
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    #include <ctype.h>
    #include <string.h>
    
    #define FNAME "random.dat"
    
    // test data struct
    struct t_Record
      { int number;
        char word[16]; }
      Record;
    
    
    
    ///////////////////////////////////////////////////////
    // Random Access File Handlers
    //
    
    // open or create the file
    FILE *FileOpen(char* Filename)
      { FILE* pFile;
        pFile = fopen(Filename,"rb+");
        if (!pFile)
          pFile = fopen(Filename,"wb+");
        return pFile; }
    
    
    // Write a record to the file
    int WriteRecord(FILE *File, int RecNum)
      { if( fseek(File, RecNum * sizeof(Record), SEEK_SET) == 0 )
          if ( fwrite(&Record,sizeof(Record),1,File) )
            return 1;
        return 0; }
    
    
    // read a record from the file
    int ReadRecord(FILE *File, int RecNum)
      { if( fseek(File, RecNum * sizeof(Record), SEEK_SET) == 0 )
          if ( fread(&Record,sizeof(Record),1,File) )
            return 1;
        return 0; }
    
    
    int AddRecord(FILE *File)
      { fseek(File,0,SEEK_END);
        fwrite(&Record,sizeof(Record),1,File);
        return (ftell(File) / sizeof(Record)) - 1; }
    
    
    
    //////////////////////////////////////////////////////////////
    // View a Record
    //
    
    int ViewRecord (FILE *File, int RecNum)
      { if (! ReadRecord(File,RecNum))
          { printf("Invalid record\n"); 
            return -1; }
        printf("-----\n");
        printf("Record        : %d\n",RecNum);
        printf("Number Value  : %d\n",Record.number);
        printf("Word Value    : %s\n",Record.word);
        printf("-----\n");  
        return RecNum; }
    
    
    
    //////////////////////////////////////////////////////////////
    // Add a new record
    //
    
    int AddNewData(FILE *File)
      { memset(&Record,0,sizeof(Record));
        printf("\nEnter a number : ");
        scanf("%d", &Record.number);
        printf("Enter a word : ");
        scanf(" %s",Record.word);
        return AddRecord(File); }
    
    
    
    //////////////////////////////////////////////////////////////
    // Edit a record
    //
    
    int EditRecord(FILE *File, int RecNum)
      { if (! ReadRecord(File,RecNum))
          { printf("Invalid record\n");  
            return -1; }
        printf("\n-----\n");
        printf("Record        : %d\n",RecNum);
        printf("Number Value  : %d\n",Record.number);
        printf("Word Value    : %s\n",Record.word);
        printf("-----\n");  
        
        do
          { while(getchar() != '\n');
            printf("Change Values: Number, Word or Save (N, W or S) ? ");
            switch (toupper(getchar()))
              { case 'N' :
                  printf("\nEnter new number : ");
                  scanf("%d",&Record.number);
                  break;
                case 'W' : 
                  printf("Enter new word : ");
                  scanf(" %15s", Record.word);
                  break;
                case 'S' :
                  if (WriteRecord(File,RecNum))
                    printf("\nRecord #%d updated\n",RecNum);
                  return RecNum; } }
        while(1);
        return -1; }
    
    
    ////////////////////////////////////////////////////////////////
    // List records
    // 
    
    void ListRecords(FILE *File )
      { int i = 0;
        printf("\nRecord     Number\tWord\n\n");
        while (ReadRecord(File,i))
          { printf("%3d%16d\t%s\n",i,Record.number,Record.word); 
            i++; }
        printf("\n\n"); }
    
    
    
    ////////////////////////////////////////////////////////
    // this is for demonstration purposes only
    // you would not do this in a real program
    void InitFile(FILE* File)
     { int x, y;
       memset(&Record,sizeof(Record),0);
       for (x = 0; x < 10; x++)
          { Record.number = rand();
            for (y = 0; y < ((Record.number % 15) + 1); y++)
              Record.word[y] = (rand() % 26) + 'a';
            Record.word[y] = 0;
            if (! WriteRecord(File,x))
              printf("Oh drat!");  } }
     
    
    
    //////////////////////////////////////////////////////////
    // program mains
    //
    int main (void)
      { int Rec = 0; // record number
        FILE *File;
    
        srand(time(NULL));
    
        File = FileOpen(FNAME); 
        if (!File)
          { printf("Curses foiled again!\n\n");
            exit(-1); }
    
        printf("Random Access File Demonstration\n\n");
     
        do
          { printf("Menu : Dummy, Add, Edit, View, List, Quit (D, A, E, V, L or Q) : ");
            switch(toupper(getchar()))
              { case 'D' :
                  printf("Creating dummy file of 10 entries\n");
                  InitFile(File);
                  break;
                case 'A' :
                  Rec = AddNewData(File);
                  printf("Record #%d Added\n\n", Rec);
                  break;              
                case 'E' :
                  printf("\nRecord number (-1 Cancels): ");
                  scanf("%d",&Rec);
                  if (Rec > -1)
                    EditRecord(File,Rec);
                  break;
                case 'V' :
                  printf("\nRecord number (-1 Cancels): ");
                  scanf("%d",&Rec);
                  if (Rec > -1)
                    ViewRecord(File,Rec);
                  break;
                case 'L' :
                  ListRecords(File);
                  break;
                case 'Q' :
                  fclose(File);
                  return 0; } 
                  
             while(getchar() != '\n'); }
        while (1); 
        return 0; }
    Last edited by CommonTater; 12-21-2011 at 01:59 PM.

  5. #5
    Registered User
    Join Date
    Dec 2011
    Posts
    20
    I got the following errors for the above code, any ideas?

    Random.c: In function 'int main()':
    Random.c:158:26: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by bonett09 View Post
    I got the following errors for the above code, any ideas?

    Random.c: In function 'int main()':
    Random.c:158:26: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
    Is that with respect to my code?
    It compiles with no warnings or errors on Pelles C...

    It appears not to like the string constant in line 158 (according to the warning)... but that's pretty standard practice in C.
    I don't know what you're compiling it on, but if it is a compiler with C and C++ capabilities... make sure it's in C only mode.

    Also note... that's only a warning not a compiler error. If the program works well enough for you to see how it works, you can probably ignore it. If you were working on production code, that'd be a different story.
    Last edited by CommonTater; 12-21-2011 at 04:33 PM.

  7. #7
    Registered User
    Join Date
    Dec 2011
    Posts
    20
    Yes, and I'm using Textpad.

    I replaced the filename with mine, but to no avail. Any other programs you may suggest?

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by bonett09 View Post
    I understood most of what you said, except the use of the code that is at the bottom. It outputs the following "#1 'Total number of Bee' has a value of 3023424 #1 's' has a value of 3023424" and so on for the rest giving the same value throughout.
    You did something wrong then, because if you put that code inside a while loop, count must be incremented and you would get #1, #2, #3, etc.

    You should post your code when you have a problem, rather than just describing it.

    Are there any links instead how I can store the data found in the inventory so it can be used and later updated?
    If you can't follow what's in this thread, I can't imagine there is anything that is going to help. Have you tried google?

    I got the following errors for the above code, any ideas?

    Random.c: In function 'int main()':
    Random.c:158:26: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
    That's not an error, that's a warning, and a very minor one at that. The code still compiled and would have ran.

    The warning could be eliminated with a (char*) cast.

    Yes, and I'm using Textpad.
    Textpad is not your compiler. It looks to me like mingw is your compiler, but I'm not sure.

    AFAICT Textpad does not have syntax highlighting. That is just stupid. At least install Notepad++ or something.

    Notepad++ Home

    Any other programs you may suggest?
    It's a waste of time throwing code if you keep giving up. These are not our mistakes, they are yours. That is excusable and understandable because you are very new at it, but you will have to accept that, humble yourself a little, and try harder to solve your problems.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User andrew89's Avatar
    Join Date
    Dec 2011
    Location
    Indiana, United States
    Posts
    80
    I suggest using SciTE or Scintilla based Text Editor and The GNU Compiler Collection

    I'm running nano v2.2.2 and GCC v4.4.3 and it compiled without error or warning.

    @CommonTater, some compilers won't compile even if it's a warning; though you can force it to compile with a flag when you compile using the terminal--most of the time anyway.

    @MK27, as far as your comment about TextPad not having syntax highlighting, it does.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Opening Text File
    By panda3 in forum C++ Programming
    Replies: 3
    Last Post: 05-10-2011, 10:43 AM
  2. Opening a text file
    By bwisdom in forum C++ Programming
    Replies: 6
    Last Post: 04-28-2008, 09:17 AM
  3. Opening and reading text files
    By pete212 in forum C Programming
    Replies: 3
    Last Post: 04-22-2008, 10:16 AM
  4. Reading and then updating a file
    By kopite in forum C Programming
    Replies: 3
    Last Post: 12-02-2003, 04:15 PM
  5. Opening text file
    By zdude in forum C Programming
    Replies: 3
    Last Post: 10-31-2002, 08:23 AM