Hello,
I am stuck on an assignment I am working on. To be honest, the way I've structured it, it goes a bit beyond me.

Can someone kindly assist?

I have to get the following text:

3435344 @ L Brooks,12 Shaftsbury Road,Burwood NSW 2134
3435344 A 2005/02/22/08:22:41
3435344 A 2005/03/20/08:22:41
3435344 B 2005/03/23/18:22:41
3435344 B 2005/04/10/28:22:41
3435344 C 2005/03/11/08:22:41
3435344 C 2005/05/10/14:22:41
3435344 C 2005/05/19/06:22:43
3435344 D 2005/05/01/01:26:41
3873242 @ N McGoldrick,8 Colless Place,South Melbourne VIC 3205
3873242 B 2005/03/29/02:40:59
3873242 B 2005/05/16/02:40:59
3873242 C 2005/04/07/22:40:59
3873242 D 2005/03/02/02:40:59


...
pipe it to a program that sorts the stations, date time, then outputs an invoice with total amount owing. (I have been told Station A costs 2.20, B costs 2.80 etc...)

I am in first year, first semester. So I have to use easy methods.

I have made functions which basically: initialise, printHeadings (such as customer name and ID), readRecords (id, date, time, station), process Record (get station, times quantity of times entered by relevant charge), printInvoice (total for each station, then total for invoice).

My first problem:
How do I read from this file data to store into arrays, the two separate types of line (ie one has address, other has station, date and time). Do I do this within the one function or split it up into 2 functions? (One line I will use for just typing up customer details, the other I will use further to calculate amount to invoice....

Thanks for your time.

By the way, I have used this code so far to read first line (ID, station, Nameand Address):

void readRecord (int& id, string& name, int& item, double& cost, int& qty, bool& more)
{
      //int id;
      char station;
      string rest;
      while(true) {
                  cerr << "reading data and processing to file...";        
                  cin >> id;
                  if(cin.fail()) break;  
                  cin >> station;
                  if(cin.fail()) break;
                  cin >> ws;            
                  getline(cin, rest);    
                  if(cin.fail()) break;
                  
  }

You could try something akin to this:

struct invoice
  id
  name and address
  date and time
  items container
  amount total

while  successful input into id
  if current id same as prior id 
     continue on same invoice
  else
     complete current invoice 
     start new invoice

  input into item

  if item equals @
     input into name and address 
  else
     store item in container if desired
     input into date and time string 
 
//At end of loop evaluate stream
if EOF found
  file read in entirety without error
else
  error in reading file

Thanks for your help. I will begin working with this.
However, as stated previously I also have problem on how to insert those string into arrays.
The above code I wrote, only enters single values. I need to make parallel arrays, so can someone guide me with how a string is passed into an array?

if item equals @
input into name and address //this shouldnt be too hard for me but...
else
store item in container if desired
input into date and time string //...how do I store the date and time?

THANKS.

Member Avatar for iamthwee

Well do you know how to use a struct or class. Classes are often preferred in c++?

We havent studied classes yet. I was trying to figure out how to use substr and get.line to store strings into parallel arrays. (I know this in theory but cant find HOW to do it). So, I would like to find character '@', anything after that is the Name, Address.
Then anything that is not '@' (ie will be a station ID such as A, B, C...), anything after that will be my date and time).
IN THEORY. Again, I dont know the code. If someone could kindly tell me how substr is organised or how I get a string and store it into an array, that's what I was invisaging. Of-course open to other recommendations.

(I am nervous I wont finish this by Friday).
Renee

Member Avatar for iamthwee

Well I guess the next question would be, do you know, or are you allowed to use, parts of the STL. Namely, vectors?

I was thinking a vector of strings may be useful for your particular problem?

Using >> to read in id and station and getline() to read in the string after station seems reasonable. You should be aware however, that >> will leave the delimiter char between inputs (in this case space char) in the input buffer, and the delimiting char will not be ignored by getline(), like it will be by another call to >>. Therefore, clearing the input buffer by calling ignore() with the appropriate parameter(s) before the call to getline() would be a good idea.

getline() will put everything after the station field on a given line of the file into a single string. You may or may not need to parse (break up) the input original input string into substrings depending on how you want to use the information in the string. The first set of substrings are delimited by commas in the name/address string and by slashes in the date/time string. Then within the name/address string you have spaces between first name and last name, and colon between hour, minute, second in the time string if you want to break the information down into even more discrete information fields. I think you could probably do one of the following to break the input strings into desired substrings based on the delimeter used, IF you need to:

1) If using STL strings, use find() to find all the delimiters in the input string and then substr() to extract each substring between any two consecutive delimiters.
2) If using C style strings use strtok() to find substrings based on the delimiters
3) Use an istringstream with getline() to find substrings based on delimiters
4) write your own function using delimiters to separate input string into substrings.

