0

I'm trying to overwrite data in a file, after inputting certain values using cin. The problem that I'm facing is that, the function that supposed to modify the file doesn't actually do it correctly.

Here's the scenario, I add these data by using register function

code:

// register a student to the system
void Student::registerStudent(string name, int studentNo, char gender) {
        outStream.open("StudentRecord.txt", ios_base::app);
        outStream << left << setw(15) << studentNo << setw(15) << gender << right << name << endl; 
        outStream.close();
}

I added the data 3 times and I get

    Batman   11  M   
    BatGirl  22  F
    Joker    33  M

Now comes the problem, I tried to modified the Batman line by adding additional subject scores

The result that I want:

    Batman   11  M   100  22  55 22  33
    BatGirl  22  F
    Joker    33  M

The number after the name is the subject scores.

However when I run the program to modify the specific line I get this

BatGirl        22             F              -858993460     -858993460          -858993460     -858993460     -858993460
Batman         11             M              12             86                          44             24             55
Joker          33             M              -858993460     -858993460          -858993460     -858993460     -858993460

Here's the code for specific line modification

//  Function to modify a student's exam scores.
    void Student::modifyScore(string newName, int newIndian, int newEnglish, int newMath, int newHistory, int newMoral) {


    map<string, tuple<int, char,int, int, int, int, int> > data;

    // Read file and fill data map
    ifstream studentRec("StudentRecord.txt");
    string line;

    while (getline(studentRec, line))
    {
       string name;
       int studentNo;
       char gender;
       int indian, english, math, history, moral;
       stringstream ss(line);
       ss >> name >> studentNo>> gender>> indian >> english >> math >> history >> moral;
       data[name] = make_tuple(studentNo, gender,indian, english, math, history, moral);

    }

    studentRec.close();
    // Modify data


    auto it = data.find(newName) ; // gets current student record from the map
    if (it == data.end()) // student not in map, that's an error
     return ;
    // now it->second holds your student data
    // an auto here could be better, but we want to be sure of type
    auto studentNo = get<0>(it->second) ;
    auto gender = get<1>(it->second) ;

     data[newName] = make_tuple(studentNo, gender, newIndian,newEnglish, newMath, newHistory, newMoral);


    // Open same file for output, overwrite existing data
    ofstream ofs("StudentRecord.txt");

    for (auto entry = data.begin(); entry != data.end(); ++entry)
    {
        tie(studentNo, gender, newIndian,newEnglish, newMath, newHistory, newMoral) = entry->second;
        //int average = averageScore(newIndian,newEnglish, newMath, newHistory, newMoral);

        ofs << left <<  setw(15) << entry->first << setw(15) << studentNo << setw(15) << gender << setw(15) << newIndian << setw(15) << newEnglish << setw(15) << right << newMath << setw(15) << newHistory << setw(15) <<  newMoral << endl;
    }
    ofs.close();


}

For the sake of clarity the arguments for modifyScore are

newName --> is to find the name in the file
newIndian --> Subject scores
newEnglish --> Subject scores
newMath --> Subject scores
newHistory --> Subject scores
newMoral --> Subject scores

Please point at where I made a mistake. Thank you!

airsoftFreak
  • 1,450
  • 5
  • 34
  • 64
  • If you ask a stream to extract a number and it can't, because there isn't a number at that position in the stream, it fails and the variable you were hoping to extract the number into is unchanged. In your case those variables are also uninitialized so they could contain anything. Without knowing what you expect in the case where the numbers do not exist it's hard to give advice. – Retired Ninja Jun 22 '15 at 05:51

1 Answers1

0

Issue is

   stringstream ss(line);
   ss >> name >> studentNo>> gender>> indian >> english >> math >> history >> moral;

When you encounter a 3 word line like Batman 11 M, the expression ss >> indian will fail and activate the failbit. Which means all variables after indian will not be modified. As it stands now, they are uninitialized, which explain the randomness of the values you get.

Now to fix this you should detect the number of columns in a specific line, ie the number of words in the string so you can restore the state of an unmodified line to its prior state.

unsigned int countWordsInString(std::string const& str);

bool fullrecord(std::string const& str)
{
   return countWordsInString(str) == 8;
}

map<string, tuple<int, char,int, int, int, int, int, bool> > data; //added bool
stringstream ss(line);
bool hasGrades = fullrecord(line);
if(hasGrades )
    ss >> name >> studentNo>> gender>> indian >> english >> math >> history >> moral;
else
    ss >> name >> studentNo>> gender;
data[name] = make_tuple(studentNo, gender,indian, english, math, history, moral, hasGrades);

Now use the boolean to decide whether to save a line with or without grades

Community
  • 1
  • 1
UmNyobe
  • 22,539
  • 9
  • 61
  • 90