Для упражнения я могу взять два целых числа или две строки. Если мне нужны целые числа в качестве входных данных, мне нужно преобразовать их в строки, а если я беру строки в качестве входных данных, мне нужно преобразовать строки в целые числа. Когда я хочу ввести две строки одновременно, они каким-то образом объединяются. Если я беру целые числа и хочу преобразовать их с помощью snprintf, строки снова объединяются!
Когда я беру строки в качестве входных данных:
#include <stdio.h>
int main(){
char n[5],m[5];
scanf("%s %s",n,m);
printf("%s %s\n",n,m);
}
Ввод: 12345 56789.
но вывод: 1234556789 12346
сканер считает, что «12345 56789» — это целая строка.
Как это происходит? Разве я не указал, что n может содержать только 5 символов? Если я уменьшу n[5] до n[1], результат будет 156789 56789
Когда я беру целые числа в качестве входных данных и пытаюсь преобразовать их с помощью snprintf
:
#include <stdio.h>
#include <stdlib.h>
int main(){
int g,w,cnt=0;
scanf("%d %d",&g,&w);
char n[5], m[5];
snprintf(n,6,"%d",g);
snprintf(m,6,"%d",w);
printf("%s\n",n);
printf("%s\n",m);
}
Если я введу 12345 67894 Выход: 1234567894 67894.
Та же проблема, что и раньше. Что я могу сделать, чтобы решить эту проблему?
Спасибо, сэр. Я не знал о важности этого. Теперь это работает. @EricPostpischil
Использование %s
в scanf
опасно, если вы не ограничите его количеством символов, которые у вас есть в массиве минус 1 (чтобы оставить место для нулевого терминатора), поэтому scanf("%s %s",n,m)
должно быть scanf("%4s %4s",n,m)
При определении массива символов для хранения строки в C вы должны учитывать конец символа строки (\0), который scanf неявно помещает в массив. Итак, если вы определите char[5], вы сможете хранить строку, состоящую из 4 символов, поскольку последняя позиция массива используется для \0.
попробуйте изменить свой код следующим образом:
#include <stdio.h>
int main(){
char n[6],m[6];
scanf("%s %s",n,m);
printf("%s %s\n",n,m);
}
Спасибо. Теперь это работает. Я не знал о важности этого. Я думал это автоматически. @N3tMaster
Это все еще небезопасно. Если пользователь вводит 123456 123456
, его поведение будет неопределенным, поскольку запись будет за пределами границ.
Здесь есть несколько проблем:
Чтобы сохранить строку из 5 символов, вам нужен массив char
минимум из 6 элементов, потому что вы должны сохранить 1 дополнительный char
для нулевого завершения.
Следовательно, n
и m
должны быть:
char n[6],m[6];
Как упоминалось @TedLyngmo, использование scanf для строк так, как вы это делали, небезопасно (даже после фиксации размеров массива) и вызывает неопределенное поведение, если пользователь вводит более 5 символов в строку (из-за записи -за пределы).
Чтобы это исправить, вам следует использовать scanf
со спецификатором ширины:
Если используется спецификатор ширины, он соответствует ширине или до первого символа пробела, в зависимости от того, что появится первым.
Это делается следующим образом:
//------v---v--------
scanf("%5s %5s",n,m);
Хорошая практика требует всегда проверять возвращаемое значение от scanf
, чтобы убедиться, что оно выполнено успешно. Он возвращает:
Количество успешно назначенных аргументов приема
В вашем случае в случае успеха должно быть 2.
Полный фиксированный пример для вашего первого фрагмента:
#include <stdio.h>
#include <cstdlib>
int main() {
char n[6], m[6];
if (scanf("%5s %5s", n, m) != 2) {
// Handle error ...
return EXIT_FAILURE;
}
printf("%s %s\n", n, m);
}
Что касается вашего второго фрагмента, соответствующие проблемные проблемы указаны выше 1 и 3 (размеры массива символов и проверка возвращаемого значения из scanf
).
В массивах недостаточно места для нулевого символа, обозначающего конец.