Не %[] или[^] спецификатор в 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 |

616   2  

2 ответов:

  1. Она завершается null. Из sscanf():

    Спецификаторы преобразования s и [ всегда хранят нулевой Терминатор В дополнение к соответствующим символам. Размер целевого массива должен быть как минимум на единицу больше заданной ширины поля.

  2. Исключенные символы не используются набором сканирования и остаются для обработки. Альтернативный спецификатор формата:
    if (sscanf(ptr, "%9[^|]|%9[^|]|%9s", type,fruit1, fruit2) == 3)
    
  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

    Ничего не найдено.