2011-01-22 3 views
8

У меня есть файл, полные строки в следующем формате:Как легко читать целые числа с использованием потока C++?

1 - 2: 3 

Я хочу, чтобы только цифры нагрузки с использованием C++ потоков. Какой самый элегантный способ сделать это? Я только думал о cin.get() и checikng каждого символа, если это число или нет.

ответ

5

Вы можете использовать locale к сп ange, что вещи читаются из файла по мере его чтения. То есть, вы отфильтровывать все без числовых значений:

struct numeric_only: std::ctype<char> 
{ 
    numeric_only(): std::ctype<char>(get_table()) {} 

    static std::ctype_base::mask const* get_table() 
    { 
     static std::vector<std::ctype_base::mask> 
      rc(std::ctype<char>::table_size,std::ctype_base::space); 

     std::fill(&rc['0'], &rc[':'], std::ctype_base::digit); 
     return &rc[0]; 
    } 
}; 

std::fstream myFile("foo.txt"); 
myfile.imbue(std::locale(std::locale(), new numeric_only())); 

Затем, когда вы читаете файл, он будет конвертировать все не цифры на пробелы, оставляя вам только номера. После этого вы можете просто использовать свои обычные преобразования, чтобы преобразовать то, что читается в int.

std::vector<int> intFromFile; 
std::istream_iterator<int> myFileIter(myFile); 
std::istream_iterator<int> eos; 
std::copy(myFileIter, eos, std::back_inserter(intFromFile)); 

Ответ на комментарии ниже:

Вот что я сделал, чтобы заставить его работать

int main(int args, char** argv){ 
    std::fstream blah; 
    blah.open("foo.txt", std::fstream::in); 
    if(!blah.is_open()){ 
     std::cout << "no file"; 
     return 0; 
    } 
    blah.imbue(std::locale(std::locale(), new numeric_only())); 

    std::vector<int> intFromFile; 
    std::istream_iterator<int> myFileIter(blah); 
    std::istream_iterator<int> eos; 
    std::copy(myFileIter, eos, std::back_inserter(intFromFile)); 

    return 0; 
} 

И это не только положить РАСЧ в вектор, больше ничего, ничего Меньше. Причина, по которой он не работал раньше, был в два раза:

  1. Я заполнял до '9', но не сам '9'. Я изменил заполнение на ':'
  2. Число, большее, чем может содержать int, является проблемой. Я бы предложил использовать длинный.
+0

Я пробовал; но он, похоже, не работает. – Nawaz

+0

@Nawaz ok, gimme a sec, чтобы запустить мой компилятор и посмотреть, где я совершил ошибку. – wheaties

+0

@wheaties: Кстати, идея действительно хороша, если вы заставляете ее работать. Мне бы очень хотелось, чтобы он работал. :-) – Nawaz

1
int a,b,c; 

    cin >> a; 
    cin.ignore(100,'-'); 
    cin >> b; 
    cin.ignore(100,':'); 
    cin >> c; 

    cout << "a = "<< a <<endl; 
    cout << "b = "<< b <<endl; 
    cout << "c = "<< c <<endl; 

Входной сигнал:

1 - 2: 3

Выход:

а = 1
Ь = 2
с = 3

Смотрите сами здесь: http://www.ideone.com/DT9KJ

Примечание: это может обрабатывать дополнительные пробелы также. Таким образом, вы можете прочитать даже это:

 1  -  2  :  3

Похожие темы:

Using ifstream as fscanf

+3

Be * * очень осторожна магических чисел в коде. Они * вернутся, чтобы укусить вас. –

+0

@ Konrad: вы говорите о '100' в' ignore() '? Вы можете увеличить это до того большого числа, которое, по вашему мнению, может быть лишним количеством пробелов! – Nawaz

+3

Вы могли бы, но не должны. Это ничего не меняет. Вы должны использовать 'numeric_limits :: max()', если таковые имеются. –

0

Просто

ifstream file("file.txt"); 
int n1, n2, n3; 
char tmp; 
while (file.good()) { 
    file >> n1 >> tmp >> n2 >> tmp >> n3; 
} 
+0

Это не сможет извлечь n3, если не было числовых компонентов к n1 или n2, например. –

2

Я рекомендовал бы делать по крайней мере беглый вменяемости проверяет при чтении:

int a, b, c; 
char dash, colon; 

if (not (cin >> a >> dash >> b >> colon >> c) or dash != '-' or colon != ':') 
    Failure. Do something. 
0

Sorry Конрада, но я не рекомендую: никогда от боли смерти, никогда никогданикогда (достаточно ясно? :-) читать форматированные данные из файла. Только не надо.

Существует только один правильный способ ввода данных форматирования: читать фрагменты символов (обычно строки, но вы также можете читать блоки фиксированной длины).

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

Отдельный ввод (операция ввода-вывода) от разбора.

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

Я пишу C++ в течение десятилетий, и я никогда не читал целое число.

7

Я думаю, что это один будет самым быстрым -Дополнительным elegant- путь:

int a, b, c; 
scanf("%d-%d:%d", &a, &b, &c);