2010-02-02 2 views
14

C++ не является моим предпочтительным языком.Нужна основная помощь в синтаксическом анализе строки в C++

У меня есть файл, который содержит это:

e 225,370 35,75 

Я хочу, чтобы отделить е, 225, 370, 35 и 75 друг от друга в полукокс и Интс, но у меня возникают проблемы. Я пробовал делать все, что я нашел в Интернете, и в моей книге на C++, и все же это не работает. Пожалуйста помоги.

Мне было бы легче сделать это на Java.

+0

Расскажите, что у вас есть. – bmargulies

+0

Спасибо, ребята. C++ очень расстраивает меня, когда я сначала изучил Java. –

+2

Хотя иногда это может расстраивать, это помогает удержать некоторые мощные библиотеки, которые не всегда связаны напрямую, как с Java. Представьте себе, насколько разочаровывает Java, если бы все, что у вас было, было основным языком и отсутствием библиотек. – joshperry

ответ

-1
#include <iostream> 
#include <fstream> 

using namespace std; 

int main() 
{ 
     ifstream f("a.txt"); // check for errors. 

     char ch,dummy; 
     int i1,i2,i3,i4; 

     f>>ch>>i1>>dummy>>i2>>i3>>dummy>>i4; 

     cout<<ch<<endl<<i1<<endl<<i2<<endl<<i3<<endl<<i4<<endl; 

     return 0; 
} 
2

Предполагая, что вы читали данные в строки ...

  1. strchr, как String.index.
  2. strtol, как Integer.parseInt()

Что вам еще нужно?

+1

strtok был бы более удобным, чем strchr –

+0

'strtok' не является потокобезопасным, хотя, если это проблема. – greyfade

2
#include <fstream> 

/* ... */ 

ifstream file; 
file.open("yourfile.txt"); 
char c, dummy; 
int i[4]; 
file >> c >> i[0] >> dummy >> i[1] >> i[2] >> dummy >> i[3]; 
file.close(); 
+0

Я не уверен в поведении, поскольку я не программист на C++, но я был бы удивлен, если бы это просто проигнорировало запятые в файле. Имеет ли это? – danben

+0

@danben: он может, но по умолчанию он не будет. Даже самые преданные программисты на С ++ никогда не касаются частей библиотеки, необходимых для того, чтобы игнорировать запятые (вам нужно создать пользовательский «ctype facet», создать «locale», содержащий этот «facet», а затем «imbue» stream with это 'locale'). –

+0

@danden, Ты прав. Я обновил свое решение. –

4

Если у вас есть контроль над форматом, это будет (немного) легче читать, если вы исключите запятые, и просто ввод как

е 225 370 35 75

В этом формате код Poita_ для чтения данных будет работать [редактировать: он с момента обновления кода, чтобы явно читать и пропускать запятые]. В противном случае, вам нужно явно пропустить через запятые:

char ingore1, ignore2; 
char ch; 
int i[4]; 

file >> ch >> i[0] >> ignore1 >> i[1] >> i[2] >> ignore2 >> i[3]; 

[Edit: если вы параноик или действительно нужно, чтобы подтвердить свой вклад в этот момент вы можете проверить, что ignore1 и ignore2 содержат запятые.]

в большинстве случаев, однако, данные, вероятно, связаны, так что вы хотите, чтобы прочитать всю строку в одну структуру (или класса):

struct data { 
    char ch; 
    int i[4]; 

    std::istream &operator>>(std::istream &is, data &d) { 
     char ignore1, ignore2; 
     return is >> ch >> i[0] >> ignore1 >> i[1] >> i[2] >> ignore2 >> i[3]; 
    } 
}; 

сделав это, вы можете прочитать весь data объект за один раз:

std::ifstream infile("my data file.txt"); 
data d; 

infile >> d; 

Или, если у вас есть целый файл полного из них, вы можете прочитать их все в вектор:

std::vector<data> d; 

std::copy(std::istream_iterator<data>(infile), 
    std::istream_iterator<data>(), 
    std::back_inserter(d)); 
+0

Ницца. Я обычно возился с методами поиска строк и substr. – StackedCrooked

3

Если вы хотите использовать старомодное выполнение C

FILE * pf = fopen(filename, "r"); 
char e; 
int a, b, c, d; 
int ii = fscanf(pf, "%c %d,%d %d,%d", &e, &a, &b, &c, &d); 
if (ii < 5) 
    printf("problem in the input file"); 
fclose (pf); 

изменить: добавлена ​​проверка ошибок на основе комментариев от dreamlax

+1

Этот очень чистый вид. Хотя, не забудьте проверить, что возвращаемое значение 'fscanf' равно 5, чтобы гарантировать, что все переменные были назначены соответствующим образом. – dreamlax

+1

В этих ситуациях я считаю, что fscanf превосходит возможности C++. – StackedCrooked

+0

Что происходит со всем диском по уценкам на этот ответ? текущая оценка +4 -3, и ни одна уценка, желающая объяснить, почему. –

2

Использование Boost Tokenizer для разделения строки. Я предполагаю, что только первый маркер представляет собой символ, так что образец кода будет что-то вроде:

#include <iostream> 
#include <boost/tokenizer.hpp> 
#include <string> 
#include <vector> 

using namespace std; 

... 

typedef boost::tokenizer<boost::char_separator<char> > tokenizer; 

string teststring("e 225,370 35,75"); 
boost::char_separator<char> separators(", "); 
tokenizer tokens(teststring, separators); 
vector<string> substrings; 
for (tokenizer::iterator iter = tokens.begin(); iter != tokens.end(); ++iter) 
{ 
    substrings.push_back(*iter); 
} 

и, вуаля, у вас есть все ваши подстрок в аккуратном векторе.Символ находится в substrings [0] как std :: string, а следующие значения int находятся в подстроках [1] и следующих ниже, также как std :: string. Вам нужно будет преобразовать их в целые значения. Для этого я предлагаю вам посмотреть на строковый поток.

+0

Библиотеки Boost можно найти здесь: http://www.boost.org/users/download/ – Demi

13

C++ String Toolkit Library (StrTk) имеет следующее решение проблемы:

 
int main() 
{ 
    std::string data("e 225,370 35,75"); 
    char c1; 
    int i1,i2,i3,i4; 
    strtk::parse(data,", ",c1,i1,i2,i3,i4); 
    return 0; 
} 

Больше примеров можно найти Here

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