Avatar of ghp7000
ghp7000
 asked on

Inner Loop Needed

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


C

Avatar of undefined
Last Comment
Kent Olsen

8/22/2022 - Mon
Kent Olsen

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
ghp7000

ASKER
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
Infinity08

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 ...
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Kent Olsen


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

ghp7000

ASKER
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?
Kent Olsen

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;
       }
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ghp7000

ASKER
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

Kent Olsen

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);
}
ghp7000

ASKER
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);
}



Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
Kent Olsen

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
ghp7000

ASKER
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?
Kent Olsen


Does this one function do all the printing?
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
Kent Olsen

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
ghp7000

ASKER
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.
ghp7000

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



Glad to help.   :)
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes