Синтаксический анализ C ++, выборка переменного числа целых чисел из строки - PullRequest
2 голосов
/ 14 декабря 2011

У меня есть набор строк, который выглядит как
"4 7 14 0 2 блаблабла"
"3 8 1 40 блаблаблабла"
...

Первое число N соответствует количеству цифр.
По сути, формат строки - это N + 1 чисел, разделенных пробелом, за которыми следуетнеизвестным количеством ненужных символов в конце, которые мне не нужны.

Как я могу получить все числа в переменных или динамической структуре, если я не знаю число N вadvance?

Другими словами, я бы хотел что-то вроде:

sscanf(s, "%d %d %d %d",&n,&x,&y,&z);

, которое бы работало независимо от количества чисел в строке.

Ответы [ 6 ]

6 голосов
/ 14 декабря 2011

Первым делом нужно разбить ввод на строки, используя getline чтобы прочитать это. Это значительно облегчит восстановление после ошибок и ресинхронизация в случае ошибки. Это также облегчит разбор; это стратегия, которая должна быть принята почти каждый раз, когда новая строка в вход является значительным. После этого вы используете std::istringstream для разобрать строку. Что-то вроде:

std::vector<std::vector<int> > data;
std::string line;
while ( std::getline( input, line ) ) {
    std::istringstream l( line );
    int iCount;
    l >> iCount;
    if ( !l || iCount < 0 ) {
        //  format error: line doesn't start with an int.
    } else {
        std::vector<int> lineData;
        int value;
        while ( lineData.size() != iCount && l >> value ) {
            lineData.push_back( value ) ;
        }
        if ( lineData.size() == iCount ) {
            data.push_back( lineData );
        } else {
            //  format error: line didn't contain the correct
            //  number of ints
        }
    }
}
4 голосов
/ 14 декабря 2011
int input;
std::vector<int> ints;
while(std::cin >>  input)  //read as long as there is integer
       ints.push_back(input);
std::cin.clear(); //clear the error flag
//read the remaining input which most certainly is non-integer
2 голосов
/ 14 декабря 2011
std::string s = "3 54 -4 42 fdsvadsdsberwte";
std::istringstream source(s);

std::vector<int> ints;

int num = 0;
int temp = 0;

if (source >> num)  // read the first number and if it succeeds, read the rest
{
    while(source >> temp) ints.push_back(temp);
    // Here, I'd compare the size of the vector with what was
    // expected (num) and act accordingly.
}
else
{
     // format error 
} 
0 голосов
/ 14 декабря 2011

Вы можете использовать динамический массив и связанный список типа динамического массива.После прочтения строки инициализируйте массив, используя число N, и последовательно вставьте числа в каждый индекс.Вставьте узел, содержащий данные строки, в связанный список.Псевдокод:

int *lineNumbers;
lineNumbers = new int[N];

List<int*> data;
data.insert(lineNumbers);
0 голосов
/ 14 декабря 2011

Вы можете сделать это примерно так:

std::string buffer;
while(std::getline(in, buffer)) {    // read a line
    std::istringstream str(buffer);  // put line in a stringstream for parsing
    int count;
    str >> count;                    // read first number
    std::vector<int> numbers(count); // reserve space for other numbers
    for(int i = 0; i < count; i++) { // read other numbers
        str >> numbers[i];
    }
}    
0 голосов
/ 14 декабря 2011

Инициализируйте istringstream со своей строкой и прочитайте из нее:

std::istringstream ss(s);

int N;
ss >> N;

std::vector<int> a(N); //int* a = new int[N];
for (int i=0;i<N;i++)
    ss >> a[i];
...