-3

I am currently tasked with creating a function that takes information from a file and stores it into a set of arrays. The first array is a one-dimensional array, storing names of students, while the second array is a two-dimensional array that stores the values of several tests. A sample of the input text from the file is below:

Jon 81 83 77 90
Amanda 80 91 95 93
Sarah 78 81 11 90
Aaron 92 83 44 69
Blair 23 45 96 38
Clark 60 85 45 39
Kenney 77 31 52 74
John 93 94 89 77
Sammy 79 85 28 93
Glenn 85 72 49 75
Brad 74 65 49 96

The first array is called studentNames[] and only stores the names. The second array is studentGrades[][] and stores the grades from four tests. I have run myself in about a million circles on this project so far. I thought I had a good way to get the information from the file, but I cannot figure out how to get the values out of each line.

int main()
{
    ifstream fileIn ("grades.txt");
    string line;

    for (int i = 0; i < 11; i++)
    {
        getline(fileIn, line);
        int lineLen = line.length();
        cout << line << " Length = " << lineLen << endl;
    }

    return 0;
}

That will display the lines, but I cannot figure out how to get the actual value of the pieces stored into an array. I know this question is probably poorly worded, but I am trying to figure out how to word it properly. I will update with more information if I can.

The above code gives me this output:

Jon 81 83 77 90 Length = 15
Amanda 80 91 95 93 Length = 18
Sarah 78 81 11 90 Length = 17
Aaron 92 83 44 69 Length = 17
Blair 23 45 96 38 Length = 17
Clark 60 85 45 39 Length = 17
Kenney 77 31 52 74 Length = 18
John 93 94 89 77 Length = 16
Sammy 79 85 28 93 Length = 17
Glenn 85 72 49 75 Length = 17
Brad 74 65 49 96 Length = 16

If I add the line to the main body:

string names[11];

Then add this to the loop:

fileIn >> names[i];
cout << names[i];

I end up with no change at all in the output. However, if I comment out the other cout statement that shows the lines, I get the following output:

Amanda Sarah Aaron Blair Clark Kenney John Sammy Glenn Brad

First off, the iterator "i" should be starting at 0, but it is ignoring the first name in the list. Now, if I keep the original comment and just add the names[i] to the output:

cout << line << " Length = " << lineLen << names[i] << endl;

I end up with:

Jon 81 83 77 90 Length = 15Amanda
 80 91 95 93 Length = 12Sarah
 78 81 11 90 Length = 12Aaron
 92 83 44 69 Length = 12Blair
 23 45 96 38 Length = 12Clark
 60 85 45 39 Length = 12Kenney
 77 31 52 74 Length = 12John
 93 94 89 77 Length = 12Sammy
 79 85 28 93 Length = 12Glenn
 85 72 49 75 Length = 12Brad
 74 65 49 96 Length = 12

As the output. So it is removing the names from the front of the line and sticking them in the back of the line above. In all cases, the first name on the list is ignored.

EDIT: To clarify, I have been working on the problem for three days, I am currently trying to recreate the steps I have taken over the past few days so I can show what I have done and what behavior I have encountered. It is a time-consuming process trying to recreate these steps.

Ernesto
  • 295
  • 2
  • 13
  • did you use the [search](https://stackoverflow.com/search?q=read+values+from+file+%5Bc%2B%2B%5D) ? E.g. [this one](https://stackoverflow.com/questions/17152396/read-multiple-values-from-file-with-fstream) would be a start – 463035818_is_not_an_ai Nov 03 '17 at 19:55
  • 1
    Create a `struct` or `class` `Student` and a `std::vector` instead of separate arrays. Regarding extraction of the the values, use a `std::istringstream` with each `line`. – user0042 Nov 03 '17 at 19:56
  • I would if I could, but I cannot due to the strict guidelines of the assignment. – Ernesto Nov 03 '17 at 19:57
  • I think here you can find the answer you need https://stackoverflow.com/questions/236129/the-most-elegant-way-to-iterate-the-words-of-a-string – jsn Nov 03 '17 at 19:59
  • 2
    if there are unrealistic requirements you have to mention them, otherwise you will get ansewrs that show you how to do it correctly ;) – 463035818_is_not_an_ai Nov 03 '17 at 19:59
  • @tobi303 Yes, I have read over 40 questions and answers on Stack Overflow as well as cplusplus.com forums. The one you linked is not an array, I have tried modifying it to turn it into an array, I get "0" when I try to cout the value of a grade. – Ernesto Nov 03 '17 at 20:01
  • then you better show your code and explain how it fails – 463035818_is_not_an_ai Nov 03 '17 at 20:03
  • @jsn I'm not sure how that pertains to arrays, could you clarify a little? – Ernesto Nov 03 '17 at 20:03
  • @tobi303 I can link the code I have currently, but I am so lost at this point it doesn't even make sense to me, and I wrote it. I have tried dozens of ways to do it. https://pastebin.com/XFTat29k – Ernesto Nov 03 '17 at 20:06
  • Like I said, I am on so many iterations of code right now, I don't even know how to describe what I've done. I started with the basics in the original post because that is what I started with and I could re-create that code in a couple of minutes to post the question. The rest of the code I have been adding, subtracting, commenting out, revising, etc, for three days. – Ernesto Nov 03 '17 at 20:09
  • nobody is going to write the code from scratch for you. If you have code that you think is a good start then show along with what error you are getting. And here everybody will say 'use std::vector' if you ask for them to do it from scratch cos its the correct thing to do. If you fail the assignment then you have a lousy teacher – pm100 Nov 03 '17 at 20:29
  • first thing, test that the file opened correctly – pm100 Nov 03 '17 at 20:30
  • The file opened correctly, hence the fact that it prints the information to the screen correctly. – Ernesto Nov 03 '17 at 20:30
  • @Ernesto As mentioned, the answer is simple: With c++ don't use any raw arrays, use `std::vector` or `std::array` instead. If they teach you something else, you must be in either a quite advanced course or they teach you wrong. – user0042 Nov 03 '17 at 20:40
  • @user0042 "Use at least 3 arrays: a one-dimensional array to store the students' names, a (parallel) two-dimensional floating-point array to store the homework scores, and a one-dimensional (parallel) floating-point array containing each student's average. No non-constant global variables are allowed (even if placed in a namespace)." As far as std::array and std::vector, neither of them have been introduced in class at this time. I can only use things from the lecture notes and/or the video lectures. – Ernesto Nov 03 '17 at 20:50
  • I think you just need `while(fileIn >> name >> f1 >> f2 >> f3 >> f4){...}` where you have `string name; float f1,f2,f3,f4;` and then you add those values to your array. This will work as long as name is a single word. – Barmak Shemirani Nov 03 '17 at 20:56
  • @Ernesto Well, even without putting the information together into a `Student` class, I'd prefer to use separate `std::vector` variables instantiated for the appropriate types over raw arrays, manually allocated arrays or such. – user0042 Nov 03 '17 at 20:56
  • @BarmakShemirani - https://pastebin.com/zypKVT7J I tried to do something similar to what you are saying (I am trying to use a 2D array, per assignment requirements) but the program appears to be in some sort of infinite loop or something because it just stops working. – Ernesto Nov 03 '17 at 21:27

2 Answers2

1

Just use while(file >> s >> f1 >> f2 >> f3 >> f4){} without getline

getline will read the whole line which you don't want in this case.

int main()
{
    ifstream file("file");

    const int capacity = 11;
    string names[capacity];
    float grades[capacity][4]; //<-- 4 is enough
    float average[capacity];

    string s;
    int counter = 0;
    float f1, f2, f3, f4;
    while(file >> s >> f1 >> f2 >> f3 >> f4)
    {
        //test this:
        cout << s << ", " << f1 << ", " << f2 << ", " << f3 << ", " << f4 << "\n";
        names[counter] = s;
        grades[counter][0] = f1;
        grades[counter][1] = f2;
        ...
        //calculate average...
        average[counter] = (f1 + f2 ...)/4;
        counter++;

        //the array holds 11 items only
        //break in case there are more than 11 valid lines in the file
        if (counter == capacity)
            break;
    }
    ...
}

The istream >> operator will skip blank lines and reads the next item. Note this code will not work if you have something like "Jon Green 81 83 77 90" because "Jon Green" is separated by blank. If there was name and last name then you need 2 >> operators for text. Or you need getline combined with other options like std::stringstream

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
1

@Ernesto: I would like to give an example to show how it could be used with arrays. In this example i didnt want to use any STL classes, so this code is only to show, how you can get the elements from a string:

prerequisites: each line has 5 items divided by a space-char

#include <iostream>
using namespace std;

#define ARRSIZE 5

string split(string &str) {
    string item;

    // look for the first space-char
    size_t found = str.find_first_of(" ");

    // if there are still space-chars found
    if (found != string::npos) {
        // get the item
        item = str.substr(0, found);

        // update the str (+1 because of the space-char
        str = str.substr (found+1);
    } else {
        // getting the last item
        item = str;
        // update the str one last time
        str = "";
    }

    return item;
}

int main() {
    string str = "Jon 81 83 77 90";
    string arr[ARRSIZE];
    int arrInd = 0;
    while(str.length() > 0) {
        arr[arrInd++] = split(str);
    }

    for(int i = 0; i < ARRSIZE; ++i)
        cout << arr[i] << endl;
}
jsn
  • 71
  • 4