If you've never heard of 1-3 before, then you are probably expected to do 4 as part of the learning exercise.

If you don't know about structs or classes yet, then keeping all this information in parrallel arrays/vectors seems a possible solution to keeping all this information in memory until you can do something with it, like print a report. For example, you could have an array for each of the fields to be printed in the report printing out a single line of information for each ID. The report may or may not use all of the fields available in the input data file. Based on your description of the report it looks like you will need the following information: id, name/address for a given ID, number of station A per ID, number of station B per ID, number of station C per ID, etc, and total amount per ID. So I would delcare appropriate arrays/vectors for each of those fields. As you are reading the file and find a station char (A, B, C, etc) you could increment the appropriate value stored in the appropriate index of the appropriate array for that ID, irrespective of the date the transaction occurred. Once the invoice for a given ID is compeleted (or once the file is completely read if that's more appropriate) you can then calculate the total amount for each ID based on the number of each station in each array for that ID times the value of each station (provided elsewhere) and store the amount in the appropriate index of the amount array/vector.

NB: my resources indicate that substr() has several variants:

1) substr() returns a copy of the string calling substr()

2) substr(x) returns a string that starts at index x in the calling string and includes all of the remaining char in the original strings

3) substr(x, y) returns a string that starts at index x and includes, at most, y char.

Therefore if you knew that there were two delimiters (say / is the delimiter) in a given input string (say abc/defg/hij is the input string) at indexes 3 and 8, then parsing the string into three substrings based on position of the delimeters using substr() would probably be:

substring1 = inputString.substr(0, 3);
substring2 = inputString.substr(4, 7 - 3);
substring3 = inputString.substr(9);

if I didn't make a mistake.

OK,
I've written this small section of code, as per last suggestion:

#include <iostream>
#include <string>
using namespace std;

int main ()
{
    
    const int MAX_LINE = 100;
    string name [MAX_LINE];
    string address [MAX_LINE];
    string line;
    int count =0;
   
    do {
        int position = line.find (',');
        string name = line.substr (0, position);
        string address = line.substr (position, MAX_LINE);
        }
        while (count<MAX_LINE);
        
        for (int i=0; i<count; i++)
        cout <<name[i]<<"/t"<<address[i]<<endl;
        
        system ("pause");
        return 0;
               }

It looks good to me, but it wont run. I think it goes in a loop or something because my program makes the .cpp crash out.

Can you suggest further on this? I will now go and do a program for storing the date and time as well.

APPRECIATE YOUR HELP BY THE WAY!

OK,

This one is giving me the error:
16 "incompatible types in assignment of `std::basic_string<char, std::char_traits<char>, std::allocator<char> >' to `std::string[100]' "

It look like it wants me to remove reference to MAX_LINE from string date declaration....but dont I need that to store into array?

Also, with the substring numbers, have I set them out right for this inputString:

3435344 A 2005/02/22/08:22:41


