Не %[] или[^] спецификатор в scanf(),использования sscanf() или функции fscanf() магазин входных В с завершающим нулем массив символов?
Вот что такое руководство Beez C (ссылка) рассказывает о спецификаторе формата %[]:
It allows you to specify a set of characters to be stored away (likely in an array of chars). Conversion stops when a character that is not in the set is matched.
Я был бы признателен, если бы Вы прояснили некоторые основные вопросы, вытекающие из этой посылки:
1) являются ли входные данные, полученные этими двумя спецификаторами формата, хранящимися в аргументах (типа char*) как массив символов или массив символов с завершающим символом (строкой)? Если не строка, то как сделать так, чтобы она хранилась в виде строки, в случаях как в приведенной ниже программе, где мы хотим получить последовательность символов в виде строки и остановиться, когда встречается определенный символ (в отрицаемом наборе символов)?
2) моя программа, кажется, предполагает, что обработка останавливается для спецификатора %[^|], когда встречается отрицательный символ |.Но когда он снова запускается для следующего спецификатора формата, начинается ли он с отрицаемого символа, на котором он остановился ранее?В моей программе я намерен игнорировать |, поэтому я использовал %*c.Но я проверил и обнаружил,что если я использую %c и дополнительный аргумент типа char, то символ | действительно хранится в этом аргументе.
3) и, наконец, самое главное для меня, в чем разница между передачей массива символов для спецификатора формата %s в printf() и строкой(массив символов с нулевым окончанием)?В другой моей программе под названием character array vs string я передал массив символов (не завершенный NULL) для спецификатора формата %s в printf(), и он получает напечатан так же, как и строка.В чем же разница?
//программа для иллюстрации спецификатора % [ ^ ]
#include<stdio.h>
int main()
{
char *ptr="fruit|apple|lemon",type[10],fruit1[10],fruit2[10];
sscanf(ptr, "%[^|]%*c%[^|]%*c%s", type,fruit1, fruit2);
printf("%s,%s,%s",type,fruit1,fruit2);
}
//массив символов vs строка
#include<stdio.h>
int main()
{
char test[10]={'J','O','N'};
printf("%s",test);
}
Выход JON
//использование %c вместо %*c
#include<stdio.h>
int main()
{
char *ptr="fruit|apple|lemon",type[10],fruit1[10],fruit2[10],char_var;
sscanf(ptr, "%[^|]%c%[^|]%*c%s", type,&char_var,fruit1, fruit2);
printf("%s,%s,%s,and the character is %c",type,fruit1,fruit2,char_var);
}
Выход fruit,apple,lemon,and the character is |
2 ответов:
Она завершается null. Из sscanf():
Спецификаторы преобразования s и [ всегда хранят нулевой Терминатор В дополнение к соответствующим символам. Размер целевого массива должен быть как минимум на единицу больше заданной ширины поля.
- Исключенные символы не используются набором сканирования и остаются для обработки. Альтернативный спецификатор формата:
if (sscanf(ptr, "%9[^|]|%9[^|]|%9s", type,fruit1, fruit2) == 3)Массив на самом деле null заканчивается, так как остальные элементы будут инициализированы нулем:
char test[10]={'J','O','N' /*,0,0,0,0,0,0,0*/ };Если он не был завершен null, то он будет продолжать печатать, пока нулевой символ не будет найден где-то в памяти, возможно, переполняя конец массива, вызывая неопределенное поведение. Можно вывести ненулевой конечный массив:
char buf[] = { 'a', 'b', 'c' }; printf("%.*s", 3, buf);
1) являются ли входные данные, полученные этими двумя спецификаторами формата, хранящимися в аргументы (типа char*) в виде символьного массива или массива символов с завершающим символом \0 (строка)? Если не струна, то как сделать он хранится в виде строки, в случаях, как программа ниже, где мы хотим чтобы получить последовательность символов в виде строки и остановиться, когда конкретный символ (в отрицаемом наборе символов) встречается?
Они хранятся в формате ASCIIZ - с нулем/ '\0' терминатор.
2) Моя программа, кажется, предполагает, что обработка останавливается для %[^|] спецификатор, когда встречается отрицаемый символ|.Но когда это запускается снова для следующего спецификатора формата,начинается ли он с отрицательный характер там, где он остановился раньше?В своей программе я намерен чтобы игнорировать | следовательно, я использовал %*c. но я протестировал и обнаружил, что если я использую %c и дополнительный аргумент типа char, то символ | is действительно хранится в том, что аргумент.
Он не должен потреблять следующий символ. Покажите нам ваш код, или этого не произошло ; - P.
3) и, наконец, но очень важно для меня, в чем разница между передача массива символов для спецификатора формата %s в printf() и a строка (массив символов с нулевым окончанием)?В другой моей программе под названием массив символов против строки, я передал массив символов(не NULL завершается) для спецификатора формата %s в printf (), и он печатается просто как струна было бы.В чем же разница?
(правка: ниже рассматривается вопрос выше, который говорит о поведении массива в целом и шире, чем фрагмент кода в вопросе, который конкретно поставил случай
char[10] = "abcd";и безопасен)
%sнеобходимо передать указатель на текст ASCIIZ... даже если этот текст явно находится в массиве символов, именно обязательное присутствие термина NUL определяет текстовое содержимое, а не длину массива. Вы должны аннулировать ваш массив символов или у вас неопределенное поведение. Иногда это может сойти вам с рук - например, strncpy в массиве будет NUL завершать его, если-и-только-если есть место для этого, а статические массивы начинаются с содержимого all-0, поэтому, если вы только перезаписываете перед финальным символом, у вас будет NUL, ваш пример char[10] имеет элементы, для которых значения не указаны, заполненные Nul, но вы обычно должны взять на себя ответственность за то, что что-то гарантирует NUL прекращение.
Comments