0

I need help with reading in a text file that has string integers for the first row and for the first column. I need to have everything print out in a table format. The program I have reads in a edited text file that only has the floats, and works fine. The program is meant to read in the text file, find the average and totals for each row and column, and print it all out in a table, but I'm unsure how to go about this. The table is supposed to print like so:

Department-Name Electric Copier Phone Miscellaneous sumOfRows totalOfRows
Bookkeeping 434.92 233.76 322.25 1442.98
Sales 610.55 233.21 144.75 1232.20
Service 343.21 224.76 128.90 987.00
Customer Relations 278.23 98.43 177.34 899.32
Marketing 522.32 109.78 233.45 1232.45
Media 132.98 221.43 119.56 1090.30
Human-Resources 109.56 342.87 298 1154
sumOfColumns
totalofColumns

I was told that I could input two string arrays, one for the first row and one for the first column, but I'm unsure how I could print it out in a table format.

Here is the file:

Department-Name Electric Copier Phone Miscellaneous 
    Bookkeeping 434.92 233.76 322.25 1442.98
    Sales 610.55 233.21 144.75 1232.20
    Service 343.21 224.76 128.90 987.00
    Customer Relations 278.23 98.43 177.34 899.32
    Marketing 522.32 109.78 233.45 1232.45
    Media 132.98 221.43 119.56 1090.30
    Human-Resources 109.56 342.87 298 1154

Here is my code:

#include "stdafx.h"
#include <iostream>
#include  <fstream>
#include  <stdlib.h>

using namespace std;

const int ROWSPACE = 7;
const int COLUMNSPACE = 4;
float rowAverage[ROWSPACE] = {0}; 
float colAverage[COLUMNSPACE] = {0};
float rowTotal[ROWSPACE] = {0}; 
float colTotal[COLUMNSPACE] = {0};

float getAverage(float averageArray[][COLUMNSPACE], int size, float rowAverage[], float colAverage[]);
float calcTotal(float sumArray[][COLUMNSPACE], int sz, float rowTotal[], float colTotal[]);
void getData(float expense[][COLUMNSPACE], int ROWSPACE);
void printTable();

int _tmain(int argc, _TCHAR* argv[])
{
    printTable();//Prints the data.
    system("pause");
    return 0;
}

float getAverage(float averageArray[][COLUMNSPACE], int size, float rowAverage[], float colAverage[])//Finds the sums of the rows and columns.
{
    int i,j;
    float sum = 0, average;

    cout<<"These are the row averages: \n";
    for(i = 0; i<size; i++)
    {
        for(j=0; j<COLUMNSPACE; j++)
        {
            sum+=averageArray[i][j];//Finds the overall average
            rowAverage[i] += averageArray[i][j]; //Finds each row's average
            colAverage[j] += averageArray[i][j]; //Finds each column's average.
        }
        rowAverage[i] /= COLUMNSPACE; 
        cout<<rowAverage[i]<<"\t"; //prints the row averages
    }
    cout<<endl;
    cout<<"These are the column averages: \n";
    for(j=0; j<COLUMNSPACE; j++) 
    {
        colAverage[j] /= size; 
        cout<<colAverage[j]<<"\t"; //prints the column averages
    }

    average=sum/(size * COLUMNSPACE); 
    return average;
}

float calcTotal(float sumArray[][COLUMNSPACE], int sz, float rowTotal[], float colTotal[])
{
    int i,j;
    float sum = 0, total;

    cout<<"These are the row totals: \n";
    for(i = 0; i<sz; i++)
    {
        for(j=0; j<COLUMNSPACE; j++)
        {
            sum+=sumArray[i][j]; //Finds the overall total
            rowTotal[i] += sumArray[i][j]; //Finds the row totals
            colTotal[j] += sumArray[i][j]; //Finds the column totals
        }
        cout<<rowTotal[i]<<"\t"; //prints out row totals
    }
    cout<<"\nThese are the column totals: \n"; 
    for(j=0; j<COLUMNSPACE; j++) {
        cout<<colTotal[j]<<"\t"; //Prints out column totals
    }

    total=sum; 
    return total;
}

