2010-03-29 4 views
11

Что это лучший вариант, если я хочу, чтобы «обновить» старый C-код для новых C++ при чтении файла с запятой разделителем:Что такое современный эквивалентный (C++) стиль для старого (C-like) метода fscanf?

/* reading in from file C-like: */ 
fscanf(tFile, "%d", &mypost.nr); /*delimiter ; */ 
fscanf(tFile, " ;%[^;];", mypost.aftername);/* delimiter ; */ 
fscanf(tFile, " %[^;]", mypost.forename); /*delimiter ; */ 
fscanf(tFile, " ;%[^;];", mypost.dept);/*delimiter ; */ 
fscanf(tFile, " %[^;];", mypost.position);/* delimiter ; */ 
fscanf(tFile, "%d", &mypost.nr2); 

//eqivalent best C++ method achieving the same thing? 
+0

Интересно, насколько строго установлен fscanf? Если вы читаете все символы до точки с запятой в строке с именем, как следующая строка может прочесть пробел перед точкой с запятой? - Кроме того, 'fscanf', вероятно, не так уж плохо, если вы также можете указать максимальное количество символов для чтения где-нибудь. – UncleBens

ответ

11

Вы можете перегрузить оператор сдвига вправо на IStream для структуры , так:

std::istream& operator>>(std::istream& is, mypost_struct& mps) { 
    is >> mps.nr; 
    is.ignore(1, ';'); 
    is.getline(mps.forename, 255, ';'); 
    is.getline(mps.aftername, 255, ';'); 
    is >> mps.dept; 
    is.ignore(1, ';'); 
    is >> mps.position; 
    is.ignore(1, ';'); 
    is >> mps.nr2; 

    return is; 
} 

Затем вход так же просто, как is >> mypost;, где is является файл, который вы открыли.

Редактировать: @UncleBens Спасибо, что указали это, я забыл взять пробелы в счете. Я обновил ответ, считая, что forename и aftername, вероятно, содержат пробелы. И было это довольно неловко немного о разделителями быть в двойных кавычках ...

Я только что проверил его, используя определение структуры в соответствии с:

struct mypost_struct { 
    int nr; 
    char forename[255], aftername[255]; 
    int dept, position, nr2; 
}; 

.. и результат был, как и ожидалось.

+0

Интересно, для чего нужны все upvotes. Идея предоставления перегруженного '>>' прекрасна, но реализация (** как ** для чтения ограниченного ввода) полностью нарушена. 'ignore' не имеет этой формы, и даже если вы исправите это, это не изменит поведение' istream.operator >> 'и не использует"; " как разделитель. Это будет работать, если вход также разделен пробелами, и ни одна из строк не содержит более одного слова. – UncleBens

+0

Спасибо, что указали это :) – susmits

3

Как @susmits говорит, но вы также можете использовать возвращаемый поток, как условный, как:

if (is >> mps.nr && is.ignore(1, ";") && is >> mps.aftername && ...) { 
    // all is well ... 
} else { 
    // bad input format 
} 

или даже:

if (is >> mps.nr >> ignore(";") >> mps.aftername >> ...) { 
    // all is well ... 
} else { 
    // bad input format 
} 
1

Что это лучший вариант, если я хочу to «обновить» старый C-код до более нового C++ ...?

IMHO, лучший способ сделать это - прочитать файл по очереди и использовать regular expressions for parsing.

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

  • Нет связанных вопросов^_^