0

My code functions as it should, however I'm in search of a more elegant solution

In this for-loop, I'm parsing a line of text from a file with data members seperated by a comma. This has been stored in vector<str>str

file in text:

bob,1,2,3
sally,5,8,6
joe,5,1,9

I need to store seperately the name and the 3 corresponding scores into their respective compartments in vector<student> s.

Any way to further condense this?

for (string currLine : str)
    {
      int pos = 0;
      int next = 0;
      next = currLine.find (',', pos);
      string name (currLine.substr (pos, next));

      pos = next + 1;
      next = currLine.find (',', pos);
      string expr (currLine.substr (pos, next));
      int a = atoi (expr.c_str());

      pos = next + 1;
      next = currLine.find (',', pos);
      expr = (currLine.substr (pos, next));
      int b = atoi (expr.c_str());

      pos = next + 1;
      next = currLine.find (',', pos);
      expr = (currLine.substr (pos, next));
      int c = atoi (expr.c_str());

      student s (name, a, b, c); //create student with extracted name and scores

      vec.push_back (s); //now push this student onto the vector
    }//end for()
SSOPLIF
  • 311
  • 1
  • 4
  • 15

2 Answers2

0

Try using the fstream and the extraction operator. You can easily store your input into individual variables.

    #include <fstream>

    .
    .
    .

    // declare variables
    fstream fin( "fileName.txt", ios::in );
    string name;
    char comma;
    int a, b, c;

    // loop until the end of the file
    while(!fin.eof())
       {
         // get one line of data from the file
         fin >> name >> comma >> a >> comma >> b >> comma >> c;

         // add to your datatype
         student s (name, a, b, c);

         // push into your vector
         vec.push_back (s);
       }
eklukovich
  • 11
  • 3
  • this fails if the score has more than one digit, also it doesn't take the numerical value of the score but the character code. – sled Jan 25 '15 at 04:13
0

You can modify the whitespace classification for your stream, introduce a "stream extractor" (operator>>()), and use std::istream_iterator<student> to insert into the vector. Here's an example of what your program can look like:

#include <iostream>
#include <vector>
#include <iterator>

class student_fmt;

struct student
{
    student() = default;
    student(std::string const& name, std::string const& a,
            std::string const& b,    std::string const& c)
        : m_name(name)
        , m_a(a)
        , m_b(b)
        , m_c(c)
    { }

    friend std::istream& operator>>(std::istream& is, student& s)
    {
        if (std::has_facet<student_fmt>(is.getloc()))
        {
            is >> s.m_name >> s.m_a >> s.m_b >> s.m_c;
        }
        return is;
    }

    void display() const
    {
        std::cout << m_name << m_a << " " << m_b << " " << m_c << '\n';
    }
private:
    std::string m_name, m_a, m_b, m_c;
};

class student_fmt : public std::ctype<char>
{
    static mask table[table_size];
public:
    student_fmt(size_t refs = 0) : std::ctype<char>(table, false, refs)
    {
        table[static_cast<int>(',')] |= space;
    }
};

student_fmt::mask student_fmt::table[table_size];

int main()
{
    std::cin.imbue(std::locale(std::cin.getloc(), new student_fmt));
    std::vector<student> v(std::istream_iterator<student>(std::cin), {});

    for (auto& c : v)
        c.display();
}
David G
  • 94,763
  • 41
  • 167
  • 253