You are here:

C/Reading a specific line in a textfile and later updating it.

Advertisement


Question
QUESTION: Hello Zlatko,

I have a textfile containing the following information:

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 so far:

#include<stdio.h>

int main()
{
  int numofbees = 0;
  float price = 5;
  char query;

  printf("How many bees would you like to purchase?\n");
     if (!scanf("%u", &numofbees)) {
        printf("Invalid amount, please try again.\n");
  }
     else {
  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;
  }

My problem is how shall I read the textfile and check if there is enough 'Money'. If there is enough the transaction is completed and 'Money' and 'Number of Bees' is updated, while if there is not, the output 'Transaction Cancelled' is printed.

To summarize I would like to know how to read the specific lines, use them and later update them.

Thanks :)

ANSWER: Hi Stephanie.

I'll show you how to read and write the file in C, and I'll let you work on the program calculation logic. Show me what you come up with and I'll help you more.

The program below handles one line in the bees file. It reads the number of bees, does some calculation, and writes it back. The comments throughout the program explain what is happening. Ask questions about anything you don't understand.

Best regards
Zlatko

#include<stdio.h>

/* Notice how we can use a define to hold the format of the file
This prevents accidental misspellings in the program
*/
#define LINE_1 "Total number of Bees: %d"
#define FILENAME "bees.txt"

int main()
{
   int numofbees = 0;
   FILE* file;
   char line[256];

   /* First you need to open the file, always check for failure */
   file = fopen(FILENAME, "r");
   if (file == NULL)
   {
       printf("Cannot open file %s for reading\n", FILENAME);
       return 0;
   }

   /* You can use fscanf to read from the file as long as your format
   line matches the line in your file. Although the actual count of spaces
   between words does not matter, at least one space is necessary between
   words.

   Always check the fscanf result against the numeber of expected conversions.
   */
   if (fscanf(file, LINE_1, &numofbees) != 1)
   {
       printf("Error reading number of bees\n");
       return 0;
   }
   else
   {
       printf("num of bees read in as %d\n", numofbees);
   }

   /* Now you do some math */
   numofbees = numofbees * 2;
   printf("Changed numofbees to %d\n", numofbees);


   /* Write the file back. The easiest way is to close the file, and re-open it for
   writing
   */
   fclose(file);

   file = fopen(FILENAME, "w");
   if (file == NULL)
   {
       printf("Cannot open file %s for writing\n", FILENAME);
       return 0;
   }

   fprintf(file, LINE_1, numofbees);
   fclose(file);
 
   return 0;
}

---------- FOLLOW-UP ----------

QUESTION: Hello again,

Thanks for the swift reply :). I have managed to understand your coding and tried to implement it into my program, however I have encountered a number of errors. Below is what I did:

#include<stdio.h>

#define LINE_1 "Total Number of Bees: %d"
#define LINE_2 "Total Number of Infected Bees: %d"
#define LINE_3 "Total Amount of Money: %d"
#define LINE_4 "Total Amount of Honey Jars: %d"
#define LINE_5 "Total Amount of Beeswax: %d"

#define FILENAME "Inventory.txt"

int main()
{
  int numofbees, Numofbees = 0;
  int Money;
  char query;
  float price = 5;

  FILE* file;
   char line[256];

  /*Asks the user how much bees he would like to buy.*/
  printf("How many bees would you like to purchase?\n");
  if (!scanf("%u", &numofbees)) {
     printf("Invalid amount, please try again.\n"); /*If a letter is entered this will print out.*/
  }

  else {
     printf("That will be $%f, confirm? (Y/N)\n", price*numofbees); /*Asks the user if he would like to confirm his purchase.*/
     scanf(" %c", &query);
  }

  if(query == 'y'|| query == 'Y') { /*If he enters Y/y */

     file = fopen(FILENAME, "r");   /*Opens the file*/
     if (file == NULL)
     {
         printf("Cannot open file %s for reading\n", FILENAME);
         getchar();
         getchar();
         return 0;
        }

      if (fscanf(file, LINE_1, &Numofbees) != 1) /*Checks for the number of bees and the amount of money he has.*/
         (fscanf(file, LINE_3, &Money) != 1);
        {
         printf("Error reading numbers.\n");
         getchar();
         getchar();
         return 0;
        }

        else if(price*numofbees < Money){      /*If he has more money than the price of the total sum of bees, the transaction is completed.*/
         printf("Transaction Completed.\n");
        }

        else {
        printf("Insufficient Amount of Funds.\n"); /*If not this will print out.*/
        printf("Transaction Cancelled.\n");
        }
  }
  else {
     printf("Transaction cancelled."); /*Else if he enters N/n the transaction will be cancelled*/
  }

  getchar();
  getchar();
  return 0;
}

