0

I have a txt file with a lot of things in it. The lines have this pattern: 6 spaces then 1 int, 1 space, then a string. Also, the 1st line has the amount of lines that the txt has.

I want to put the integers in an array of ints and the string on an array of strings.

I can read it and put it into an array , but only if I'm considering the ints as chars and putting into one array of strings.When I try to separate things I have no idea on how I'd do it. Any ideas?

The code I used for putting everything in an array was this:

int size()
{
    ifstream sizeX;
    int x;
    sizeX.open("cities.txt");
    sizeX>>x;

    return x;
};


int main(void)
{   
    int size = size();
    string words[size];

    ifstream file("cities.txt");
    file.ignore(100000,'\n');

    if(file.is_open())
    {
        for(int i=0; i<size; i++)
        {
            getline(file,words[i]);
        }
    }
}
ST3
  • 8,826
  • 3
  • 68
  • 92

1 Answers1

0

Just to start I'm going to provide some tips about your code:

  • int size = size(); Why do you need to open the file, read the first line and then close it? That process can be done opening the file just once.

  • The code string words[size]; is absolutely not legal C++. You cannot instantiate a variable-length-array in C++. That C feature has been not included in C++ standard (some ref). I suggest you to replace with std::vector, which is more C++ code.


Here I write a snippet of function which perform what you need.

int parse_file(const std::string& filename,
                std::vector<std::string>* out_strings,
                std::vector<int>* out_integers) {
  assert(out_strings != nullptr);
  assert(out_integers != nullptr);

  std::ifstream file;
  file.open(filename, std::ios_base::in);
  if (file.fail()) {
    // handle the error
    return -1;
  }

  // Local variables
  int num_rows;
  std::string line;

  // parse the first line
  std::getline(file, line);
  if (line.size() == 0) {
    // file empty, handle the error
    return -1;
  }
  num_rows = std::stoi(line);

  // reserve memory
  out_strings->clear();
  out_strings->reserve(num_rows);
  out_integers->clear();
  out_integers->reserve(num_rows);

  for (int row = 0; row < num_rows; ++row) {
    // read the line
    std::getline(file, line);
    if (line.size() == 0) {
      // unexpected end of line, handle it
      return -1;
    }

    // get the integer
    out_integers->push_back(
        std::stoi(line.substr(6, line.find(' ', 6) - 6)));

    // get the string
    out_strings->push_back(
        line.substr(line.find(' ', 6) + 1, std::string::npos));
  }
  file.close();

  return 0;
}

You can definitely improved it, but I think it's a good point where to start.

The last suggest I can give you, in order to improve the robustness of your code, you can match each line with a regular expression. In this way you can be sure your line is formatted exactly how you need.

For example:

std::regex line_pattern("\\s{6}[0-9]+\\s[^\\n]+");
if (std::regex_match(line, line_pattern) == false) {
  // ups... the line is not formatted how you need
  // this is an error
}
Community
  • 1
  • 1
BiagioF
  • 9,368
  • 2
  • 26
  • 50