2014-09-12 6 views
1

Я довольно новичок в C++. У меня есть текстовый документ, который выглядит следующим образом:Сохраните следующее слово, если данное слово найдено (C++)

InputFile.txt

... 
. 
.. 
. 
. 
.... 
TIME/DISTANCE =  500/ 0.1500E+05 
.. 
.. 
. 
... 
TIME/DISTANCE =  500/ 1.5400E+02 
. 
... 
... 
. 
TIME/DISTANCE =  500/ 320.0565 
.. 
.. 
. 
. 
... 

Одна линия, показанная не устает повторять на протяжении всего файла. Моя цель - сохранить все числа после 500/ в массив/вектор/другой файл/что угодно. Я знаю, как читать файл и получить строку:

string line; 
vector <string> v1; 
ifstream txtfile ("InputFile.txt"); 
if (txtfile.is_open()) 
{ 
    while (txtfile.good()) 
    { 
     while(getline(txtfile, line)) 
     { 
      // ????? 
      // if(line.find("500/") != string::npos) 
      // ????? 
     } 
    } 
    txtfile.close(); 
} 

У кого-нибудь есть решение? Или указать мне в правильном направлении?

Заранее спасибо.

Редактировать: Оба предлагаемых решения (Джерри и Галик) работают отлично. Мне нравится это сообщество. :)

+0

Цикл 'while (txtfile.good()) является избыточным, как и' if (txtfile.is_open()) ', если вы не используете его, чтобы сообщить, что файл не открывается или что-то в этом роде. – Galik

+0

@Galik - Да, часть кода после этого выводит сообщение об ошибке, если файл не найден или что-то еще. – user3845866

+0

См. Методы basic_string на странице cppreference.com. Используйте find, чтобы найти начало 500 /. Если не npos, добавьте 4 и получите s = substr (found + 4). Теперь вы можете использовать istringstream (s) >> doubleval, чтобы преобразовать его в double, если необходимо. вектор x.push_back (doubleval).Если вы хотите учиться, учитесь, читая учебные пособия. Это довольно просто. – Pihhan

ответ

3

Это один из тех редких случаев, что (IMO) может иметь смысл использовать sscanf в C++.

std::string line; 
std::vector<double> numbers; 

while (std::getline(txtfile, line)) { 
    double d; 
    if (1==sscanf(line.c_str(), " TIME/DISTANCE = 500/%lf", &d)) 
     numbers.push_back(d); 
} 

Это берет каждую строку и пытается рассматривать ее как имеющую формат, о котором вы заботитесь. Если это удалось, возвращаемое значение от sscanf будет равно 1 (количество преобразованных элементов). В случае сбоя возвращаемое значение будет 0 (т. Е. Оно ничего не конвертировало). Затем мы сохраняем его, если (и только если) произошло успешное преобразование.

Также обратите внимание, что sscanf достаточно «умный», чтобы обрабатывать одиночное пространство в строке формата в соответствии с произвольным количеством пробелов во входном файле, поэтому нам не нужно пытаться сопоставить количество пробелов точно.

Мы можем изменить это несколько. Если перед символом «/» должно быть число, но оно может быть чем-то отличным от 500, мы могли бы заменить эту часть строки формата %*d. Это означает, что sscanf будет искать номер (в частности целое число), но не назначать его чему-либо. Если он найдет что-то отличное от целого числа, преобразование завершится неудачно, поэтому (например) TIME/DISTANCE ABC/1.234 потерпит неудачу, но TIME/DISTANCE 234/1.l234 преуспеет.

+0

Я попробую это и отчитаю. Спасибо. Я не знал, что такая функциональность существует. – user3845866

+0

Не работает по какой-то причине. Я сделал то, что вы предложили, и я получаю тарабарщину как сохраненный результат. Есть идеи? '-9.25596e + 061' ' -9.25596e + 061' '-9.25596e + 061' – user3845866

+0

@ user3845866: Ой. Я просто продемонстрировал не один, а два недостатка 'scanf'. Во-первых, он не является безопасным для типов (и у меня было несоответствие между пройденным типом и тем, что строка формата сказала ему ожидать). Другое заключается в том, что хотя форматы 'scanf' в основном * такие же, как форматы' printf', они различаются в * нескольких случаях: '% f' - это формат для' double' с 'printf', но формат для 'float' с' scanf'. Вам нужно использовать '% lf' для чтения' double'. Мои извинения. –

0

При обработке строки, то вы можете использовать line.find(), чтобы проверить его правильную линию и найти ваши данные:

if(line.find("TIME/DISTANCE") != std::string::npos) 
{ 
    // this is the correct line 
} 

После того, как у вас есть правильная линия вы можете получить позицию данных, как это :

std::string::size_type pos = line.find("500/"); 

if(pos != std::string::npos) 
{ 
    // pos holds the position of the numbers you want 

    std::string wanted_numbers = lint.substr(pos + 4); // get only the numbers in a string 
} 

Надежда, что помогает

EDIT: Исправлена ​​ошибка (добавление 4 к поз, чтобы перескочить «500/"part)

+0

Я попробую это и отчитаю. – user3845866

+0

Это отлично сработало Спасибо большое, у меня есть только один вопрос о том, что я очень смущен, чтобы спросить, но я все равно, потому что мне нужно учиться. Почему номер 4 в 'pos + 4'? Это связано с хранением памяти строка или что-то? – user3845866

+0

Я отметил другой ответ как «Принято» только потому, что он дает мне числа в виде двухместных номеров, что позволяет мне сделать шаг для их преобразования. Тем не менее, я действительно ценю ваш ответ. Это было ближе к моей линии мышления – user3845866

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