Джентльмены, всем доброго времени суток!
У меня вопрос по форматному вводу C++.
Задача следующая – нужно читать исходные данные (числа) из текстового файла древнего формата.
Каждое число записано в поле длиной восемь символов, т.е. строка файла представляет собой нечто следующее:
123 34.78 54.123 и т.п.
Проблема в том, что число может занимать все восемь символов, и тогда между соседними числами не будет пробелов. Для Fortrana здесь проблем нет, такой формат можно читать стандартными фортрановскими средствами без применения специальных ухищрений. А для C++ я не придумал ничего лучшего, чем:
чтение строки из файла целиком,
принудительная вставка пробелов между полями в прочитанную строку,
создание входного строкового потока на основе полученной строки,
и только после этого чтение чисел из указанного входного строкового потока .
Не подскажете, может быть есть способ попроще, не прибегаю к ухищрениям?
С уважением, Павел.
Форматный ввод на C++
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
- Romeo
- Сообщения: 3091
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Ну можно копировать в цикле по 8 символов в отдельный буфер, и потом преобразовывать из него в число. Наверное проще будет выглядеть код. Но в любом случае так, чтобы прочитать все числа одним махом из подобной хитрой строки, не меняя её, никак не получится.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
- Romeo
- Сообщения: 3091
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Можно даже в том же самом буфере всё делать.
P.S. Пример кода намеренно написан в С-style, так как работа напрямую с памятью там более лаконична.
Код: Выделить всё
char buff[256];
scanf("%s", buff);
auto curr = buff;
while (*curr != '\0')
{
auto next = curr + 8;
auto old = *next;
*next = '\0';
float value = .0;
sscanf(curr, "%f", &value);
printf("%f ", value);
*next = old;
curr = next;
}
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
- Romeo
- Сообщения: 3091
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Нет, резать strtok не получится. У нас нет делиметра. Числа могут быть "слипнуты"
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Кстати, а fcnanf не получится?
Код: Выделить всё
fscnaf(file, "%8f", a);
- Romeo
- Сообщения: 3091
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Да, чёрт побери, работает
Код: Выделить всё
char buff[256];
float value = .0;
scanf("%s", buff);
for (auto curr = buff; *curr != '\0'; curr += 8)
{
sscanf(curr, "%8f", &value);
printf("%f ", value);
}
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
а с std::cout есть такой же быстрый и эффективный способ форматирования текста, как с printf? Гугл мне выдавал только, что-то неудобное, по типу setw(), setfill().
- Romeo
- Сообщения: 3091
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Точно такого же нет. Это делается через упомянутые манипуляторы и, в общем-то, запись получается тоже достаточно лаконичной.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.