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

я есть файл, полный строк в этом формате:

1 - 2: 3

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

Ответы на вопрос(6)

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

Просто,

ifstream file("file.txt");
int n1, n2, n3;
char tmp;
while (file.good()) {
  file >> n1 >> tmp >> n2 >> tmp >> n3;
}
 Lightness Races in Orbit22 янв. 2011 г., 14:12
Это не сможет извлечь n3, если не было, например, числовых компонентов для n1 или n2.

никогда под страхомсмерть, никогданикогда никогда (это достаточно ясно? :-) читать отформатированные данные из файла. Просто не надо.

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

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

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

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

Я писал C ++ десятилетиями и никогда не читал целых чисел.

Решение Вопроса

Вы можете использоватьместо действия изменить то, что читается из файла во время чтения. То есть вы отфильтруете все нечисловые значения:

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()));

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

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;
}

И это помещает только целые числа в вектор, ни больше, ни меньше. Причина, по которой он не работал раньше, была в два раза:

Я заполнял до «9», но не до «9». Я изменил заливку на ':'Числа, превышающие то, что может хранить int, являются проблемой. Я бы предложил использовать длинные.
 wheaties22 янв. 2011 г., 15:17
@ Наваз работает. Имейте в этом.
 Nawaz22 янв. 2011 г., 14:36
@wheaties: Кстати, идея действительно хороша, если вы заставите ее работать. Я хотел бы видеть это работающим. :-)
 Nawaz22 янв. 2011 г., 14:32
Я попробовал это; но это не похоже на работу.
 wheaties22 янв. 2011 г., 14:33
@Nawaz хорошо, дай мне секунду, чтобы запустить мой компилятор и посмотреть, где я допустил ошибку.
 wheaties22 янв. 2011 г., 15:00
@ Наваз, ты прав, это не дает эффекта. Если я не смогу заставить это работать в следующие полчаса, мне придется отозвать его. Нет смысла публиковать решение, которого нет.

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

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

if (not (cin >> a >> dash >> b >> colon >> c) or dash != '-' or colon != ':')
    Failure. Do something.
    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

Подобная тема:

Использование ifstream в качестве fscanf

 Nawaz22 янв. 2011 г., 14:12
@ Конрад: ты говоришь о100 вignore()? Вы можете увеличить это до любого большого числа, которое, по вашему мнению, может быть дополнительным числом пробелов!
 Konrad Rudolph22 янв. 2011 г., 14:19
ты мог бы, но не должен. Это ничего не меняет. Вы должны использоватьnumeric_limits<streamsize>::max()если есть.
 Konrad Rudolph22 янв. 2011 г., 14:09
Бытьочень Остерегайтесь магических чисел в вашем коде. Oнибудем вернись, чтобы укусить тебя.

Ваш ответ на вопрос