1

I desire to output the file contents to the console using file handling. The variable marks is user defined.Now the contents are saved in the file correctly(I have attached a screenshot below). When I want to read the file the user defined functions gives inaccuarte output for the last two times. Contents of file:

  • Calculus 11
  • FoP 22
  • AP 33
  • LCA 44
  • Workshop 55
  • Pak Studies 66
  • English 77

Output

  • Calculus 11
  • FoP 22
  • AP 33
  • LCA 44
  • Workshop 55
  • Pak Studies 0
  • English 1875928375
    int marks[7],i=0;
     string subject[7]={"Calculus","FoP","AP","LCA","Workshop","Pak Studies","English"};
     ifstream file3("Task4.txt");


     while(!file3.eof())
     {
         file3>>subject[i]>>marks[i];
         cout<<subject[i]<<" "<<marks[i]<<"\n";
         i++;

     }
     file3.close();
Kh. Murad
  • 41
  • 7
  • @sweenish can you please send the correct code – Kh. Murad Jan 26 '21 at 15:59
  • @sweenish No, they are reading and immediately cout-ing the contents. What caught my eye here is that this wierd behavior only occurs after running into a two-word subject name. The >> operator always reads a single word (ie. until encountering a whitespace). Then everything could be offset. What puzzles me here is that the subject names are still read correctly. So I do not think this is going to work, but I would try to remove that one whitespace in "Pak studies" – IWonderWhatThisAPIDoes Jan 26 '21 at 16:00
  • @sweenish No, he's extracting from the file with operator>>. Also he's opening the file with std::ifstream, thus it's a bit tricky to write to the file. – Tobias Fendin Jan 26 '21 at 16:01
  • 1
    Mandatory reading: [Why eof in while loop...](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – Thomas Matthews Jan 26 '21 at 16:02
  • The problem is that the code is reading word by word, a string, int, string, int and so on. On the next to last line there's two strings then a int, it's trying to extract "Studies" into a integer which fails. – Tobias Fendin Jan 26 '21 at 16:05
  • I'd read the file line by line into a std::string and use find_last_of(' ') to split the string into a subject and a (integer) mark. – Tobias Fendin Jan 26 '21 at 16:11
  • Good catch on the read and write. The `subject` array being pre-filled makes no sense then. I've deleted my initial comment. – sweenish Jan 26 '21 at 16:25

2 Answers2

1

You have multiple problems here:

  • eof flag is only set on a failed read. This means by the time you check for it you already have a failed read.

  • streams read one token at a time, meaning you do not read the entire Pak Studies string (just "Pak").

  • then you attempt to read the second token into an integer ("Studies") which puts the stream in an error state. The stream is not in eof state though, so your loop continues, possibly traversing memory with i > 7 (and triggering undefined behavior).

The correct way (or rather "a more correct way") to do it:

  • read input as long as you have input lines:

    std::string line;
    while(std::getline(file3, line))
    {
        // find position of last space
        int pos = line.rfind(' ');
        subject[i] = line.substr(0, pos - 1);
        mark[i] = std::stoi(line.substr(pos, std::npos));
    
        i++;
        if(i == 7)
            break;
    }
    
utnapistim
  • 24,817
  • 3
  • 41
  • 76
0

Your loop should be:

while (file3>>subject[i]>>marks[i])
{
    ++i;
    cout<<subject[i]<<" "<<marks[i]<<"\n";
}

See Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong? for more details.

Thomas Matthews
  • 52,985
  • 12
  • 85
  • 144