Hello!

So for my assignment I had to declare an array of 25 student objects and input data into them including another array of 5 test scores.

All that is done and works flawlessly(At least that's what I think), but the last portion of the assignment is for me to design a stringstream and print function to print out all of the data in a tabular format. I have never used stringstream before, but my main problem is formatting and finding a way for the print and display(stringstream) functions to take in and output the correct data.

Here's my code so far:

MAIN:

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

#include "Student.h"

const int MAX = 25;

//void printData(Student userData[]);
void getData(Student userData[]);
bool newStudent(Student userData[], int index);

int main(int argc, char *argv[])
{
    Student userData[MAX];
    
    getData(userData);
    
    void printData();
    
    system("PAUSE");
    return EXIT_SUCCESS;
}

void getData(Student userData[])
{
     bool done = false;
     int index = Student::getCount();
     while (index < MAX && !done)
     {
           while(newStudent(userData, index))
           {
                 Student::addCount();
                 index++;
           }
           done = true;
     }

}

bool newStudent(Student userData[], int index)
{
     int sX;
     int sS;
     string fN;
     string lN;
     
     cout << "Students currently entered: " << index << endl;
     cout << "Enter student ID (ctrl-z to quit): ";
     cin >> sX;
     
     if(cin.eof() || cin.fail())
     {
        system("cls");
        return false;
     }
        cin.ignore();
     
     cout << "Enter student's first name: ";
     getline(cin, fN);
     cout << "Enter student's last name: ";
     getline(cin, lN);
     
     userData[index].setId(sX);
     userData[index].setFirst(fN);
     userData[index].setLast(lN);
     
     cout << "Please enter 5 test scores (seperate with spaces): ";
     
     for(int i = 0; i < 5; i++)
     {
           cin >> sS;
           userData[index].setScores(sS,i);
     }
     system("cls");
     return true;
}

HEADER FILE:

using namespace std;
#ifndef STUDENT_CLASS
#define STUDENT_CLASS
class Student
{
    private:
            int studentId;
            string firstName;
            string lastName;
            int scores[5];
            double average;
            char grade;
            
            static int count;
            
            double calcAverage();
            
    public:
           Student();
                   
            void setId(int sX);
            void setFirst(string fN);
            void setLast(string lN);
            void setAverage(double sA);
            void setGrade(char sG);
            void setScores(int sS, int i);
            
            int getId() const;
            string getFirst() const;
            string getLast() const;
            int getScores() const;
            char getGrade() const;
            double getAverage() const;
            
            static int getCount();
            static void addCount() { count++; };
            
            string displayData();
};
#endif

IMPLEMENTATION FILE:

#include<iostream>
#include<iomanip>
#include<string>
#include<sstream>

using namespace std;

#include "Student.h"

int Student :: count = 0;

//Default Constructor
Student::Student()
{
         int sX = 0;
         string fN = "";
         string lN = "";
         
         for(int i = 0; i < 5; i++)
         scores[i] = 0;
         
         double sA = 0.0;
         char sG = ' ';
}

//================================Set Mutator Function declarations=============================================
void Student::setId(int sX)
{
     studentId = sX;
}

void Student::setFirst(string fN)
{
     firstName = fN;
}

void Student::setLast(string lN)
{
     lastName = lN;
}

void Student::setAverage(double sA)
{
     average = sA;
}

void Student::setScores(int sS, int i)
{
     scores[i] = sS;
}
//================================Get Accessor Function declarations=============================================
int Student::getId() const
{
    return studentId;
}

string Student::getFirst() const
{
       return firstName;
}

string Student::getLast() const
{
       return lastName;
}

double Student::getAverage() const
{
     return average;  
}

char Student::getGrade() const
{
     if(average >= 90.0)
     grade == 'A';
     return grade;
     
     if(average >= 80.0)
     grade == 'B';
     return grade;
     
     if(average >= 70.0)
     grade == 'C';
     return grade;
     
     if(average >= 60.0)
     grade == 'D';
     return grade;
     
     if(average < 60.0)
     grade == 'F';
     return grade;
}

int Student::getCount()
{
    return count;
}

double Student::calcAverage()
{
     double avg;
     avg = (scores[0] + scores[1] + scores[2] + scores[3] + scores[4]) / 5.0;
}

Okay so as you can see I have not even set up a string stream function as of yet. I do have a print method prototype up in main, but I'm unsure how to implement it along with the stringstream.

I'm guessing the function would look something like this (according to what I've read):