[

#include <iostream>
#include <string>
using namespace std;

int main ()
{
    
    const int MAX_LINE = 100;
    string date [MAX_LINE];
    string time [MAX_LINE];
    string inputString;
    int count =0;
   
    do {
        int position = inputString.find ('/');
        date = inputString.substr(0, 4); 
        time = inputString.substr(7,15-4);
        }
        while (count<MAX_LINE);
        
        for (int i=0; i<count; i++)
        cout <<date[i]<<"/t"<<time[i]<<endl;
        
        system ("pause");
        return 0;
               }

]

You have failed to use code tags in the 3 posts you have posted code. Use

tags the next time. There is a watermark in the message edit box telling you about it, so you can't say you didn't know.

I'm sorry about that. I actually dont understand it fully.
I thought I did it, but obviously not.
Do I have to put a [] around everyline then?

or just [ at the start and ] at the end?

Anything written between [code] [/code] will be considered as code.

For example

[code]#include <iostream>[/code]

will appear like

#include <iostream>

Shame I cant delete old posts, because I have improved my code.

Please ignore the last 2 codes.

I will update soon.

Can someone suggest why this for loop is not working as it should?

#include <iostream>
#include <string>
using namespace std;

int main ()
{   

    const int MAX_SIZE=5;
    char station [MAX_SIZE];
      
    int count = 0;
   
   do{
      cout<<"Enter station:"<<endl;
      cin>>station[count];
      double totalA = 0;
       if (station [MAX_SIZE] = 'A')
   {               
              for (int i=0; i<count; i++)
              totalA= totalA + 2.20;
              cout<<totalA;
              }
              }
   while (count<MAX_SIZE); 
              
              
                     system ("pause");
        return 0;
               }

it returns a value of 0 everytime.

Member Avatar for iamthwee

You have to increment count:

count = count + 1;

Change this:

char station [MAX_SIZE];

to this:

string station [MAX_SIZE];

and this:

if (station [MAX_SIZE] = 'A')

to this:

if (station [MAX_SIZE] == "A")

if (station [MAX_SIZE] = 'A')

In the above line, station[MAX_SIZE] doesn't exist or is out of bounds/illegal, is bad. The largest valid index is MAX_SIZE minus 1. You probably don't even want MAX_SIZE minus 1 because it won't be initialized until the fifth time through the do/while loop. You probably want count instead of MAX_SIZE.

Keeping station an array of char isn't wrong. Making sation an array of strings isn't necessary, but will also work.

Do yourself and others trying to help by using good indenting and spaces habits. It's much easier to read.

Geez,
thanks everyone.
I have been busy and come up with this. about 5 lines give me errors. So I have not been able to test the thing yet on the data. But I am excited about getting closer!

I have also worked on my indentations. Please check it out.

#include <iostream>
#include <string.h>
using namespace std;

void printGenericHeading(int&, int&);
void printCustomerHeading(int&, int&);
void readDateTime (int& , int& , string& , string& , string& ,int& , int& );
void calculateTotalStation (int& , char& , int& , double& , double& , double& , double& );
void resetControlTotals(double&);
void printTotalInvoice (int& , char& , double& , double& , double& , double& , double& );

const int MAX_DETAIL_LINES =100;
const int MAX_LINE = 100;
const int MAX_SIZE = 20;
double TotalInvoice = 0;
int pageCount = 0;
int lineCount = 0;
bool more= true;

void printGenericHeading(int& pageCount, int& lineCount)
{
     pageCount = pageCount +1;
     cout<<"INVOICE FOR TOLL EXPENSES"<<endl;
     cout<<"_________________________"<<endl;
     cout<<"TAG\tCUSTOMER\tSTATION"
     <<"\t\t\t\t\n";
     cout<<"ID\tNAME\t\tID\n";
     
     lineCount = 4;
     }
     
void printCustomerHeading(int& pageCount, int& lineCount)
{
     pageCount = pageCount +1;
     cout<<"\t\t\t\t\n";
     cout<<"t\t\t\t\tDATE\t\tTIME\tAMOUNT\n\n";
     
     lineCount = 3;
     }

