Inner Loop Needed

ghp7000
ghp7000 used Ask the Experts™
on
Need an inner loop to process lines from a file that have the same account number abd I cant seem to make it work.
Here is the scenario:
a text file containing an ordered listing of names. I am using  while (fgets( filler, 115, FilePtr)) to read
each line of the file, with each line being no longer than 115 characters. I have no problem to read the lines and assign the read values to appropiate char or int type variables. I am also using atof to change some of the read values to double type numbers, so that they can be added as subtotals.
But what I want to do is to process a subset of the file, so that each time the account number changes, I can write the subtotals of each account number to a another file, and this is the part that I am hung up on. I have tried various if statements, while loops etc but I cant seem to get the right algorithm.
I still want to process the entire file, I just need a way to process each subset of data within the file.
Thanks


Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Hi ghp7000,

Odd seeing you in the C forum.  :)

It's not too bad to do....
 
  FILE *f;
  char Buffer[116];
  int     Account = 0;   // presumes that an account number of zero is invalid
  int     NewAcct;

  f = fopen ();

  while (fgets (Buffer, 115, f) > 0)
  {
    NewAcct = atoi (Buffer);   // Convert as your data requires
    if (NewAcct != Account)   // change accounts
      if (Account != 0)              // Print totals if not the first time throuth the loop
      {
        PrintTotals ();
        //  Zero out the accumulators
      }
    // Add to the accululators
  }
  if (Account)                        // If any accounts were processed, there is still data in the accumulators for the last account
    PrintTotals ();


That should just about do it.



Good Luck,
Kent

Author

Commented:
lol, Im all over the place (one of the advantages of having unlimited points).
I will try your suggestion and let you know the outcome, this cant be as difficult as Im making it
Top Expert 2009

Commented:
Can you also show a sample of the text file, as well as which subset you'd like to get ... just an example to give us an idea ...
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!


Well, C doesn't have DB2's cube functionality built in so it is a bit more work.   ;)

Author

Commented:
Sorry, Im still hung up. I am going to paste the entire function so that youc an see what Im doing:
/*****************************************************************************/
/*read_accounts                                                              */
/*****************************************************************************/
/*parses accounts.txt file */
int read_accounts(char * datafile, char * logfile, char * reportfile)
{
   if(!OpenFiles(datafile, logfile, reportfile))
      return(0);

    header(1,datafile,"", "");
    header(2,reportfile,"","");
    message_box(8,datafile);

    while(fgets(filler,115,FilePtr))
    {
     LINENO=LINENO+1;
     getstr(acctnumber,         filler, 00,  7);
     getstr(acctname,           filler, 07, 30);
     trim_spaces(acctname);
     getstr(acctyear,           filler, 37,  4);
     trim_spaces(acctyear);
     strcpy(processloop, acctname);
     getstr(acctinvbalance,     filler,100,  9);
     trim_spaces(acctinvbalance);
       if (strlen(acctinvbalance)==0)
       strcpy(acctinvbalance,"0.00");
       if((account!=atoi(acctnumber)) && (strcmp(acctyear,current_year)==0))
       header(3,acctname,acctnumber,acctinvbalance);
       if(strcmp(acctyear,current_year)==0)
       {
        account=atoi(acctnumber);
        printf("%s %f %f\n", acctname, invtotal, invtotalsubtotal);
        invtotal=0.00;
        invtotalsubtotal=0.00;
       }
     getstr(acctmonth,          filler, 41,  2);
     trim_spaces(acctmonth);
     getstr(acctday,            filler, 43,  2);
     trim_spaces(acctday);
     getstr(acctinvnumber,      filler, 45,  5);
     trim_spaces(acctinvnumber);
     getstr(acctinvtotal,       filler, 73,  9);
     getstr(acctinvpayment,     filler, 82, 10);
     getstr(acctinvdiscount,    filler, 92,  8);
     getstr(acctinvbalance,     filler,100,  9);
     getstr(acctinvpayment,     filler, 82, 10);
     getstr(acctinvdiscount,    filler, 92,  8);
     getstr(acctinvbalance,     filler,100,  9);
       if(strcmp(acctyear,current_year)!=0)
       {
        fprintf(ErrLogPtr, "%6d \t%-7s\t%-30s \t%s-%s-%s   %5s %9s %10s %8s %9s \n", LINENO, acctnumber, acctname, acctday, acctmonth, acctyear, acctinvnumber, acctinvtotal, acctinvpayment, acctinvdiscount, acctinvbalance);
        continue;
       }
        else
        fprintf(RptPtr, "%s-%s-%s \t %5s \t %s \t %s \t %s \t %s \n", acctday, acctmonth, acctyear, acctinvnumber, acctinvtotal, acctinvpayment, acctinvdiscount, acctinvdiscount);
      invtotal=atof(acctinvtotal);
      invtotalsubtotal=invtotalsubtotal+invtotal;
     }
 if(!CloseFiles(datafile,logfile, reportfile))
    return(0);
    return(1);
}
the output prints the invtotal and invtotal subtotal for each line that meets the date qualification,what I want is to first:
be able to add each invoicetotal (ie keep track of running total per account number)
be able to print the result in the pointer file at the end of each account number listing.
Can you point out what I am doing wrong?
I think so.  :)

