2

I am trying to port an old program of mine from C to C++. I am having trouble coming up with code to accomplish the task of parsing each line of a file (delimited by semi-colons). I understand that to read each line into a string, I should use std::getline() and have also read solutions involving stringstream. However, I am lost as far as parsing the line into individual variables. Previously, in C, I was using sscanf(). Here is my old code...

void loadListFromFile(const char *fileName, StudentRecordPtr *studentList) {
    FILE *fp; // Input file pointer
    StudentRecord student; // Current student record being processed
    char data[255]; // Data buffer for reading line of text file

    // IF file can be opened for reading
    if ((fp = fopen(fileName, "r")) != NULL) {
        // read line of data from file into buffer 'data'
        while (fgets(data, sizeof(data), fp) != NULL) {
            // scan data buffer for valid student record 
            // IF valid student record found in buffer
            if (sscanf(data, "%30[^,], %d, %d, %d, %d, %d, %d, %d", student.fullName, &student.scoreQuiz1,
                &student.scoreQuiz2, &student.scoreQuiz3, &student.scoreQuiz4, &student.scoreMidOne,
                &student.scoreMidTwo, &student.scoreFinal) == 8) {
                // Process the current student record into the student record list
                processStudentToList(student, studentList);
            }
        }
    }
    else {
        // Display error
        puts("**********************************************************************");
        puts("Could not open student record file.");
        puts("**********************************************************************");
    }
    // Close file
    fclose(fp);
}

And my current code, which is incomplete as I got stuck on this issue.

void Database::loadFromFile(const string filename) {
    ifstream file(filename);
    string data;
    if ( file.is_open() ) {
        cout << "Sucessfully loaded " << filename << ".\n" << endl;
        while (getline(file, data)) {
            // 
        }
    }
    else {
        cerr << "Error opening input file.\n" << endl;
    }
}

I would greatly appreciate any insight to the C++ equivalent to this approach.

EDIT: The post that this was marked as duplicate of does not answer my question. That solution does not take into account a semi-colon (or any character) delimited string.

user2864740
  • 60,010
  • 15
  • 145
  • 220
Cam
  • 45
  • 4

2 Answers2

1

I believe this is what you are after: What should I use instead of sscanf?

#include <sstream>

std::ifstream file( fileName );

if ( file ) { //Check open correctly
    std::stringstream ss;
    ss << file.getline();
    int a, b, c;
    ss >> a >> b >> c;
}
Community
  • 1
  • 1
excalibur1491
  • 1,201
  • 2
  • 14
  • 29
  • I have read this solution but am unsure on how to use this when the string is delimited by semi-colon's and not blank space. – Cam Mar 25 '16 at 03:49
  • ohh, I see the problem now. Ok, let me try a couple of things :) – excalibur1491 Mar 25 '16 at 03:54
  • 2
    @Cam perhaps this is what you're looking for? http://stackoverflow.com/questions/11719538/how-to-use-stringstream-to-separate-comma-separated-strings – yano Mar 25 '16 at 03:54
  • 1
    Another very elegant way to handle the commas / semi-colons or what have you is shown in [this](http://stackoverflow.com/a/9832875/410767) answer; then you can code `while (file >> student.fullName >> ',' >> student.scoreQuiz1 >> ','` ...etc... – Tony Delroy Mar 25 '16 at 03:57
  • Exactly what I was looking for. Thank you! – Cam Mar 25 '16 at 04:02
0

You can use std::getline and use your delimiter , with it:

Example:
A file with content "name,id,age"

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

int main()
{
   std::ifstream in_file("file", std::ios::in);
   if (!in_file.is_open()) {
      std::cerr << "File not open" << '\n';
      return -1;
   }

   std::vector<std::string> vec;
   std::string word;
   while (std::getline(in_file, word, ',')) {
      vec.emplace_back(word);
   }
   for (const auto& i : vec)
      std::cout << i << '\n';
}

Will output:

name
id
age

You can use this to store it into variables.

Andreas DM
  • 10,685
  • 6
  • 35
  • 62