У меня есть код, который сканирует строку и сохраняет значения в нескольких временных переменных.
Вот пример кода:
char str[] = "# # Time=80 interval";
char hash1, hash2;
char timeStr[20];
sscanf(str, "%c %c %[^\0]s", &hash1, &hash2, timeStr);
printf("hash 1: %c\n", hash1);
printf("hash 2: %c\n", hash2);
printf("Time String: %s\n", timeStr);
Фактический результат:
hash 1: #
hash 2: #
Time String:
Ожидаемый результат:
hash 1: #
hash 2: #
Time String: Time=80 interval
Я изменил код, и он работает:
sscanf(str, "%c %c **%[^\n]s**", &hash1, &hash2, timeStr);
Это устаревший код %[^\0]s
и сейчас он не работает.
Может ли кто-нибудь случайно помочь понять, почему он работал раньше и перестал работать сейчас?
В этот строковый литерал вы вставили \0
:
"%c %c %[^\0]s"
Функция scanf
увидит все, вплоть до \0
, поэтому она видит строку формата.
"%c %c %[^"
Некоторые составители могут даже пожаловаться на это и сказать «no closing ']' for '%[' format
».
Более того, %[^\n]s
должно быть просто %[^\n]
. %[
...]
и %s
— разные спецификаторы преобразования. Кроме того, всегда проверяйте возвращаемое значение scanf
.
Может ли кто-нибудь случайно помочь понять, почему он работал раньше и перестал работать сейчас?
Предыдущий компилятор, по-видимому, обрабатывал незавершенную последовательность %[^
как %[^\0]
, чтобы допустить подобные ошибки, и в этом случае вы, вероятно, могли бы просто использовать "%c %c %[^"
со старым компилятором. Новый компилятор не поддерживает это расширение.
Кстати, побег тоже не решает проблему Демо
Спасибо @Ted, понял. Я не ожидаю новой строки во входной строке. Я просто хочу прочитать все символы до конца строки. Как вы думаете, [^\n] — правильный выбор. Более ранняя реализация, похоже, [^\0] предназначена для чтения всех символов до тех пор, пока не встретится завершающий символ '\0'
@PriyankaChauhan Если вы придерживаетесь scanf
, просто используйте любой символ, которого гарантированно нет в строке. \n
часто хорошо, но есть много других, которые вы могли бы использовать. Лично я бы полностью отказался от scanf
и использовал std::string
и вспомогательные функции C++, например std::getline
.
@Jarod42 Нет, вот бы прочитать всё до первого \ или 0
:-)
Что вам нужно, так это регулярные выражения, которые являются частью STL, начиная с C++11. И
sscanf
не работайте с регулярными выражениями. Итак, если вы намеренно не придерживаетесь C++98, он очень прост в использовании и к тому же портативен cplusplus.com/reference/regex