0

I'm currently working on a program that's supposed to read data from a text file, and place said data in a linked list. I've got a pretty good idea of what I'm doing, but the thing is I'm supposed to include error handling that jumps to the next line if there is any errors in the data format in the file.

The file contains information about a number of terminators in the form of their model and their serial number.

An example of the data that can be read is:

TERMINATOR T-800 1

TERMINATOR T-1000 2

TERMINATOR T-800 3

TERMINATOR T-800 4

In the first row above, T-800 is the model, and 1 is the serial number. The four rows above are all valid, but if the fifth row would look something like this:

TORMONUTTUR T-800 1h6

or:

abc 2

, the data should be discarded and the program should continue reading the next row.

I'm currently lost on this, and would appreciate just a nod in the right direction, since I'm not sure how I should even begin with this problem.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 3
    "I'm currently working on a program that's supposed to read data from a text file" --> post what you have done so far to add clarity to the issues to this otherwise broad question. – chux - Reinstate Monica Jun 07 '17 at 23:25

2 Answers2

1

One way to not overwhelm yourself is to delegate different actions to different functions so you don't have to worry about everything at once. I would recommend opening the file and reading one line at a time. For each line, you can validate the format, then append the data to your linked list, otherwise do nothing and continue to the next line. That might look something like this.

char line[128];
while(fgets(line, 128, (FILE*)fh) != NULL) {
    if(isValidLine(line)) {
        // add data to linked list
    }
}

The logic is easy to understand there. You just have to define your function isValidLine to read the line to make sure it has valid data in it, and return the corresponding boolean value. To validate this, you might use sscanf or some other string tokenizer to parse the line, or do it yourself manually. For instance, check that it starts with the string "TERMINATOR " and proceed from there. One everything checks out, return true, but at any time the string fails your format requirements, return false right away.

kamoroso94
  • 1,713
  • 1
  • 16
  • 19
0

You could read try to read every part of the line as a string (because if serial number was an int for example, 1h6 would be truncated, and you would fail to check if it's valid). For the serial number string, you should check if it's really an integer, and if so convert to a number with std::stoi.

From my answer and How do I check if a C++ string is an int?, I got this:

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

inline bool isInteger(const std::string & s)
{
   if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false ;

   char * p ;
   strtol(s.c_str(), &p, 10) ;

   return (*p == 0) ;
}

int main(void)
{

    std::ifstream infile("thefile.txt");
    if (infile.is_open()) {
        int serial_number;
        std::string model, terminator, serial_number_str;
        while (infile >> terminator >> model >> serial_number_str)
        {
            if(terminator == "TERMINATOR" && isInteger(serial_number_str))
            {
                serial_number = std::stoi(serial_number_str);
                std::cout << terminator << " " << model << " " << serial_number << "\n";
            }
        }
    }
    infile.close();
    return 0;
}

which for a file of:

Georgioss-MacBook-Pro:~ gsamaras$ cat thefile.txt

TERMINATOR T-800 1

TERMINATOR T-1000 2

TERMINATOR T-800 3

TERMINATOR T-800 4

TORMONUTTUR T-800 1h6

abc 2

gives:

Georgioss-MacBook-Pro:~ gsamaras$ g++ main.cpp 
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
TERMINATOR T-800 1
TERMINATOR T-1000 2
TERMINATOR T-800 3
TERMINATOR T-800 4

You can improve it further by using std::regex to check the format of model.

gsamaras
  • 71,951
  • 46
  • 188
  • 305