string Student :: displayData(void)
{
       calcAverage();

       stringstream strstr;
       
       strstr << left << setw(3) << studentId 
              << right << setw(3) << lastName << ", "
              << left << setw(10) << firstName
              << right << setw(10) << scores[0] 
              << right << setw(10) << scores[1] 
              << right << setw(10) << scores[2]
              << right << setw(10) << scores[3] 
              << right << setw(10) << scores[4]
              << right << setw(3) << average
              << right << setw(3) << getGrade();
              
              return strstr.str();
}

Obviously the setw values are just placeholders. Some guidance would be extremely helpful!

Thank you!

Think of a stringstream as a file you can't see. Then you realize you need to load the file with something and then you can read from it. In this case you probably want to load the stringstream with a student object and then use the output operators and modifiers to format the output as you have outlined, adjusting the parameters as desired to get a nice clean appearance.

What exactly do you mean by "load the stringstream with a student object"?

Sorry for being so dense, lol. This is probably the easiest part of the assignment, but I'm just having a brain block atm.

A stringstream is an I/O stream just like ifstream, ofstream, etc. It just uses a string as the I/O medium instead of a file. You "output" to the string, then display the string.

It is possible to overload the injection "<<" and extraction ">>" operators for a class to make it easier to output from the class directly. If you successfully overload them you should be able to "inject" a student into a stringstream, then display the string to the console.

Here's and example of using a stringstream to read in a string, then parse the string into individual values using the >> to separate the string into substrings and convert them to ints.

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

int main () {

  int val;
  stringstream ss (stringstream::in | stringstream::out);

  ss << "120 42 377 6 5 2000";

  for (int n=0; n<6; n++)
  {
    ss >> val;
    cout << val*2 << endl;
  }

  return 0;
}

This example is copied from post at cplusplus by the way.

I don't use them that often so I can't say for sure if the stringstream will load member variables of an object as if they were a string, assuming you have overloaded the << operator for the class, or not, but it's worth a try. If it loads it, then you should be able to spit out individual fields of the object using the appropriate stream method. The other way to try to load it is to pass the object like this:

Student Stud;
stringstream ss(Stud);

The other way to try to load it is to pass the object like this:

Student Stud;
stringstream ss(Stud);

I would have to try this, but I have my doubts about it working. With that statement, you are calling the overloaded constructor, not using an operator.

There are 2 versions of the stringstream constructor:

explicit stringstream ( openmode which = ios_base::out|ios_base::in );
explicit stringstream ( const string & str,
                        openmode which = ios_base::out|ios_base::in );

The second version accepts a std::string as an argument, but there is no direct conversion to that unless you somehow wrote your own as a cast operator or something.

Okay!

thanks guys, I got that figured out now I have one quick question:

When I call this function to set the grade to whatever it should be, it just returns a value of 0 when it displays in the console.

I can't figure out why this is.

Function:

void Student::setGrade(char grade)
{
     if(average >= 90.0)
     {
        grade == 'A';
        //return grade;
     }
     
     if(average >= 80.0)
     {
        grade == 'B';
        //return grade;
     }
     
     if(average >= 70.0)
     {
        grade == 'C';
        //return grade;
     }
     
     if(average >= 60.0)
     {
        grade == 'D';
        //return grade;
     }
     
     if(average < 60.0)
    {
        grade == 'F';
        //return grade;
     }
}

Call:

string Student :: displayData(void)
{
       calcAverage();

       stringstream strstr;
       
       strstr << left << setw(5) << studentId 
              << right << setw(5) << lastName << ", "
              << left << setw(5) << firstName
              << right << setw(5) << scores[0] 
              << right << setw(5) << scores[1] 
              << right << setw(5) << scores[2]
              << right << setw(5) << scores[3] 
              << right << setw(5) << scores[4]
              << right << setw(8) << average;
              
              setGrade(grade);
              
             strstr << right << setw(8) << grade;
              
              return strstr.str();
}

Thanks so much for the great help!

This thread is marked solved, but your last post is a question.

Were you able to resolve the issue on your own?

This thread is marked solved, but your last post is a question.

Were you able to resolve the issue on your own?

Yes, sorry. I eventually just included the method to find the character grade inside of the stringstream function.

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.