GIDForums  

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 15-Mar-2005, 11:48
blitzy blitzy is offline
New Member
 
Join Date: Mar 2005
Posts: 3
blitzy is on a distinguished road
Exclamation

Need help reading data from files


I've been trying to fix this problem for the past several hours but it just gets worse everytime I try.

The program is supposed to read data in from the file "Snow.data" which contains data in this format:
Code:
603 4 C 203 G 101 N 25 O 19 538 2 C 433 G 399 759 5 C 287 G 328 L 87 N 43 O 28 321 4 C 199 G 280 N 25 O 18

One part of the assignment requires a switch statement to convert the character values (C, G, L, N, O) to a real description (cherry, grape, lime, coconut, orange) and a function to read in the location number and number of different flavors sold at the location (#'s on first line).

My switch statement works and I'm able to read in the correction location ID. However, the program does not print the correct flavors with the locations. The data printed overflows from the next location.

Sample Output:
Code:
Chilly Sno-Cones, Inc. DATE: March 15, 2005 Weekly Sales Report By Location LOCATION: 603 Cherry COUNT: 203 TOTAL SALES $ 0.00 Grape COUNT: 101 TOTAL SALES $ 0.00 Coconut COUNT: 25 TOTAL SALES $ 0.00 Orange COUNT: 19 TOTAL SALES $ 0.00 ----------- LOCATION: 538 Cherry COUNT: 433 TOTAL SALES $ 0.00 Grape COUNT: 399 TOTAL SALES $ 0.00 Cherry COUNT: 287 TOTAL SALES $ 0.00 Grape COUNT: 328 TOTAL SALES $ 0.00 ----------- LOCATION: 759 Lime COUNT: 87 TOTAL SALES $ 0.00 Coconut COUNT: 43 TOTAL SALES $ 0.00 Orange COUNT: 28 TOTAL SALES $ 0.00 Cherry COUNT: 199 TOTAL SALES $ 0.00 ----------- LOCATION: 321 Grape COUNT: 280 TOTAL SALES $ 0.00 Coconut COUNT: 25 TOTAL SALES $ 0.00 Orange COUNT: 18 TOTAL SALES $ 0.00 Grape COUNT: 180 TOTAL SALES $ 0.00

Here's my C coding:
CPP / C++ / C Code:
int main (void)
{
   FILE *fpSnow;    /* File pointer */
   FILE *fpReport;  /* File pointer */
   int locID;       /* Location ID */
   int numFlavors;  /* Number of flavors */
   char code; 	    /* Snow cone flavor code */
   double numSold;  /* # of cones sold */
   double totSales; /* Total Sales by flavor */
   double finSales; /* Total sales per location */
   int countTypes;  /* Counter for flavor types */
   double sales;    /* total sales */
   double countAvg; /* average accumulator */

   /* Check opened files for NULL */
   if ((fpSnow = fopen("Snow.data", "r")) == NULL)
	printf("\nERROR opening Snow.data\n");
   else if ((fpReport = fopen("Report.out", "w")) == NULL)
	printf("\nCannot open Report.out\n");
   else
   {
      printDate(fpReport);

      getData(fpSnow, &locID, &numFlavors, &code, &numSold);

      while (!feof(fpSnow))
      {
        fprintf(fpReport, "LOCATION: %d\n", locID);
	for (countTypes=0; countTypes<=numFlavors; countTypes++)
	{
	   PrintTotalsByFlavor(fpReport, code, numSold, totSales);   
	   getData(fpSnow, &locID, &numFlavors, &code, &numSold);
	}
	printLocSales(fpReport, finSales);
      } /* end of while loop */
   } /* end of else loop */

   /* Closes files opened */
   fclose(fpReport);
   fclose(fpSnow);

   return 0;

}  /* End of main */

int getData(FILE *fpSnow, int *locID, int *numFlavors, char *code, 
double *numSold)
{
   int locale;     /* Stores data read */
   int saleInfo;   /* Stores data read */
   double sales;  /* total sales */

   locale = fscanf(fpSnow, "%d %d", locID, numFlavors);
   saleInfo = fscanf(fpSnow, "%c%d", code, numSold);

//   sales = 1.75 * (*numSold);

   return;

}  /* End of getData */

void PrintTotalsByFlavor(FILE *fpReport, char code, double numSold, double 
totSales)
{
   /* Switch statement for flavors */
   switch (code)
   {
     	case 'C': 
		  fprintf(fpReport, "\tCherry\t");
		  fprintf(fpReport, "COUNT: %5d\t", numSold);
		  fprintf(fpReport, "TOTAL SALES $ %10.2f\n", totSales);
		  break;
     	case 'G': 
		  fprintf(fpReport, "\tGrape\t");
		  fprintf(fpReport, "COUNT: %5d\t", numSold);
		  fprintf(fpReport, "TOTAL SALES $ %10.2f\n", totSales);
		  break;
     	case 'L': 
		  fprintf(fpReport, "\tLime\t");
		  fprintf(fpReport, "COUNT: %5d\t", numSold);
		  fprintf(fpReport, "TOTAL SALES $ %10.2f\n", totSales);
		  break;
	case 'N': 
		  fprintf(fpReport, "\tCoconut\t");
		  fprintf(fpReport, "COUNT: %5d\t", numSold);
		  fprintf(fpReport, "TOTAL SALES $ %10.2f\n", totSales);
		  break;
	case 'O': 
		  fprintf(fpReport, "\tOrange\t");
		  fprintf(fpReport, "COUNT: %5d\t", numSold);
		  fprintf(fpReport, "TOTAL SALES $ %10.2f\n", totSales);
		  break;
   } /* end of switch statement */
	
} /* End of PrintTotalsByFlavor */

Can someone please help me? I'm at my wit's end!
Last edited by LuciWiz : 15-Mar-2005 at 13:59. Reason: Please insert your C code between [c] & [/c] tags
  #2  
Old 15-Mar-2005, 13:00
Dr. Evil Dr. Evil is offline
Member
 
Join Date: Oct 2004
Location: Netherlands
Posts: 120
Dr. Evil will become famous soon enough
Here, this works for me. I think one of your main problems is that I don't think the scanf() family of functions reads along a string/file like one would with fgets() or fread(), but rather scans the from the start each time. My solution, a not so neat one I might add, is to create a function to crawl along the string and pick up a char and an int after it, ignoring all whitespace. There were also a few other miscellaneous bugs which I noticed, and there might be a few more that I missed, but this works for now (at least, I think it does).

CPP / C++ / C Code:
#include <stdio.h>

#define TMP_SIZE 256

#define IS_SPACE(c) ((c == 32) || ((c >= 9) && (c <= 13)))
#define IS_NUM(c) ((c >= 48) && (c <= 57))

void PrintTotalsByFlavor(FILE *fpReport, char code, double numSold, double totSales)
{
	char ok = 0;
   //You didn't need to repeatedly put those other fprintf()s, just put it at the bottom
   /* Switch statement for flavors */
   switch (code)
   {
     case 'C': 
      fprintf(fpReport, "\tCherry\t");
      ok = 1;
      break;
       case 'G': 
      fprintf(fpReport, "\tGrape\t");
       ok = 1;
      break;
       case 'L': 
      fprintf(fpReport, "\tLime\t");
       ok = 1;
      break;
  case 'N': 
      fprintf(fpReport, "\tCoconut\t");
      ok = 1;
      break;
  case 'O': 
      fprintf(fpReport, "\tOrange\t");
      ok = 1;
      break;
   } /* end of switch statement */
   
   if(ok)
   {
     fprintf(fpReport, "COUNT: %5d\t", numSold);
     fprintf(fpReport, "TOTAL SALES $ %10.2f\n", totSales);
   }
  
} /* End of PrintTotalsByFlavor */

//gets a char then an int, ignores whitespace, not very pretty
void getcharint(char string[], int *index, char *out1, int *out2)
{
	char tmp[20];
	int my_index, i, j;
	
	my_index = *index;
	for(i=my_index; IS_SPACE(string[i]); i++) ;
	*out1 = string[i];
	i++;
	my_index = i;
	
	//printf("index: %d\n", my_index);
	for(i=my_index; !IS_NUM(string[i]); i++) ;
	my_index = i;
	for(i=my_index, j=0; IS_NUM(string[i]); i++, j++) tmp[j] = string[i];
	tmp[j] = 0;
	*out2 = atoi(tmp);
	*index = i;
	
	return;
}

int main (void)
{
   FILE *fpSnow;    /* File pointer */
   FILE *fpReport;  /* File pointer */
   int locID;       /* Location ID */
   int numFlavors;  /* Number of flavors */
   char code;       /* Snow cone flavor code */
   double numSold;  /* # of cones sold */
   double totSales; /* Total Sales by flavor */
   double finSales; /* Total sales per location */
   int index, countTypes;  /* Counter for flavor types */
   double sales;    /* total sales */
   double countAvg; /* average accumulator */
   char tmp[TMP_SIZE];

  //those else-ifs would have ensured that it would have continued only if none of the files opened correctly
   /* Check opened files for NULL */
   if ((fpSnow = fopen("Snow.data", "r")) == NULL)
  printf("\nERROR opening Snow.data\n");
   if ((fpReport = fopen("Report.out", "w")) == NULL)
  printf("\nCannot open Report.out\n");
   if((fpSnow != NULL) && (fpReport != NULL))
   {
      //printDate(fpReport); <-- what was this function?

      while (!feof(fpSnow))
      {
      	fgets(tmp, TMP_SIZE, fpSnow);
      	  //getData(fpSnow, &locID, &numFlavors, &code, &numSold);
      	//fscanf(fpSnow, "%d %d", &locID, &numFlavors);
      	sscanf(tmp, "%d %d", &locID, &numFlavors);
        fprintf(fpReport, "LOCATION: %d\n", locID);
        
        memset(tmp, 0, TMP_SIZE);
  	 fgets(tmp, TMP_SIZE, fpSnow);
  for (countTypes=0, index=0; countTypes<=numFlavors; countTypes++)
  {
     PrintTotalsByFlavor(fpReport, code, numSold, totSales);
     getcharint(tmp, &index, &code, &numSold);
     //getData(fpSnow, &locID, &numFlavors, &code, &numSold);
     
  }
  //printLocSales(fpReport, finSales); ...and this?
      } /* end of while loop */
   } /* end of else loop */

   /* Closes files opened */
   fclose(fpReport);
   fclose(fpSnow);

   return 0;

}  /* End of main */

Sorry it's not very neat.
  #3  
Old 15-Mar-2005, 13:37
blitzy blitzy is offline
New Member
 
Join Date: Mar 2005
Posts: 3
blitzy is on a distinguished road
Dr. Evil,

Thanks for your reply! Unfortunately, we haven't covered fgets or arrays yet in the class, so I cannot use that in the program. I'm limited to using plain old fscanf and fprintf. That's why I'm having so many problems! As soon as I can get this error fixed, I hopefully get the other functions to calculate correctly.

Code:
printDate(fpReport);
This is just a function call to printDate, which prints the header message for the program. It works properly. The entire program is HUGE. ??:

I just don't understand why the first block of data from the file was read and printed correctly, but after that, everything else is messed up.

I'm so frustrated right now I'd pay someone to write the entire program for me! LOL
  #4  
Old 15-Mar-2005, 14:11
Dr. Evil Dr. Evil is offline
Member
 
Join Date: Oct 2004
Location: Netherlands
Posts: 120
Dr. Evil will become famous soon enough
How's this then? I was wrong about fscanf(), it does go along the file. One of your big problems was the <= in the for() loop, it should have just been <. What I also added was something to read through until it didn't come across a space, otherwise it would accept the space as the char.

CPP / C++ / C Code:
#include <stdio.h>

#define TMP_SIZE 256

#define IS_SPACE(c) ((c == 32) || ((c >= 9) && (c <= 13)))
#define IS_NUM(c) ((c >= 48) && (c <= 57))

void PrintTotalsByFlavor(FILE *fpReport, char code, double numSold, double totSales)
{
	char ok = 0;
	
   /* Switch statement for flavors */
   switch (code)
   {
     case 'C': 
      fprintf(fpReport, "\tCherry\t");
      ok = 1;
      break;
       case 'G': 
      fprintf(fpReport, "\tGrape\t");
       ok = 1;
      break;
       case 'L': 
      fprintf(fpReport, "\tLime\t");
       ok = 1;
      break;
  case 'N': 
      fprintf(fpReport, "\tCoconut\t");
      ok = 1;
      break;
  case 'O': 
      fprintf(fpReport, "\tOrange\t");
      ok = 1;
      break;
   } /* end of switch statement */
   
   if(ok)
   {
     fprintf(fpReport, "COUNT: %5d\t", numSold);
     fprintf(fpReport, "TOTAL SALES $ %10.2f\n", totSales);
   }
  
} /* End of PrintTotalsByFlavor */

/*
//gets a char then an int, ignores whitespace
void getcharint(char string[], int *index, char *out1, int *out2)
{
	char tmp[20];
	int my_index, i, j;
	
	my_index = *index;
	for(i=my_index; IS_SPACE(string[i]); i++) ;
	*out1 = string[i];
	i++;
	my_index = i;
	
	//printf("index: %d\n", my_index);
	for(i=my_index; !IS_NUM(string[i]); i++) ;
	my_index = i;
	for(i=my_index, j=0; IS_NUM(string[i]); i++, j++) tmp[j] = string[i];
	tmp[j] = 0;
	*out2 = atoi(tmp);
	*index = i;
	
	return;
}*/

int main (void)
{
   FILE *fpSnow;    /* File pointer */
   FILE *fpReport;  /* File pointer */
   int locID;       /* Location ID */
   int numFlavors;  /* Number of flavors */
   char code, junk;       /* Snow cone flavor code */
   double numSold;  /* # of cones sold */
   double totSales; /* Total Sales by flavor */
   double finSales; /* Total sales per location */
   int index, countTypes;  /* Counter for flavor types */
   double sales;    /* total sales */
   double countAvg; /* average accumulator */
   //char tmp[TMP_SIZE];

   /* Check opened files for NULL */
   if ((fpSnow = fopen("Snow.data", "r")) == NULL)
  printf("\nERROR opening Snow.data\n");
   if ((fpReport = fopen("Report.out", "w")) == NULL)
  printf("\nCannot open Report.out\n");
   if((fpSnow != NULL) && (fpReport != NULL))
   {
      //printDate(fpReport);

      while (!feof(fpSnow))
      {
      	//fgets(tmp, TMP_SIZE, fpSnow);
      	  //getData(fpSnow, &locID, &numFlavors, &code, &numSold);
      	//fscanf(fpSnow, "%d %d", &locID, &numFlavors);
      	//sscanf(tmp, "%d %d", &locID, &numFlavors);
      	fscanf(fpSnow, "%d %d", &locID, &numFlavors);
        fprintf(fpReport, "LOCATION: %d\n", locID);
        
        //printf("Location: %d, Flavors: %d\n", locID, numFlavors);
        //memset(tmp, 0, TMP_SIZE);
  	 //fgets(tmp, TMP_SIZE, fpSnow);
  for (countTypes=0, index=0; countTypes<numFlavors; countTypes++)
  {
  	 do {fscanf(fpSnow, "%c", &code);} while(IS_SPACE(code));
  	 fscanf(fpSnow, "%d", &numSold);
     PrintTotalsByFlavor(fpReport, code, numSold, totSales);
     //getcharint(tmp, &index, &code, &numSold);
     //printf("--Code: %c, Sold: %d\n", code, numSold);
     //sscanf(tmp, "%c %d", &code, &numSold);
     //getData(fpSnow, &locID, &numFlavors, &code, &numSold);
     
  }
  //printLocSales(fpReport, finSales);
      } /* end of while loop */
   } /* end of else loop */

   /* Closes files opened */
   fclose(fpReport);
   fclose(fpSnow);

   return 0;

}  /* End of main */

Also kind of messy...
  #5  
Old 15-Mar-2005, 14:28
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,700
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold
Quote:
Originally Posted by blitzy
Dr. Evil,

Thanks for your reply! Unfortunately, we haven't covered fgets or arrays yet in the class, so I cannot use that in the program. I'm limited to using plain old fscanf and fprintf. That's why I'm having so many problems! As soon as I can get this error fixed, I hopefully get the other functions to calculate correctly.

Code:
printDate(fpReport);
This is just a function call to printDate, which prints the header message for the program. It works properly. The entire program is HUGE. ??:

I just don't understand why the first block of data from the file was read and printed correctly, but after that, everything else is messed up.

I'm so frustrated right now I'd pay someone to write the entire program for me! LOL


The return value from scanf() or fscanf() tells you how many items in your specification were actually read.

If you know that there are supposed to be three ints, you can simply do something like this:

CPP / C++ / C Code:
int num read;
int x, y, z;
..
..
..
  if (scanf("%d%d%d", &x, &y, &z) != 3) {
  /* do something here that reports errors and/or tries to recover */
  }
  else {
  /* do something with x, y, and z */
  }

You can do the equivalent with fscanf() --- and you should always (always) check the return value of scanf() and fscanf().
In your case, you need to know the exact format of the input data before you can write a program to get the data into your data base.

Some lines have int int
Some lines have char int char int int int
Some lines have char int char int char int int int ...

I ask myself: what do these mean? Forget the program for a minute; what do they mean to me? More importantly, what do they mean to you? Can you predict how many things of each type are on each line?

Whether you use fscanf() or fgets(), unless the format is fixed and required to be in specific form, you will have to test the data as you go, and decide what is what and where it goes.

Before you write a program: make sure you know what the input is supposed to be. Write out the input specification and see if you can see any way to implement the function to read the input data. (And as you implement the code, make sure you can detect bad input and either attempt to recover, or, at the very least, report errors before aborting execution.)

Regards,

Dave
  #6  
Old 15-Mar-2005, 19:07
blitzy blitzy is offline
New Member
 
Join Date: Mar 2005
Posts: 3
blitzy is on a distinguished road
*sighs* Thanks for helping Dr. Evil and David. I think I'm just going to give up on this program. I doubt that I'll have it figured out by tomorrow morning at this rate; I've been working on it all weekend. My poor head! If only I could pay someone to do it for me. LOL. Well, better luck on the next program.
 
 

Recent GIDBlogToyota - 2008 September Promotion by Nihal

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
[Include] Doubly-linked List dsmith C Programming Language 6 14-Apr-2006 13:12
Need Help reading HEX data from a sensor Moooey C Programming Language 4 09-Mar-2005 13:46
[CONTEST?]Data Structure Test dsmith C Programming Language 2 06-Jun-2004 15:13
reading a char* into struct data spike666 C Programming Language 7 19-Apr-2004 12:06

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 13:45.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.