And these are the errors:

Maybe2.c: In function 'int main()':
Maybe2.c:52:6: error: expected '}' before 'else'
Maybe2.c: At global scope:
Maybe2.c:61:2: error: expected unqualified-id before 'else'
Maybe2.c:65:11: error: expected constructor, destructor, or type conversion before ';' token
Maybe2.c:66:11: error: expected constructor, destructor, or type conversion before ';' token
Maybe2.c:67:2: error: expected unqualified-id before 'return'
Maybe2.c:68:1: error: expected declaration before '}' token

Tool completed with exit code 1

I am looking forward to receiving your feedback and thank you for your time.

:)

ANSWER: Hi Stephanie

At this part:

if (fscanf(file, LINE_1, &Numofbees) != 1) /*Checks for the number of bees and the amount of money he has.*/
(fscanf(file, LINE_3, &Money) != 1);
{

You have misplaced your brackets. You have the "if" terminated by a closing parenthesis, then the second fscanf is part of the consequent of the if, and not part of the if itself. That is why the compiler is confused by the else farther below.

But there is another problem, the inventory file must be read in order. You cannot skip around from line 1 to line 3, so I suggest you read all things from the file at when the file is opened. Also, you will have to add the newline character "\n", to the LINE definitions so that the scanf reads past the newline in each case.

Notice the newline (\n) character in each of the definitions below:

#define LINE_1 "Total Number of Bees: %d\n"
#define LINE_2 "Total Number of Infected Bees: %d\n"
#define LINE_3 "Total Amount of Money: %d\n"
#define LINE_4 "Total Amount of Honey Jars: %d\n"
#define LINE_5 "Total Amount of Beeswax: %d\n"



I don't know the full logic of your program, so I'm putting all the inventory data into new variables, each prefixed with Inv_. You can use a struct to group them together if you know how.

   int Inv_numofbees;
   int Inv_infectedbees;
   double Inv_Money;
   int Inv_Jars;
   int Inv_wax;

Below is your whole program with my changes. Now you can add your "business logic"


#include<stdio.h>

#define LINE_1 "Total Number of Bees: %d\n"
#define LINE_2 "Total Number of Infected Bees: %d\n"
#define LINE_3 "Total Amount of Money: %d\n"
#define LINE_4 "Total Amount of Honey Jars: %d\n"
#define LINE_5 "Total Amount of Beeswax: %d\n"

#define FILENAME "Inventory.txt"

int main()
{

   int Inv_NumofBees;
   int Inv_InfectedBees;
   int Inv_Money;
   int Inv_HoneyJars;
   int Inv_Wax;


   int numofbees;
   char query;
   float price = 5;

   FILE* file;

   /*Asks the user how much bees he would like to buy.*/
   printf("How many bees would you like to purchase?\n");
   if (!scanf("%u", &numofbees)) {
       printf("Invalid amount, please try again.\n"); /*If a letter is entered this will print out.*/
   }

   else {
       printf("That will be $%f, confirm? (Y/N)\n", price*numofbees); /*Asks the user if he would like to confirm his purchase.*/
       scanf(" %c", &query);
   }

   if(query == 'y'|| query == 'Y') { /*If he enters Y/y */

       file = fopen(FILENAME, "r"); /*Opens the file*/
       if (file == NULL)
       {
         printf("Cannot open file %s for reading\n", FILENAME);
         getchar();
         getchar();
         return 0;
       }

       if (
         fscanf(file, LINE_1, &Inv_NumofBees) != 1
         ||
         fscanf(file, LINE_2, &Inv_InfectedBees) != 1
         ||
         fscanf(file, LINE_3, &Inv_Money) != 1
         ||
         fscanf(file, LINE_4, &Inv_HoneyJars) != 1
         ||
         fscanf(file, LINE_5, &Inv_Wax) != 1
         )
       {
         printf("Error reading numbers.\n");
         getchar();
         getchar();
         return 0;
       }

       else if(price*numofbees < Inv_Money){ /*If he has more money than the price of the total sum of bees, the transaction is completed.*/
         printf("Transaction Completed.\n");
       }

       else {
         printf("Insufficient Amount of Funds.\n"); /*If not this will print out.*/
         printf("Transaction Cancelled.\n");
       }
   }
   else {
       printf("Transaction cancelled."); /*Else if he enters N/n the transaction will be cancelled*/
   }

   getchar();
   getchar();
   return 0;
}


---------- FOLLOW-UP ----------

QUESTION: Hello,

Your coding works perfectly, thank you. Now I only have a tiny problem to solve. When I try to update the Inventory text file, 'Money' is printed as 0. Any idea what is causing this.

Below is the coding you gave me with an addition to update the textfile:


#include<stdio.h>

#define LINE_1 "Total Number of Bees: %d\n"
#define LINE_2 "Total Number of Infected Bees: %d\n"
#define LINE_3 "Total Amount of Money: %d\n"
#define LINE_4 "Total Amount of Honey Jars: %d\n"
#define LINE_5 "Total Amount of Beeswax: %d\n"

#define FILENAME "Inventory.txt"

int main()
{

  int Inv_NumofBees;
  int Inv_InfectedBees;
  int Inv_Money;
  int Inv_HoneyJars;
  int Inv_Wax;

  int numofbees;
  char query;
  float price = 5;

  FILE* file;

  /*Asks the user how much bees he would like to buy.*/
  printf("How many bees would you like to purchase?\n");
  if (!scanf("%u", &numofbees)) {
      printf("Invalid amount, please try again.\n"); /*If a letter is entered this will print out.*/
  }

  else {
      printf("That will be $%f, confirm? (Y/N)\n", price*numofbees); /*Asks the user if he would like to confirm his purchase.*/
      scanf(" %c", &query);
  }

  if(query == 'y'|| query == 'Y') { /*If he enters Y/y */

      file = fopen(FILENAME, "r"); /*Opens the file*/
      if (file == NULL)
      {
        printf("Cannot open file %s for reading\n", FILENAME);
        getchar();
        getchar();
        return 0;
      }

      if (
        fscanf(file, LINE_1, &Inv_NumofBees) != 1
        ||
        fscanf(file, LINE_2, &Inv_InfectedBees) != 1
        ||
        fscanf(file, LINE_3, &Inv_Money) != 1
        ||
        fscanf(file, LINE_4, &Inv_HoneyJars) != 1
        ||
        fscanf(file, LINE_5, &Inv_Wax) != 1
        )
      {
        printf("Error reading numbers.\n");
        getchar();
        getchar();
        return 0;
      }

      else if(price*numofbees <= Inv_Money){ /*If he has more money than the price of the total sum of bees, the transaction is completed.*/
        printf("Transaction Completed.\n");
      }

      else {
        printf("Insufficient Amount of Funds.\n"); /*If not this will print out.*/
        printf("Transaction Cancelled.\n");
      }
  }
  else {
      printf("Transaction cancelled."); /*Else if he enters N/n the transaction will be cancelled*/
  }

     fclose(file);

     file = fopen(FILENAME, "w");
     if (file == NULL)
     {
         printf("Cannot open file %s for writing\n", FILENAME);
         return 0;
     }

     fprintf(file, LINE_1, Inv_NumofBees+numofbees);
     fprintf(file, LINE_2, Inv_InfectedBees);
     fprintf(file, LINE_3, Inv_Money-price*numofbees);
     fprintf(file, LINE_4, Inv_HoneyJars);
     fprintf(file, LINE_5, Inv_Wax);
     fclose(file);

     return 0;
}

Answer
Hi Stephane

In the line which prints to the file you have:
Inv_Money-price*numofbees

price is a float, so the entire expression gets promoted to a float, but the formatting string in LINE_3 specifies %d. You should change it to %f. That will make more sense since money is not just integer.

Also, you should change
int Inv_Money;
to
float Inv_Money;

to match the format specifier.

Finally, consider that you do not want to always write to the file. In particular, if the transaction is cancelled, or there are insufficient funds, you should not write back to the file.

Best regards
Zlatko

C

All Answers


Answers by Expert:


Ask Experts

Volunteer


Zlatko

Expertise

No longer taking questions.

Experience

No longer taking questions.

Education/Credentials
No longer taking questions.

©2012 About.com, a part of The New York Times Company. All rights reserved.