Look at this block of code:

       if((account!=atoi(acctnumber)) && (strcmp(acctyear,current_year)==0))
         header(3,acctname,acctnumber,acctinvbalance);
       if(strcmp(acctyear,current_year)==0)
       {
        account=atoi(acctnumber);
        printf("%s %f %f\n", acctname, invtotal, invtotalsubtotal);
        invtotal=0.00;
        invtotalsubtotal=0.00;
       }

I think that you want it to be more on the order of:

       if (account!=atoi(acctnumber) || strcmp(acctyear,current_year) !=0)
       {
          header(3,acctname,acctnumber,acctinvbalance);
          account=atoi(acctnumber);
          printf("%s %f %f\n", acctname, invtotal, invtotalsubtotal);
          invtotal=0.00;
          invtotalsubtotal=0.00;
       }

Author

Commented:
thanks for the reply.
I made some changes, the code now looks like this:
/*****************************************************************************/
/*read_accounts                                                              */
/*****************************************************************************/
/*parses accounts.txt file */
int read_accounts(char * datafile, char * logfile, char * reportfile)
{
   if(!OpenFiles(datafile, logfile, reportfile))
      return(0);

    header(1,datafile,"", "");
    header(2,reportfile,"","");
    message_box(8,datafile);

    while(fgets(filler,115,FilePtr))
    {
     LINENO=LINENO+1;
     getstr(acctnumber,         filler, 00,  7);
     getstr(acctname,           filler, 07, 30);
     trim_spaces(acctname);
     getstr(acctyear,           filler, 37,  4);
     trim_spaces(acctyear);
     strcpy(processloop, acctname);
     getstr(acctinvbalance,     filler,100,  9);
     trim_spaces(acctinvbalance);
       if (strlen(acctinvbalance)==0)
       strcpy(acctinvbalance,"0.00");
       if((account!=atoi(acctnumber)) && (strcmp(acctyear,current_year)==0))
       {
       header(3,acctname,acctnumber,acctinvbalance);
       account=atoi(acctnumber);
       fprintf(RptPtr,"%s %f %f\n", acctname, invtotal, invtotalsubtotal);
       invtotal=0.00;
       invtotalsubtotal=0.00;
       }
     getstr(acctmonth,          filler, 41,  2);
     trim_spaces(acctmonth);
     getstr(acctday,            filler, 43,  2);
     trim_spaces(acctday);
     getstr(acctinvnumber,      filler, 45,  5);
     trim_spaces(acctinvnumber);
     getstr(acctinvtotal,       filler, 73,  9);
     getstr(acctinvpayment,     filler, 82, 10);
     getstr(acctinvdiscount,    filler, 92,  8);
     getstr(acctinvbalance,     filler,100,  9);
     getstr(acctinvpayment,     filler, 82, 10);
     getstr(acctinvdiscount,    filler, 92,  8);
     getstr(acctinvbalance,     filler,100,  9);
       if(strcmp(acctyear,current_year)!=0)
       {
        fprintf(ErrLogPtr, "%6d \t%-7s\t%-30s \t%s-%s-%s   %5s %9s %10s %8s %9s \n", LINENO, acctnumber, acctname, acctday, acctmonth, acctyear, acctinvnumber, acctinvtotal, acctinvpayment, acctinvdiscount, acctinvbalance);
        continue;
       }
        else
       {
        fprintf(RptPtr, "%s-%s-%s \t %5s \t %s \t %s \t %s \t %s \n", acctday, acctmonth, acctyear, acctinvnumber, acctinvtotal, acctinvpayment, acctinvdiscount, acctinvdiscount);
        invtotal=atof(acctinvtotal);
        invtotalsubtotal=invtotalsubtotal+invtotal;
       }
     }
 if(!CloseFiles(datafile,logfile, reportfile))
    return(0);
    return(1);
}
but it gives this result:
****************************************************************************
       ACCOUNTS RECEIEVABLE LIST
       YEAR MONTH PERIOD: 2002/12
       PREPARED ON      : WEDNESDAY, MAY 30, 2007
****************************************************************************
first account number
  CUSTOMER NAME  :
  CUSTOMER NUMBER:       0
  OPENING BALANCE: 0.00
