2013-12-10 2 views
2

У меня есть огромный файл для разбора. Раньше он был разделен либо space, либо comma, и я использовал sscanf(string, "%lf %lf ", &aa, &bb);, чтобы получить данные в моей программе.Как разобрать цитаты и запятые в C++

Но теперь формат данных изменяется на "122635.670399999","209705.752799999" с запятой и кавычками. И я понятия не имею, как с этим бороться. На самом деле мой предыдущий код был найден в Интернете, и мне очень трудно найти подходящий документ для подобных проблем. Будет здорово, если вы можете мне порекомендовать. Благодарю.

+0

Он состоит из строк данных? Если да, почему бы не прочитать в строке, а затем проанализировать строку в запятых, а затем удалить кавычки? –

+0

Да, данные в строках. Не могли бы вы объяснить мне, как удалить цитаты? – KuN

+0

[std :: regex] (http://www.cplusplus.com/reference/regex/) Также google для «как разобрать CSV», вы должны найти достаточно информации даже на SO. –

ответ

4

Вместо того, прочитайте строку, затем удалите запятые и кавычки из строк и, наконец, преобразуйте данные в числа, я бы, вероятно, создал объект локали, который классифицирует запятые и кавычки как пробелы, imbue str с этой локалью, и читать номера без дальнейших прощаний.

// here's our ctype facet: 
class my_ctype : public std::ctype<char> { 
public: 
    mask const *get_table() { 
     static std::vector<std::ctype<char>::mask> 
      table(classic_table(), classic_table()+table_size); 

     // tell it to classify quotes and commas as "space": 
     table['"'] = (mask)space; 
     table[','] = (mask)space; 
     return &table[0]; 
    } 
    my_ctype(size_t refs=0) : std::ctype<char>(get_table(), false, refs) { } 
}; 

Используя это, мы можем прочитать что-то данных, как это:

int main() { 
    // Test input from question: 
    std::string input("\"122635.670399999\",\"209705.752799999\""); 

    // Open the "file" of the input (from the string, for test purposes). 
    std::istringstream infile(input); 

    // Tell the stream to use the locale we defined above: 
    infile.imbue(std::locale(std::locale(), new my_ctype)); 

    // Read the numbers into a vector of doubles: 
    std:vector<double> numbers{std::istream_iterator<double>(infile), 
           std::istream_iterator<double>()}; 

    // Print out the sum of the numbers to show we read them: 
    std::cout << std::accumulate(numbers.begin(), numbers.end(), 0.0); 
} 

Заметьте, что когда-то мы пропитаны поток с помощью нашего локали CTYPE огранку, мы можем только читать числа, как если бы запятые и кавычки вообще не существовали. Поскольку фаза ctype классифицирует их как белое пространство, они полностью игнорируются, не действуя как разделители между другими вещами.

Я указываю это прежде всего, чтобы четко указать, что после этой обработки нет никакой магии. Нет ничего особенного в использовании istream_iterator вместо (например) double value; infile >> value;, если вы предпочитаете это делать. Вы можете прочитать номера любого из способов, по которым вы обычно читали числа, разделенные пробелом - потому что, насколько это касается потока, это точно что у вас есть.

+0

Это работает! В дополнение к решению моего проблема, вы ответили также представили мне много нового. Кстати, если вы измените 's.imbue' на' infile.imbue' в своем коде? – KuN

+0

@KuN: К сожалению - да, я должен. Спасибо. –

1

, если у вас есть разделенная запятая данных в строках, то просто удалить " из строки, как: скажет строка str1

str1.erase(std::remove(str1.begin(), str1.end(), '"'), str1.end()); 

это удалит все вхождения "

//Use below code to convert string into float 
    float f1;  
    std::stringstream ss; 
    ss<<str1; 
    ss>>f1; 
+0

, а затем я 'sscanf' снова, чтобы прочитать данные? – KuN

+0

Вы тоже так делаете или получаете данные типа '" 122635.670399999 "' в строках, а затем удаляете '' 'и конвертируете эту строку в float.both, и решает вашу проблему. – EmptyData

+0

@KuN Я добавил код для его преобразования в float – EmptyData