2015-12-07 4 views
-3

Я делаю упражнение для колледжа, и мне нужно сравнить добавленную строку, включая заголовок <string> и символ.Преобразование простого преобразования на C++

У меня есть текстовый файл с несколькими строками данных переписи, как

Алабама AL 4849377
Аляска AK 736732
штата Аризона AZ 6731484

Я хочу, чтобы прочитать название штата каждой строки со строковой переменной, но сравнение - это единственное, что я прошу, потому что там, где у меня есть ошибка.

У меня есть этот фрагмент кода:

struct Census{ 
    string name; 
    int population, code; 
}; 

struct States{ 
    Census state; 
}; 

typedef States Vector[US_STATES]; 

void loadCensus(ifstream & census, Vector stats){ 
    int i=0; 
    string readData; 
    string line; 
    while (getline(census, line)) { 
     stringstream linestream(line); 
     while (linestream >> readData) { 
      if (linestream >> stats[i].state.name >> 
       stats[i].state.code >> 
       stats[i].state.population) 
      { 
       std::cerr << "Bad input on line " << i << ": " << line << std::endl; 
      } 
      stats[i].state.name=readData; 
      stats[i].state.code=readData; 
      stats[i].state.population=readData; 
      i++; 
     } 
    } 
} 

Как следует преобразовать readData в целое число для назначения статистику [I] .state.population = readData? Я получаю сообщение об ошибке в строке 17 в linestream >> readData.

+0

Пожалуйста, пост [Minimal, полный и проверяемых пример] (http://stackoverflow.com/помощь/mcve). –

+0

Вы, вероятно, хотите * указать * свою строку, но код, который вы предоставили, на самом деле недостаточно, чтобы точно сказать. См. [* Как создать минимальный, полный и проверенный пример *) (https://stackoverflow.com/help/mcve). – 5gon12eder

+0

Вы имели в виду использовать строку '' \ n "'? – immibis

ответ

0

census >> readData будет читать следующее слово (любая группа символов без пробелов) с ввода. Чтобы сделать это, он отбросит все пробелы на своей охоте за следующим словом. '\n' - это пробел, поэтому вы никогда не прочтете его с оператором >>, не играя в игры, которые, вероятно, вы не хотите играть.

Вместо >> используйте std::getline, чтобы прочитать строку, а затем используйте std::stringstream, чтобы разбить линию на слова.

std::string line; 
while (std::getline(census, line)) { 
    std::stringgstream linestream(line); 
    while (linestream >> readData) { 
     statistics.state[i]=readData; 
     i++; 
    } 
} 

Но ...

Я не верю statistics.state[i]=readData; делает совсем то, что вы хотите сделать. Вы, наверное, хотите что-то подобное:

std::string line; 
while (std::getline(census, line)) { 
    std::stringstream linestream(line); 
    if (!(linestream >> statistics.state[i].name >> 
         statistics.state[i].abbreviation >> 
         statistics.state[i].population)) 
    { 
     std::cerr << "Bad input on line " << i << ": " << line << std::endl; 
    } 
    i++; 
} 

В этом state становится массив или вектор объектов, которые, вероятно, выглядит чем-то вроде

struct statestats 
{ 
    std::string name; 
    std::string abbreviation; 
    int population; 
}; 

разбив его построчно

std::stringstream linestream(line); 

делает строковый поток. Строковый поток представляет собой поток, такой как cin и cout, или fstream, но содержит строку. Основное использование - буферизация и построение строк с тем же синтаксисом, который вы использовали бы в другом потоке. В этом случае мы используем его для разделения строки на слова.

if (linestream >> statistics.state[i].name >> 
        statistics.state[i].abbreviation >> 
        statistics.state[i].population) 

Нужно обрабатывать несколько частей в нескольких частях. Над всем это аббревиатура от

if (linestream >> statistics.state[i].name && 
    linestream >> statistics.state[i].abbreviation && 
    linestream >> statistics.state[i].population) 

Каждый этап считывается из линейного потока в переменную.

Далее оператор >> возвращает поток, который считывается, и это используется в примере двумя способами. Первый позволяет цепочки. Выход один >> используется в качестве входа в следующий, так что если вы посмотрите на >> как вы бы функцию (and it is a function. See Stream extraction and insertion for more) вы можете думать об этом выглядеть примерно так:

linestream.read(statistics.state[i].name).read(statistics.state[i].abbreviation).read(statistics.state[i].population) 

Синтаксис >> просто облегчает работу.

Следующее преимущество, которое вы получаете от возврата потока, - это поток, который можно протестировать, чтобы убедиться, что поток по-прежнему хорош. Он имеет boolean operator, который вернет true, если поток находится в хорошем состоянии и может использоваться.

if(linestream) 
{ 
    good 
} 
else 
{ 
    bad 
} 

вступит хорошо, если поток открыт, не достиг конца потока, и не было никаких проблем чтения или записи данных.

Возвращаясь к нашему примеру

if (linestream >> statistics.state[i].name >> 
        statistics.state[i].abbreviation >> 
        statistics.state[i].population) 

Вступит тело из if заявления, если поток успешно считаны все три значения из потока. Это не то, что мы хотим. По электронной почте Ой. Я уже исправил вышеуказанный код.

if (!(linestream >> statistics.state[i].name >> 
        statistics.state[i].abbreviation >> 
        statistics.state[i].population)) 

войдет в тело, если if по крайней мере, одно значение не читался какой-либо причине и распечатать сообщение об ошибке. Обычно, когда есть ошибка, вам нужно будет clear the error, прежде чем продолжить, но в этом случае мы используем весь поток и собираемся его отбросить.

Предполагая, что не произошла ошибка все данные из этой строки было прочитано, и нет никакой необходимости

stats[i].state.name=readData; 
stats[i].state.code=readData; 
stats[i].state.population=readData; 
+0

Благодарим вас за рекомендацию. Посмотрите на код, который я обновил, пожалуйста. –

+0

И еще один вопрос только для любопытства, я видел много людей, набирающих std :: вместо «using namespace std». Зачем? –

+0

[Хорошее чтение в 'using namespace std;' issue.] (Http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) версия TL; DR пространство имен std огромен, и 'using namespace std' вытаскивает все это в глобальное пространство имен. Скажем, вы делаете функцию 'distance'. Какое 'расстояние' будет использоваться? Ваш 'расстояние' или' std :: distance'? С 'using namespace std;' они теперь имеют одинаковое имя. 'pow' и' std :: pow' немного отличаются. Кого вызвали? – user4581301

1

Вместо этого вы хотите использовать функцию getline(). Я думаю, что это функция-член ifstream или сравнить не readData со строкой ("\ n") - двойная кавычка. Или поместите прочитанные данные в строку и проверьте, содержит ли sting '\ n'.

Смежные вопросы