void readDateTime (int& MAX_LINE, int& MAX_SIZE, string& date, string& time, string& inputString,int& count, int& position)
{
    
    date [MAX_SIZE];
    time [MAX_SIZE];
    inputString;
    count =0;
    
    do {
        cerr<<"processing..."<<endl;
        getline(cin, inputString);   
        if(cin.fail()) break;  
        
        int position = inputString.find ('/');
        date [count] = inputString.substr(0, 10); 
        time [count]= inputString.substr(11,16-11);
        count++;
        }
        while (count<MAX_SIZE);
        
        for (int i=0; i<count; i++)
        cout <<date[i]<<"\t"<<time[i]<<endl;
                      
  }   
  void calculateTotalStation (int& MAX_SIZE, char& station, int& count, double& totalA, double& totalB, double& totalC, double& totalD)
  
  {
    station [MAX_SIZE];
      
    count = 0;
    totalA = 0;
    totalB = 0;
    totalC = 0;
    totalD = 0;
    
   do{
      
       if (station [count] == 'A')
   {               
                   totalA= totalA + 2.20;
                   cout<<totalA;
              }
              
       if (station [count] == 'B')
   {               
                   totalB= totalB + 2.80;
                   cout<<totalB;
              }
              
       if (station [count] == 'C')
   {               
                   totalC= totalC + 2.30;
                   cout<<totalC;
              }
              
       if (station [count] == 'D')
   {               
                   totalD= totalD + 3.80;
                   cout<<totalD;
              }
                  
              }
   while (count<MAX_SIZE);        
}
     
     void resetControlTotals(double& controlTotal)
     
     {
     controlTotal = 0;  
     }

     void printTotalInvoice (int& MAX_SIZE, char& station, double& totalA, double& totalB, double& totalC, double& totalD, double& totalInvoice, double& controlTotal)
     
{
    
    station [MAX_SIZE];
      
    totalA = 0;
    totalB = 0;
    totalC = 0;
    totalD = 0;
    totalInvoice = 0;
   
 totalInvoice = totalA + totalB + totalC + totalD;
 cout<<"TOTAL:\t\t\t\t\t\t\$"<<totalInvoice<<endl;
 cout<<"\t\t\t\t\t\t_______"<<endl;
 cout<<"\t\t\t\t\t\t_______"<<endl;
 cout<<"We thankyou for your prompt payment."<<endl;
 resetControlTotals(controlTotal);
 
}

int main ()
{
int id;
int prevId;
string name;
string prevName;
double invoiceTotal;
double controlTotal;
int pageCount;
int lineCount;

prevId =id;
prevName=name;
         while(more)
         {
               if (id!=prevId)
               printTotalInvoice (MAX_SIZE, station, totalA, totalB, totalC, totalD, totalInvoice);
               prevId= id;
               prevName = name;
               }
               if (lineCount >MAX_DETAIL_LINES)
               printGenericHeading(pageCount, lineCount);
               printCustomerHeading(pageCount, lineCount);
               readDateTime (MAX_LINE, MAX_SIZE, date, time, inputString, count, position);
               calculateTotalStation (MAX_SIZE, station, count, totalA, totalB, totalC, totalD);
               resetControlTotals(controlTotal);
               printTotalInvoice (MAX_SIZE, station, totalA, totalB, totalC, totalD, totalInvoice);

               system("pause");
               return 0;
}

By the way, as per iamthwee, I changed the station declaration to be string type. (just now). Sorry its not included above and I'll avoid resubmitting to avoid clutter.

Lerner,
If I make changes to make station[count], then will it be ok to have code like this for that section:


void calculateTotalStation (int& MAX_SIZE, string& station, int& count, double& totalA, double& totalB, double& totalC, double& totalD)
  
  {  
    count = 0;
    station [count];
    totalA = 0;
    totalB = 0;
    totalC = 0;
    totalD = 0;
    
   do{
      
       if (station [count] == 'A')
   {               
                   totalA= totalA + 2.20;
                   cout<<totalA;
              }

I would have a series of arrays of int called stationA, stationB, stationC all initialized to zero. As I was reading the data from file, each time a stationA was found for any given ID i would increase the int at index i for stationA. Else if a stationB was found for any given ID I would increment the value at index of stationB with same index as given ID, etc. Then when I wanted to calculate the total of the invoice it would be a calculation such as:

amount to put at index i for array totalAmount is (number at index i in stationA * value of stationA) plus (number at index i in stationB * value of stationB) plus etc

So my method wont work at all? That is a shame coz it seems so nice and logical to me. I'll start making changes....

In reviewing your post with the "entire" program, it looks as though you have abanded the idea of storing all the data in parallel arrays and printing out the results all at once after the entire file has been read in favor of printing out an invoice for a given ID when a new ID has been found, which is fine, but you won't need arrays for stationA, stationB, etc. under the latter scenario.

I note that there is no mechanism to read from file in the program posted so that mechanism will need to be added at some point if you are going to be getting the data from a file.

It also looks like the while loop in main() is terminated early and the body of the if() statements terminate prematurely for lack of controlling brackets, but it's difficult to say for sure without comments.

In the following, it looks like you are trying to save all the stations for a given ID in an array and then calculate the station totals from there. That's viable. However, to pass an array of strings you would use string * station, not string & station and MAX_SIZE was declared global, so it doesn't need to be passed anywhere. (Globals should be avoided when possible, but this is one situation where I find using them at least tolerable).

void calculateTotalStation (int& MAX_SIZE, string& station, int& count, double& totalA, double& totalB, double& totalC, double& totalD)
  
  {  
    //count appears to be the number of stations visit by this ID
    //the array of stations and the count are passed in, so the
    //following two lines aren't needed.

    count = 0;   //this would mean no stations will be visited
    station [count];  //to my knowledge this is an illegal statement

    //this will set all station totals to 0
    totalA = 0;
    totalB = 0;
    totalC = 0;
    totalD = 0;

  do
  {
     if (station [count] == 'A')  //station[count] is a string so use "A"
     {               
                   totalA= totalA + 2.20;
                   cout<<totalA;
     }

Here's how I would use an array of string called station to do the calculations:

void calculateTotalStation (string * station, int count, double& totalA, double& totalB, double& totalC, double& totalD)
{  
    totalA = 0;
    totalB = 0;
    totalC = 0;
    totalD = 0;
    
   int i = 0;
   do
   {
      
       if (station [i] == "A")
       {               
                   totalA= totalA + 2.20;
                   cout<<totalA;
       }

     else if(station[i] == "B")
    .
    .
    .
  }while(i < count)
}

I really want to print out total for id xx is $....
Total for id YY is $....

I have amended code.
Is this looking closer to it?
I have made comments where I get errors. My declarations here and there are weird now...

#include <iostream>
#include <string.h>
using namespace std;

void printGenericHeading(int&, int&);
void printCustomerHeading(int&, int&);
void readDateTime (int& , int& , string& , string& , string& ,int& , int& );
void calculateTotalStation (int& , char& , int& , double& , double& , double& , double& );
void resetControlTotals(double&);
void printTotalInvoice (int& , char& , double& , double& , double& , double& , double& );

const int MAX_DETAIL_LINES =100;
const int MAX_LINE = 100;
const int MAX_SIZE = 20;
double TotalInvoice = 0;
int pageCount = 0;
int lineCount = 0;
bool more= true;

void printGenericHeading(int& pageCount, int& lineCount)
{
     pageCount = pageCount +1;
     cout<<"INVOICE FOR TOLL EXPENSES"<<endl;
     cout<<"_________________________"<<endl;
     cout<<"TAG\tCUSTOMER\tSTATION"
     <<"\t\t\t\t\n";
     cout<<"ID\tNAME\t\tID\n";
     
     lineCount = 4;
     }
     
void printCustomerHeading(int& pageCount, int& lineCount)
{
     pageCount = pageCount +1;
     cout<<"\t\t\t\t\n";
     cout<<"t\t\t\t\tDATE\t\tTIME\tAMOUNT\n\n";
     
     lineCount = 3;
     }

void readDateTime (int& MAX_LINE, int& MAX_SIZE, string * date, string * time, string& inputString,int& count, int& position)
{
    
    date [MAX_SIZE];
    time [MAX_SIZE];
    inputString;
    count =0;
    
    do {
        cerr<<"processing..."<<endl;
        getline(cin, inputString);   
        if(cin.fail()) break;  
        
        int position = inputString.find ('/');
        date [count] = inputString.substr(0, 10); // this line gave error so I change string & to string * date)
        time [count]= inputString.substr(11,16-11); //this line gave error so I change string & to string * time)
        count++;
        }
        while (count<MAX_SIZE);
        
        for (int i=0; i<count; i++)
        cout <<date[i]<<"\t"<<time[i]<<endl;
                      
}
  void calculateTotalStation (string * station, int count, double& totalA, double& totalB, double& totalC, double& totalD, double& totalInvoice, double& controlTotal)
{  
    totalA = 0;
    totalB = 0;
    totalC = 0;
    totalD = 0;
    
   int i = 0;
   do
   {
      
       if (station [i] == "A")
       {               
                   totalA= totalA + 2.20;
                   cout<<totalA;
       }

     else if(station[i] == "B")
     {               
                   totalB= totalB + 2.80;
                   cout<<totalB;
       }
        else if(station[i] == "C")
     {               
                   totalC= totalC + 2.30;
                   cout<<totalC;
       }
        else if(station[i] == "D")
     {               
                   totalD= totalD + 3.80;
                   cout<<totalD;
       }
       
        totalInvoice = totalA + totalB + totalC + totalD;
 cout<<"TOTAL:\t\t\t\t\t\t\$"<<totalInvoice<<endl;
 cout<<"\t\t\t\t\t\t_______"<<endl;
 cout<<"\t\t\t\t\t\t_______"<<endl;
 cout<<"We thankyou for your prompt payment."<<endl;
 resetControlTotals(controlTotal);
 
       
  }while(i < count);
}
     
     void resetControlTotals(double& controlTotal)
     
     {
     controlTotal = 0;  
     }



int main ()
{
int id;
int prevId;
string name;
string prevName;
double invoiceTotal;
double controlTotal;
int pageCount;
int lineCount;

prevId =id;
prevName=name;
         while(more)
         {
               if (id!=prevId)
               calculateTotalStation (MAX_SIZE, station, count, totalA, totalB, totalC, totalD); //this line gives error (STATION UNDECLARED)
               prevId= id;
               prevName = name;
               }
               if (lineCount >MAX_DETAIL_LINES)
               printGenericHeading(pageCount, lineCount);
               printCustomerHeading(pageCount, lineCount);
               readDateTime (MAX_LINE, MAX_SIZE, date, time, inputString, count, position); // this line gives error of date undeclared
               calculateTotalStation (MAX_SIZE, station, count, totalA, totalB, totalC, totalD);// this line gives error of station undeclared
               resetControlTotals(controlTotal);
               printTotalInvoice (MAX_SIZE, station, totalA, totalB, totalC, totalD, totalInvoice);// this line gives error of station undeclared

               system("pause");
               return 0;
}

Thanks for your help....

You asked if I had abandoned the idea of using parallel arrays.

I havent. I just am walking in the dark here and only getting to understand the whole concept of parallel arrays.

I hope this final version is pretty close to how it should be, since I have to hand it in tonight (Australia time). but I also have to 'clean up' my hierarchy chart, PSEUDOCODE, and do a deskcheck chart, once I am happy the program is as close as I can get it).

Thanks for your time.
So am I almost there?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.