DATE           INVOICE         INVOICE         PAYMENT
               NUMBER           AMOUNT         AMOUNT
 0.000000 0.000000>>>> this is fprintf of invtotal and subtotal, it should say 2208.00 and it should be printed after the detail list
24-10-2002        17872          2208.00                                                   

second account number
  CUSTOMER NAME  : CASH AND CARRY ACCT
  CUSTOMER NUMBER: 1111111
  OPENING BALANCE: 0.00
DATE           INVOICE         INVOICE         PAYMENT
               NUMBER           AMOUNT         AMOUNT
CASH AND CARRY ACCT (C.O.D)QC 2208.000000 2208.000000>>>this is the subtotal for first account
19-02-2002        16446           353.13                                                   
20-02-2002        16466           259.50                                                   
20-02-2002                                         -353.13            0.00            0.00
this is basically the same problem Ive had all along, I cant seem to find the right way to do this

Ah.  Ok.  :)

It's a little bit of a challenge to follow the code since there are no literals in it, but this should be close.  Well, closer.....


int read_accounts(char * datafile, char * logfile, char * reportfile)
{
   if(!OpenFiles(datafile, logfile, reportfile))
      return(0);

    header(1,datafile,"", "");
    header(2,reportfile,"","");
    message_box(8,datafile);

    while(fgets(filler,115,FilePtr))
    {
     LINENO=LINENO+1;
     getstr(acctnumber,         filler, 00,  7);
     getstr(acctname,           filler, 07, 30);
     trim_spaces(acctname);
     getstr(acctyear,           filler, 37,  4);
     trim_spaces(acctyear);
     strcpy(processloop, acctname);
     getstr(acctinvbalance,     filler,100,  9);
     trim_spaces(acctinvbalance);
     if (strlen(acctinvbalance)==0)
       strcpy(acctinvbalance,"0.00");
     if((account!=atoi(acctnumber)) || (strcmp(acctyear,current_year)))
     {
//  Print the previous totals if there are any
       if(strcmp(acctyear,current_year)!=0)
         fprintf(ErrLogPtr, "%6d \t%-7s\t%-30s \t%s-%s-%s   %5s %9s %10s %8s %9s \n", LINENO, acctnumber, acctname, acctday, acctmonth, acctyear, acctinvnumber, acctinvtotal, acctinvpayment, acctinvdiscount, acctinvbalance);
//  Now set the current account number for the next pass    
       header(3,acctname,acctnumber,acctinvbalance);
       account=atoi(acctnumber);
       fprintf(RptPtr,"%s %f %f\n", acctname, invtotal, invtotalsubtotal);
       invtotal=0.00;
       invtotalsubtotal=0.00;
     }
     getstr(acctmonth,          filler, 41,  2);
     trim_spaces(acctmonth);
     getstr(acctday,            filler, 43,  2);
     trim_spaces(acctday);
     getstr(acctinvnumber,      filler, 45,  5);
     trim_spaces(acctinvnumber);
     getstr(acctinvtotal,       filler, 73,  9);
     getstr(acctinvpayment,     filler, 82, 10);
     getstr(acctinvdiscount,    filler, 92,  8);
     getstr(acctinvbalance,     filler,100,  9);
     getstr(acctinvpayment,     filler, 82, 10);
     getstr(acctinvdiscount,    filler, 92,  8);
     getstr(acctinvbalance,     filler,100,  9);
     
// Always print.  The line will contain some kind of detail that we want.
     fprintf(RptPtr, "%s-%s-%s \t %5s \t %s \t %s \t %s \t %s \n", acctday, acctmonth, acctyear, acctinvnumber, acctinvtotal, acctinvpayment, acctinvdiscount, acctinvdiscount);
     invtotal=atof(acctinvtotal);
     invtotalsubtotal=invtotalsubtotal+invtotal;
   }
   
 if(!CloseFiles(datafile,logfile, reportfile))
    return(0);
    return(1);
}

Author