void getData(float expense[][COLUMNSPACE], int ROWSPACE)
{
    ifstream expenseFile;
    ofstream outFile;
    int i, j;

    expenseFile.open("Expense1.txt"); //reads in the file (I have Expense1 as the floats only, and Expense with the strings and the floats)
    outFile.open("newFile.txt"); //creates thew new file

    outFile<<"The expenses are: \n";

    for(i = 0; i<ROWSPACE; i++) //creates the array from the file
{
    for(j = 0; j<COLUMNSPACE; j++)
    {
        expenseFile>>expense[i][j];
        cout<<expense[i][j]<<"\t"; 
        outFile<<expense[i][j]<<"\t";
    }
    cout << endl;  //closes the expense file
    outFile << endl; //closes the new file
    }
}

void printTable() //prints out the data
{
    float average;
    float total;
    float expenseArray[ROWSPACE][COLUMNSPACE];
    cout<<"Electric Copier Phone Miscellaneous\n";
    getData(expenseArray,ROWSPACE);
    cout<<endl;
    average=getAverage(expenseArray,ROWSPACE,rowAverage, colAverage);
    cout<<endl;
    total= calcTotal(expenseArray, ROWSPACE, rowTotal, colTotal);
    cout<<endl;
}

Any suggestions?

1 Answers1

0

Use an array of structures, not a 2D array.

One reason is all elements of an array must have the same data type so you can't mix strings and floats without playing shifty games with casting or unions. But with a class or structure... You can really have fun!

struct datastruct 
{
    string DepartmentName; 
    float Electric; 
    float Copier; 
    float Phone; 
    float Miscellaneous;
};

If allowed, prefer std::vector

std::vector<datastruct> list;

If bound by odd requirements and you have to use an array

datastruct list[ROWSPACE];

Now you can read the file in line by line. The following is adapted from Read file line by line

std::string line;
std::getline(infile, line); // discard first line. It is only header information
while (std::getline(infile, line))
{
    std::istringstream iss(line);
    datastruct temp;
    if (!(iss >> temp.DepartmentName 
              >> temp.Electric
              >> temp.Copier
              ...)) 
    {
        // handle error 
    }

    // store temp in vector or array
    list.push_back(temp);
    // or
    list[index] = temp;
}

If using an array add an exit condition to the while loop to prevent overrunning the end of the array

When you have a good grasp on C++ you can also overload >> for the structure and write something more like

datastruct temp;
while (infile >> temp))
{
    // store temp in vector or array
}

But I'm not going to cover that trick here.

Passing it around is much easier because you now have a one dimensional vector or array.

float getAverage(vector<datastruct> & list, 
                 vector<float> &rowAverage, 
                 datastruct & colAverage)

or

float getAverage(datastruct list[], 
                 int size,  
                 float rowAverage[], 
                 datastruct & colAverage)

To make computing the row and column average easy we modify datastruct

struct datastruct 
{
    string DepartmentName; 
    float Electric; 
    float Copier; 
    float Phone; 
    float Miscellaneous;

    float getAverage()
    {
        return (Electric + Copier + phone + Miscellaneous) / 4;
    }
    datastruct & operator+=(const datastruct & rhs)
    {
        Electric += rhs.Electric;
        Copier+= rhs.Copier;
        Phone+= rhs.Phone;
        Miscellaneous+= rhs.Miscellaneous;
        return *this;
    }
    datastruct & operator/=(float divisor)
    {
        Electric /= divisor;
        Copier/= divisor;
        Phone/= divisor;
        Miscellaneous/= divisor;
        return *this;
    }
};

and call it like

for (auto & row: list)
{
    rowAverage.push_back(row.getAverage());
    colAverage += row;
}
colAverage /= size;

or

for(i = 0; i<size; i++)
{
    rowAverage[i] = list[i].getAverage();
    colAverage += list[i];
}
colAverage /= size;

Here colAverge is used to sum up all the items in the list with the overloaded += operator and is then divided by the size with the/= operator.

Note that colAverage needs to be zeroed before it can be used to sum. You may want to add a method or a constructor to do that for you.

Calculating the totals is similar.

Community
  • 1
  • 1
user4581301
  • 33,082
  • 7
  • 33
  • 54