I have a quick question, I have to read in data from a file that has names and grades in it, I must take the names and store them in a string array and the grades and store them in a 2-d array. Any pointers on how to determine what to do to determine which should be stored in what, here is the data that is in the txt file


Two B Orknot 85 68 85 84 95 100 86 87 85
Mack Camp 77 73 77 79 80 73 76 73 78
Cant Never Koud 88 89 83 80 93 95 97 99 100
Eve N Ghigher 100 100 100 100 100 100 100 100 100
Tow Jammer 93 88 77 66 77 86 89 95 92
Lue Knew Lotts 98 99 97 100 100 99 96 96 97
Ah C Moto 65 67 70 77 73 69 70 66 67
Too Much 83 84 88 77 88 88 73 75 80
Al Dah Zame 90 90 90 90 90 90 90 90 90
Tu Phinish Awf 100 95 90 85 80 75 70 65 60

Dani AI

Generated

Short answer: read each input line as one string, split it into whitespace tokens, peel off the numeric tokens from the end (those are the grades) and join whatever remains at the front into the student name. That approach handles names with internal spaces and any amount of spacing between fields.

A compact, safe pattern (illustrative):

#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cctype>

static bool isIntegerToken(const std::string &s) {
    if (s.empty()) return false;
    size_t i = (s[0] == '+' || s[0] == '-') ? 1 : 0;
    for (; i < s.size(); ++i)
        if (!std::isdigit(static_cast<unsigned char>(s[i]))) return false;
    return true;
}

std::pair<std::string, std::vector<int>> parseLine(const std::string &line) {
    std::istringstream iss(line);
    std::vector<std::string> words;
    std::string w;
    while (iss >> w) words.push_back(w);

    std::vector<int> grades;
    while (!words.empty() && isIntegerToken(words.back())) {
        grades.push_back(std::stoi(words.back()));
        words.pop_back();
    }
    std::reverse(grades.begin(), grades.end());

    std::string name;
    for (size_t i = 0; i < words.size(); ++i) {
        if (i) name += ' ';
        name += words[i];
    }
    return {name, grades};
}

Why the compile error you saw: calling split.str(held[k]) inside an expression invokes the setter overload of str which returns void — that is why the compiler reports "invalid use of a void function." Construct the stream with the string (std::istringstream split(held[k]);) or call split.str() (no arg) to get the contents. Also avoid using uninitialized counters and incrementing i twice inside your loop; prefer std::vector for storage and explicit bounds checks.

For numeric parsing without exceptions, consider std::from_chars (C++17) or validate with the helper above before std::stoi. Reference: std::basic_stringstream::str (setter/getter) and std::isdigit behavior on unsigned char (cppreference, cppreference).

(As noted, isdigit is for characters; used correctly it helps, but the immediate compile error came from using the str setter in an expression. This parsing pattern should solve the name-with-spaces + trailing grades layout you posted.)

Recommended Answers

All 5 Replies

Well try including the header cctype and using the function

int isdigit(int c)

Is there any way to test if a string is an integer without having to convert the C++ string to a C_string?

Is there any way to test if a string is an integer without having to convert the C++ string to a C_string?

std::string my_str = "123abc";


for (int i = 0; i < my_str.length(); ++i)
{
if (isdigit(my_str[i]))
{
//do something
}
}

Thanks

I am getting an error out of this function, its not complete and doesn't set the values as needed yet, but I was debugging as I went along and it keeps giving me 'invalid use of a void function' whenever I try to tun the program, any pointers as to whats wrong?

void setData(string held[], int k){
    int i, j, c, r;
    string hereHoldThis[4];
    int holdThisInt[9];
    istringstream split;    // To divide the strings into substrings
        split.str(held[k]);
        for(i = 0; i < rmax; i++){
            if(isdigit(split.str(held[k])) == false){
                split >> hereHoldThis[i];
                cout << students[i] << ", ";
                i++;
            }
            else if((split.str(held[k])) == true){
                split >> holdThisInt[i];
                sGrades[c][r] = holdThisInt[i];
            }
        }
        cout << endl;
}
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.