Commented:
sorry kdo, your code does exactly the same thing, it prints the subtotals before the detail lines:
here is the original code reposted with literals to help you debug this:
*****************************************************************************/
/*read_accounts                                                              */
/*****************************************************************************/
/*parses accounts.txt file */
int read_accounts(char * datafile, char * logfile, char * reportfile)
{
   if(!OpenFiles(datafile, logfile, reportfile)) //test if can read/create/create files
      return(0);

    header(1,datafile,"", ""); //and write report header to error log  ptr
    header(2,reportfile,"",""); //and write report header to rpt ptr
    message_box(8,datafile); //display processing file name to user

    while(fgets(filler,115,FilePtr))
    {
     LINENO=LINENO+1;
     getstr(acctnumber,         filler, 00,  7);  //all getstr read values from file
     getstr(acctname,           filler, 07, 30);
     trim_spaces(acctname);                    //trim_spaces removes leading and trailing blanks
     getstr(acctyear,           filler, 37,  4);
     trim_spaces(acctyear);
     strcpy(processloop, acctname);    //this is not used to do anything, should be removed!
     getstr(acctinvbalance,     filler,100,  9);
     trim_spaces(acctinvbalance);
       if (strlen(acctinvbalance)==0)  //some values may contain only "   .  ", need to reset to 0.00
       strcpy(acctinvbalance,"0.00");
       if((account!=atoi(acctnumber)) && (strcmp(acctyear,current_year)==0))
       {
       header(3,acctname,acctnumber,acctinvbalance); //and write acct name, number and balance to rpt ptr
       account=atoi(acctnumber); //process current account number
       fprintf(RptPtr,"%s %f %f\n", acctname, invtotal, invtotalsubtotal);//write to rpt ptr but it is writing in the wrong place
       invtotal=0.00; //reset the last amount to zero
       invtotalsubtotal=0.00; //reset the running totals
       }
     getstr(acctmonth,          filler, 41,  2);
     trim_spaces(acctmonth);
     getstr(acctday,            filler, 43,  2);
     trim_spaces(acctday);
     getstr(acctinvnumber,      filler, 45,  5);
     trim_spaces(acctinvnumber);
     getstr(acctinvtotal,       filler, 73,  9);
     getstr(acctinvpayment,     filler, 82, 10);
     getstr(acctinvdiscount,    filler, 92,  8);
     getstr(acctinvbalance,     filler,100,  9);
     getstr(acctinvpayment,     filler, 82, 10);
     getstr(acctinvdiscount,    filler, 92,  8);
     getstr(acctinvbalance,     filler,100,  9);
       if(strcmp(acctyear,current_year)!=0) //dont process any records if the year read from file is not the same as the year entered by the user to start the program
       {
        fprintf(ErrLogPtr, "%6d \t%-7s\t%-30s \t%s-%s-%s   %5s %9s %10s %8s %9s \n", LINENO, acctnumber, acctname, acctday, acctmonth, acctyear, acctinvnumber, acctinvtotal, acctinvpayment, acctinvdiscount, acctinvbalance);//write all those records not prcoessed into the error log
        continue;//go to next record in file
       }
        else //if the year is the same , write the detail line of each transaction to the rpt ptr file
       {
        fprintf(RptPtr, "%s-%s-%s \t %5s \t %s \t %s \t %s \t %s \n", acctday, acctmonth, acctyear, acctinvnumber, acctinvtotal, acctinvpayment, acctinvdiscount, acctinvdiscount);
        invtotal=atof(acctinvtotal); //convert the string to float
        invtotalsubtotal=invtotalsubtotal+invtotal; //keep the running total
       }
     }
 if(!CloseFiles(datafile,logfile, reportfile)) //test if can close all files
    return(0);
    return(1);
}



Ahhh.....

It's still in the same place as I'd suspected...

       if (strlen(acctinvbalance)==0)  //some values may contain only "   .  ", need to reset to 0.00
       strcpy(acctinvbalance,"0.00");
       if((account!=atoi(acctnumber)) && (strcmp(acctyear,current_year)==0))
       {
>>           header(3,acctname,acctnumber,acctinvbalance); //and write acct name, number and balance to rpt ptr
           account=atoi(acctnumber); //process current account number
>>           fprintf(RptPtr,"%s %f %f\n", acctname, invtotal, invtotalsubtotal);//write to rpt ptr but it is writing in the wrong place
           invtotal=0.00; //reset the last amount to zero
           invtotalsubtotal=0.00; //reset the running totals
       }


Swap the two lines marked with '>>'  
You may also want to test whether this is "first pass" by testing that there is a saved account number.  If not, you don't need to print empty totals.


whew.....
Kent

Author

Commented:
sorry again, that didnt work, all it does is print the subtotals one line higher-what Im trying to do is print to the same file but at a different point in processing-first I want to print the detail lines and then print the subtotals-perhaps I need another approach? Maybe a linked list will do it the trick?

Does this one function do all the printing?

In addition to swapping those two lines, you also need to save the account name when you save the account number.  The code overwrites the account name so that it prints the account name of the just-read record, not the one associated with the totals you've been accumulating.


Kent

Author

Commented:
yes, the one function does all the printing, either by calling the header function or just doing the fprintf.
Okay, I will make the suggested change and inform you fo the result. Thanks again.

Author

Commented:
yes, the account name, I didnt 'get it' right away, but that was the problem, thanks for helping me out


Glad to help.   :)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial