substr обрезает часть строки без причины.или, по крайней мере, причина ускользает от меня - PullRequest
0 голосов
/ 14 октября 2018
#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main()
{
    string line = "";
    string firstName = "";
    string middleName = "";
    string lastName = "";
    ifstream myFile("Ch7_Ex9Data.txt");
    if(myFile.is_open()){
        while( getline (myFile, line) ){
            size_t pos = line.find(" ");
            lastName = line.substr(0, pos);

            size_t index = 0;
            for(int i = 0; i < 2; ++i){
                index = (line.find(" ", index)) + 1;
            }
            index = index - 1;
            firstName = line.substr(line.find(" "), line.find(" "));
            middleName = line.substr(index);
            cout << firstName << endl;
            //cout << firstName << " " << middleName << " " << lastName << endl;
        }
        myFile.close();
    }else{
        cout << "unable to open file" << endl;
    }
   return 0; 
}

мой текстовый файл настроен так (lastName, firstName, middleName)

Miller, Jason Brian
blair, Lisa Maria
Gupta, Anil Kumar
Arora, Sumit Sahil
Saleh, Rhonda Beth

, однако он продолжает обрезать "a" в "Rhonda", но правильно отображает имя длялюбой другой человек?

когда я использую другой компилятор (Visual Studio 2017), он печатает только имя Джейсон, затем я получаю сообщение об ошибке:

Необработанное исключение в 0x76F917D2 при тестировании.exe: исключение Microsoft C ++: std:: out_of_range в ячейке памяти 0x010FF108.

Click here to see output

Ответы [ 3 ]

0 голосов
/ 14 октября 2018

C ++ 17 решение с использованием string_view:

#include <string>
#include <string_view>

std::string line = "Saleh, Rhonda Beth";
const auto first_space = line.find(' ');
const auto last_space = line.rfind(' ');
std::string_view lastName(line.c_str(), first_space - 1);
std::string_view middleName(line.c_str() + last_space + 1);
std::string_view firstName(line.c_str() + first_space + 1, last_space - first_space - 1);

std::cout << firstName << ' ' << middleName << ' ' << lastName << std::endl;
0 голосов
/ 14 октября 2018
  • substr - не тот инструмент, который вы пытаетесь сделать.

  • Не используйте длинные ifs .Вместо if(myFile.is_open()) {...} используйте:

    if(!myFile) return -1; // error
    
  • getline имеет третий параметр - delimiter - который позволяет указать, какой символ остановит извлечение.Таким образом, вы можете попросить его остановить, когда он найдет ‘,’
  • To пропустить пробелы использовать ws функцию или манипулятор:

    ws( is ); // function
    is >> ws; // manipulator
    

Ваша фиксированная программа (предполагается, что содержимое файла правильно сформировано):

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

using namespace std;

int main()
{
  ifstream is{ "Ch7_Ex9Data.txt" };
  if (!is)
    return -1;

  string s;
  while (ws(is), getline(is, s, ',')) // skip the white-spaces, then read up to ','
  {
    cout << "First Name: " << s << endl;

    ws( is ), getline(is, s, ' ');
    cout << "Middle Name: " << s << endl;

    ws(is), getline(is, s, '\n');
    cout << "Last Name: " << s << endl;
  }

  return 0;
}
0 голосов
/ 14 октября 2018

Я не понимаю ваш код.Например, что вы пробуете в цикле:

for(int i = 0; i < 2; ++i){
    index = (line.find(" ", index)) + 1;
}

или строка

firstName = line.substr(line.find(" "), line.find(" "));

это означает: вырезать подстроку из строки, начальный индекс - line.find ("") иколичество символов - line.find (""), что неверно.Потому что вы должны показать здесь количество символов, которые должны быть вырезаны.Документация: https://en.cppreference.com/w/cpp/string/basic_string/substr

Вот почему я решил вашу проблему просто самостоятельно:

while( getline (myFile, line) ){
    // Miller, Jason Brian
    // Getting Miller 
    lastName = line.substr(0, line.find(" ") - 1); // find(" ") - 1 for removing , symbol
    line = line.substr(lastName.length() + 2); // cut out lastname from line
    firstName = line.substr(0, line.find(" "));
    middleName = line.substr(line.find(" ") + 1); // find(" ") + 1 for remove leading whitespace
    cout << firstName << " " << middleName << " " << lastName << endl;
}
...