Data File input sorting question

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • heiro1
    New Member
    • Jan 2013
    • 29

    Data File input sorting question

    Hello everyone!
    I am a computer science student taking my first C++ class and this is my first time posting a query online. So, I apologize in advance for my lack of savvy. Up until now, I have not had any problems whatsoever but my current assignment is throwing me for one heck of a loop so I was hoping one of you more experienced folk can point me in the right direction.

    These are my assignment instructions:

    1 - Your assignment is to prompt the user to enter the filename with the path on disk. If the file does not exist in the specified location, your program should exit with a suitable error message.

    2 - The first thing your program should do is output to the screen a copy of the data read in from the disk file. This is known as “echoing” the input data.

    3 - Your program should then calculate and display the average score for males, females, community college students, and university students. Display your results to two places of decimals, and write your program to automatically list your four calculated averages one to a line, along with a suitable label for each result.

    4 - Finally, your program should calculate and display to two places of decimals the overall average score for all of the students surveyed.


    Questions:

    1 - I understand loops fairly well but I don't know how to get the while loop to read info from a data file, one "column" at a time. They are not allowing us to do arrays yet but even if they did, I think arrays work line by line instead of column by column.

    I have a feeling though, that through the use of loops, I can potentially manipulate the data search to the point that it will bypass everything except the data I need but I have no idea if that is the direction I need to go or if it is a matter of figuring out how to get a loop to read data from specific columns.

    2 - The provided text file is this:

    Bailey M CC 68
    Harrison F CC 71
    Grant M UN 75
    Peterson F UN 69
    Hsu M UN 79
    Bowles M CC 75
    Anderson F UN 64
    Nguyen F CC 68
    Sharp F CC 75
    Jones M UN 75
    McMillan F UN 80
    Gabriel F UN 62

    Since I am not outputting data to the file but instead, querying for input from the file, I would guess that I do not need any outfile commands but I am not sure about that. I am guessing the teacher put a list of names in there to make it harder to access the data I need (like the gender column). I am happy to provide more details if needed and thank you for your time! Here is a short template of my approach, it is just the gender scores so far:
    Code:
    #include <iostream> 
    #include <fstream> 
    #include <string> 
    #include <iomanip>
    using namespace std;
    int main()
    {
        //Declare variables to manipulate data
        char sex;
        string name;
        string school;
        string fileSource;
        int maleScore;
        int femScore;
        int UniScore;
        int commcollScore;
        int maleTotal;
        int femTotal;
        int uniTotal;
        int commcollTotal;
        double sum = 0;
        int femCount = 0;
        int maleCount = 0;
        int score;
        //Declare stream variables
        ifstream inData;
        ofstream outData;
        inData >> name >> sex >> school >> score;
        // Promt user for file location
        cout << "Please input file location: ";
        cin >> fileSource;
        
        // open output file and run program exit failsafe command
        inData.open(fileSource);
        if (!inData)
        {
            cout << "Cannot open input file. "
            << "Program will now terminate." << endl;
            return 1;
        }
            outData << fixed << showpoint << setprecision(2);
        
        // echo the data file
        while (inData)
        {
            cout << name << sex << school << score << endl;
            inData >> name >> sex >> school >> score;
        }
        
        // while reading incoming data from file, execute the conditions
        while (inData)
        {
            if(sex=='M')
            {
                maleScore = maleScore + maleTotal;
                ++maleCount;
            }
            else if(sex =='F')
                    {
                        femScore = femTotal;
                        ++femCount;
                    }
        }
    }
  • heiro1
    New Member
    • Jan 2013
    • 29

    #2
    Ok, I added an echo. The errors read on the echo and the pseudo code

    Here is is a bit more clean but still super basic:

    Code:
    #include <iostream> 
    #include <fstream> 
    #include <string> 
    #include <iomanip>
    using namespace std;
    int main()
    {
        //Declare variables to manipulate data
        char m;
        char f;
        string commcoll;
        string uni;
        double malescore;
        double maleaverage;
        double femalescore;
        double femaleaverage;
        double commcollscore;
        double commcollaverage;
        double uniscore;
        double uniaverage;
        double overallsum = 0;
        int count = 0;
        
        //Declare stream variables
        ifstream inData;
        ofstream outData;
        
        // open output file and run program exit failsafe command
        inData.open("/Users/jasonrodriguez/Desktop/scores.txt");
        if (!inData) {
            cout << "Cannot open input file. "
            << "Program will now terminate." << endl;
            return 1; }
        
        while(infile.get()) // echo
        {
            cout << infile;
        }
            outData << fixed << showpoint << setprecision(2);
        
        inData >> malescore;   //give a value to male score
        
        while (inData) // while reading incoming data from file, execute the conditions
        {
            if (column 2 == m)
                malescore = malescore + column 4 input;
            else (column 2 == f)
                femaleaverage = femaleaverage 
        inData.close();
        return 0;
    }

    Comment

    • heiro1
      New Member
      • Jan 2013
      • 29

      #3
      Code:
      #include <iostream> 
      #include <fstream> 
      #include <string> 
      #include <iomanip>
      using namespace std;
      int main()
      {
          //Declare variables to manipulate data
          char m;
          char f;
          string commcoll;
          string uni;
          double malescore;
          double maleaverage;
          double femalescore;
          double femaleaverage;
          double commcollscore;
          double commcollaverage;
          double uniscore;
          double uniaverage;
          double overallsum = 0;
          int count = 0;
          
          //Declare stream variables
          ifstream inData;
          ofstream outData;
          
          // open output file and run program exit failsafe command
          inData.open("/Users/jasonrodriguez/Desktop/scores.txt");
          if (!inData) {
              cout << "Cannot open input file. "
              << "Program will now terminate." << endl;
              return 1; }
          
          while(infile.get()) // echo
          {
              cout << infile;
          }
              outData << fixed << showpoint << setprecision(2);
          
          inData >> malescore;   //give a value to male score
          
          while (inData) // while reading incoming data from file, execute the conditions
          {
              if (column 2 == m)
                  malescore = malescore + column 4 input;
              else (column 2 == f)
                  femaleaverage = femaleaverage 
          inData.close();
          return 0;
      }

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        Each record contains 4 data elements: name, sex, type of school, and score.

        You can read these in using cin >> name >> sex >> etc...

        Then you test the sex and type of school to add to some variables that are your totals. I would also count the records read in.

        Place the cin>> and the totaling logic onside a loop that runs until you run out of input data.

        You now have all of the totals you need and if you have kept a inut record count you an divide your totals by the record count to get the averages.

        From what I see, your program just needs chnages to the input reading and totallng logic which appear overly complicated.

        Also, I see a lot of doubles but only integer values in the data. I expect you want to make the average of 3 to be 1.5. If that's the case, you are violating sigificant figures rules: derived data cannot be more accurate than the source cdata. That is, and averge of 1.5 requires source data of 3.0.

        I think you should be using int variables.

        Post again and let me know what happened.

        Comment

        • heiro1
          New Member
          • Jan 2013
          • 29

          #5
          Thanks so much for clarifying those important things! I made osme adjustments and am still trying to figure out a logical approach. Here is what I have so far:


          Code:
          #include <iostream> 
          #include <fstream> 
          #include <string> 
          #include <iomanip>
          using namespace std;
          int main()
          {
              //Declare variables to manipulate data
              char M;
              char F;
              string file;
              string commcoll;
              string uni;
              double malescore;
              double maleaverage;
              double femalescore;
              double femaleaverage;
              double commcollscore;
              double commcollaverage;
              double uniscore;
              double uniaverage;
              double overallsum = 0;
              int count = 0;
              int score;
              
              //Declare stream variables
              ifstream inData;
              ofstream outData;
              
              // Promt user for file location
              cout << "Please input file location: ";
              cin >> file;
              
              // open output file and run program exit failsafe command
              inData.open(file);
              if (!inData) {
                  cout << "Cannot open input file. "
                  << "Program will now terminate." << endl;
                  return 1; }
                  outData << fixed << showpoint << setprecision(2);
              
              // while reading incoming data from file, execute the conditions
              while (inData) 
              {
                  if (char = M)
                      malescore = malescore + score;
                  else if (char = F)
                      femalescore = femalescore + score;
                  count ++;
              }
              inData.close();
              return 0;
          }
          Is there anything I am not doing correctly? I am not sure where to go from here.

          Oh, also is this echoing the file?

          // echo
          Code:
          {
           cout << istream.get;
          }

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            This is a sample of your data:

            Bailey M CC 68

            What I see is a name, a sex identifier, a school identifier and a score.

            You would read this data by:

            Code:
            string Name;
            string Sex;
            string School;
            int    Score;
            
            inData >> Name >> Sex >> School >> Score;
            I don't see in your code where you are actualy reading the data.

            Then if Sex == "F" you add to the female total
            if Sex == "M" you add to the male total
            if School == "CC" you add to the community college total
            etc...

            Finally add 1 to the record count and go back and read another record using a while loop as you are already doing.

            Echoing the file would be to display the data read by:

            Code:
            cout << Name << Sex << School << Score << "\n";
            right after your inData >>. Nothing prevents you from formatting the cout so that your data isn't all mushed together.

            Comment

            • heiro1
              New Member
              • Jan 2013
              • 29

              #7
              Hello again wfc,
              Thank you for sharing your observations! I thought about it for a bit and came up with this version of the code:
              Code:
              #include <iostream> 
              #include <fstream> 
              #include <string> 
              #include <iomanip>
              using namespace std;
              int main()
              {
                  //Declare variables to manipulate data
                  char sex;
                  string name;
                  string school;
                  string fileSource;
                  string CC;
                  string UN;
                  int maleScore = 0;
                  int femScore = 0;
                  int unScore = 0;
                  int ccScore = 0;
                  double maleAvg;
                  double femAvg;
                  double unAvg;
                  double ccAvg;
                  double sumAvg = 0;
                  int femCount = 0;
                  int maleCount = 0;
                  int ccCount = 0;
                  int unCount = 0;
                  int score;
                  int sum;
                  //Declare stream variables
                  ifstream inData;
                  ofstream outData;
                  inData >> name >> sex >> school >> score;
                  // Promt user for file location
                  cout << "Please input file location: ";
                  cin >> fileSource;
                  
                  // open output file and run program exit failsafe command
                  inData.open(fileSource);
                  if (!inData)
                  {
                      cout << "Cannot open input file. "
                      << "Program will now terminate." << endl;
                      return 1;
                  }
                      outData << fixed << showpoint << setprecision(2);
                  
                  // echo the data file
                  while (inData)
                  {
                      cout << name << sex << school << score << endl;
                      inData >> name >> sex >> school >> score;
                  }
                  
                  // while reading incoming data from file, execute the conditions
                  // Male and female calculations
                  while (inData)
                  {
                      if(sex=='M')
                      {
                          maleScore = maleScore + score;
                          ++maleCount;
                      }
                      else if(sex =='F')
                              {
                                  femScore = femScore + score;
                                  ++femCount;
                              }
                      if (maleCount == 12)
                      {
                          maleAvg = maleScore/maleCount;
                      }
                      
                      // Male average output
                      cout << maleAvg;
                      
                      if (femCount == 12)
                      {
                          femAvg = femScore/femCount;
                      }
                      // Female average output
                      cout << femAvg;
                      // Community college and University calculations
                      if(school == CC)
                      {
                          ccScore = ccScore + score;
                          ++ccCount;
                      }
                      else if(school == UN)
                      {
                          unScore = unScore + score;
                          ++femCount;
                      }
                      if (ccCount == 12)
                      {
                          ccAvg = ccScore/ccCount;
                      }
                      // Community College average output
                      cout << ccAvg;
                      
                      if (unCount == 12)
                      {
                          unAvg = unScore/unCount;
                      }
                      // University average output
                      cout << unAvg;
                      sum = maleScore + femScore + ccScore + unScore;
                      sumAvg = sum/12;
                      cout << sumAvg;
                      return 0;
              }
              }
              3 things about it though,

              1 - my compiler is telling me that none of my "count" variables are initialized. I am pretty sure that is because I did not create a condition that bases the amount of loops with the counters. Any idea on how I can incorporate that into my code or is it even necessary?

              2 - I played it pretty safe here with the coding. I think the teacher wanted us to be more daring with the loops. Any ideas on how I can cut my code shorter using a "while..do" or a "for" loop?

              3 - The first loop was intended to be an echo. Did I do it wrong? How do I close it? Place a

              Code:
              cout << endl;
              on the next line? Thanks for your insight!!

              Comment

              • weaknessforcats
                Recognized Expert Expert
                • Mar 2007
                • 9214

                #8
                This code:

                Code:
                 inData.open(fileSource.c_str());
                is how you open the file. The open method does not use a C++ string argument but instead uses a C string argument. I'm surprised your code:

                Code:
                inData.open(fileSource);
                is compiling. What compiler are you using.

                Next, you have loop problems. This loop:
                Code:
                while (inData)
                    {
                        cout << name << sex << school << score << endl;
                        inData >> name >> sex >> school >> score;
                    }
                Will display the data before it is read. Not good. It should be:
                Code:
                while (inData)
                    {
                           inData >> name >> sex >> school >> score;
                           cout << name << sex << school << score << endl;
                
                    }
                Now the inout will be echoed but when you leave it your input file is at the end of the file so the next loop:
                Code:
                    while (inData)
                    {
                        if(sex=='M')
                        {
                ETC...
                Won't do anything because inData is false. You have to do the echo plus all the analysis inside the first loop.


                Code:
                while (inData)
                    {
                        inData >> name >> sex >> school >> score;
                        cout << name << sex << school << score << endl;
                
                        
                        //totaling and other processing done here
                    }
                This way you come into the loop, read a record of data, then echo that record, then process that record, then go back to the start of the loop so you can read the nexr record.

                When you leave this single loop all inout has been echoed, totals calculated. Now you just calculate your averages. To do this you will need to count the number of records read but I do not see you doing that.

                Next, this code:
                Code:
                if(sex=='M')
                etc...
                compares sex to a single character. This may be OK but for beginners I wouls use "M" rather than 'M'. The difference is that "M" is a C string whereas 'M' is a single character. So use "CC". I see you using CC where CC is a string but you never assigned "CC" to the string.

                I also see hard-coded numbers, like 12. Why 12? Did you peek at the input? A hard-coded number like this puts a limit in your program. The program gives wrong answers when the input is not exactly 12.

                I would to this in steps.

                Write one loop to read and echo the input. Get this working.

                Then add code to test for community college and add to a total. Display the total at the end of the program.

                When this works, add code for the other schools. Display thse totals.

                Now add code that counts males and females...

                Make sure at each step your program works. If ti fails to work you are pretty sure it is the you just added that's not working.

                And before you modify a working program make a copy of it in case your modifications result in a mess. You can start over just by making a copy of the original from the previous step.

                The code is coming along. I see progress.

                Comment

                • heiro1
                  New Member
                  • Jan 2013
                  • 29

                  #9
                  Thanks so much for your input, I really appreciate it! I am using Xcode. I had that C command in there because a friend who knows C told me that is how to echo, I didn't realize it was a different type of code.

                  I meant to say the compiler gave me 4 warning markers, I didn't actually compile anything at that point. I figured out why they were not initialized though.

                  I made some changes based on your observations and now everything compiles and the program runs but there are a few problems.

                  The first problem is with my echo.
                  // echo the data file
                  Code:
                   while (inData)
                      {
                          inData >> name >> sex >> school >> score;
                          cout << name << sex << school << score << endl;
                  The program does echo the data but it ends up echoing the last name on the list, twice for some reason. Also, (and I don't know if this matters) when it does echo, it does not skip spaces inbetween name, sex, school, and score.

                  The second problem is that it isn't executing the calculations and I think it is because I am missing a "count" related instruction of some sort.

                  Here is my revised code, let me know what you think:

                  Code:
                  #include <iostream>
                  #include <fstream>
                  #include <string>
                  #include <iomanip>
                  using namespace std;
                  int main()
                  {
                      //Declare variables to manipulate data
                      char sex;
                      string name;
                      string school;
                      string fileSource;
                      string CC;
                      string UN;
                      int maleScore = 0;
                      int femScore = 0;
                      int unScore = 0;
                      int ccScore = 0;
                      double maleAvg;
                      double femAvg;
                      double unAvg;
                      double ccAvg;
                      double sumAvg = 0;
                      int femCount = 0;
                      int maleCount = 0;
                      int ccCount = 0;
                      int unCount = 0;
                      int score;
                      int sum;
                      //Declare stream variables
                      ifstream inData;
                      ofstream outData;
                      inData >> name >> sex >> school >> score;
                      // Promt user for file location
                      cout << "Please input file location: ";
                      cin >> fileSource;
                      
                      // open output file and run program exit failsafe command
                      inData.open(fileSource);
                      if (!inData)
                      {
                          cout << "Cannot open input file. "
                          << "Program will now terminate." << endl;
                          return 1;
                      }
                      outData << fixed << showpoint << setprecision(2);
                      
                      // echo the data file
                      while (inData)
                      {
                          inData >> name >> sex >> school >> score;
                          cout << name << sex << school << score << endl;
                          
                          // while reading incoming data from file, execute the conditions
                          
                          // Male and female calculations
                              if(sex=='M')
                              {
                                  maleScore = maleScore +=score;
                                  ++maleCount;
                              }
                              else if(sex =='F')
                              {
                                  femScore = femScore +=score;
                                  ++femCount;
                              }
                              
                              // Community college and University calculations
                              if(school == CC)
                              {
                                  ccScore = ccScore +=score;
                                  ++ccCount;
                              }
                              else if(school == UN)
                              {
                                  unScore = unScore +=score;
                                  ++unCount;
                              }
                              maleAvg = maleScore/maleCount;
                          }
                          
                              // Male average output
                              cout << maleAvg;
                              
                              femAvg = femScore/femCount;
                              
                              // Female average output
                              cout << femAvg;
                              
                              ccAvg = ccScore/ccCount;
                              
                              // Community College average output
                              cout << ccAvg;
                              
                              unAvg = unScore/unCount;
                              
                              // University average output
                              cout << unAvg;
                              sum = maleScore + femScore + ccScore + unScore;
                              sumAvg = sum/12;
                              cout << sumAvg;
                              return 0;
                      }
                  Also, my compiler keeps running the program and does not stop. I took a pic of my compiler window but don't know how to post it.

                  Comment

                  • weaknessforcats
                    Recognized Expert Expert
                    • Mar 2007
                    • 9214

                    #10
                    This code:
                    Code:
                      while (inData)
                          {
                              inData >> name >> sex >> school >> score;
                    etc...
                    Try:

                    Code:
                      while (! inData.eof())
                          {
                              inData >> name >> sex >> school >> score;
                    etc...
                    The input file has a member function named eof(). This function returns true when you reach the end of file. So the code above says "while NOT at the end of file..."

                    As to the last line over and over I suspect th actual data zipped off the top of the screen between eyeblinks. Nw yu are in a loop forever until inData is false (which will never happen) displaying the last data read every cycle of the loop.

                    Comment

                    • heiro1
                      New Member
                      • Jan 2013
                      • 29

                      #11
                      Ah, yes that's right. Still, even after making that change, I still have all of those problems though. Nothing changed. Well, one thing did change actually. Now the echo does not repeat the last name in the file list.

                      It still isn't doing any of the calculations and it is still perpetually running until I manually stop it. Mainly though, I am concerned with how to get my calculations to run. Any thoughts? It looks solid, I can't figure out why it isn't calculating.

                      Comment

                      • heiro1
                        New Member
                        • Jan 2013
                        • 29

                        #12
                        Ok problem solved, here is my result. It works like a charm:

                        Code:
                        #include <iostream>
                        #include <fstream>
                        #include <string>
                        #include <iomanip>
                        
                        using namespace std; 
                        
                        int main()
                        {
                            //Declare variables to manipulate data
                            string name;
                            string fileSource;
                            
                            int maleScore = 0;
                            int femScore = 0;
                            int unScore = 0;
                            int ccScore = 0;
                            int femCount = 0;
                            int maleCount = 0;
                            int ccCount = 0;
                            int unCount = 0;
                            
                            //Declare stream variables
                            ifstream inData;
                            ofstream outData;
                            
                            // Prompt user for file location
                            cout << "Please input file location: ";
                            cin >> fileSource;
                            
                            // open output file and run program exit failsafe command
                            inData.open(fileSource);
                            
                            if(!inData)
                            {
                                cout << "Cannot open input file. "
                                << "Program will now terminate." << endl;
                                return 1;
                            }
                            
                            cout << "Reading data from '" << fileSource << "'" << endl;
                            
                            while(inData >> name)
                            { // If we read a name, we can continue. Otherwise, we're done.
                                char sex;
                                int score;
                                string school;
                                
                                inData >> sex >> school >> score;
                                
                                // Echo
                                cout << name << sex << school << score << endl;
                                
                                // Male and female calculations
                                if(sex=='M')
                                {
                                    maleScore +=score;
                                    maleCount++;
                                }
                                else if(sex =='F')
                                {
                                    femScore +=score;
                                    femCount++;
                                }
                                
                                // Community college and University calculations
                                if(school == "CC")
                                {
                                    ccScore +=score;
                                    ccCount++;
                                }
                                else if(school == "UN")
                                {
                                    unScore +=score;
                                    unCount++;
                                }
                            }
                            
                            // Average Calculations
                            cout << fixed << showpoint << setprecision(2) << endl; 
                            if(maleCount != 0)
                            {
                                cout << "The average scores for males is: " 
                                << static_cast<double>(maleScore) / maleCount << endl;
                            }
                            
                            if(femCount != 0)
                            {
                                cout << "The average score for females is: " 
                                << static_cast<double>(femScore) / femCount << endl;
                            }
                            
                            if(ccCount != 0)
                            {
                                cout << "The average score for Community Colleges is: " 
                                << static_cast<double>(ccScore) / ccCount << endl;
                            }
                            
                            if(unCount != 0)
                            {
                                cout << "The average score for Universities is: "   
                                << static_cast<double>(unScore) / unCount << endl;
                            }
                            
                            cout << "The average test score for all students combined is: " 
                            << (1.0 * (maleScore + femScore + ccScore + unScore)) / 12 << endl;
                            
                            return 0;
                        }
                        Still, I have this nagging feeling like there is a way to make this program shorter. Is it possible?

                        Comment

                        • weaknessforcats
                          Recognized Expert Expert
                          • Mar 2007
                          • 9214

                          #13
                          It's always possible to improve a program but my motto has always been:

                          The only reality is a running program - all else is prophecy.

                          Your program works. Call it day. The lessons you learned on this program will be applied to the next one making the next program better.

                          Be sure to post again as necessary.
                          Last edited by weaknessforcats; Feb 14 '13, 05:08 PM. Reason: used wrong tags

                          Comment

                          Working...