scanf(),sscanf()或fscanf()中的%[]或%[^]说明符是否将输入存储在以null结尾的字符数组中?

Rüp*_*ure 4 c string scanf format-specifiers character-arrays

以下是Beez C指南 (LINK)讲述%[]格式说明符的内容:

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*)中的那两个格式说明符作为字符数组或带有\0终止字符(字符串)的字符数组获取输入吗?如果不是字符串,如何将其存储为字符串,在下面的程序中我们想要将字符序列作为字符串获取并在遇到特定字符(在否定字符集中)时停止?

2)我的程序似乎建议%[^|]|遇到否定字符时处理停止为说明符.但是当它再次为下一个格式说明符启动时,它是否从之前停止的否定字符开始?在我的程序中我打算忽略|因此我使用过%*c.但我测试并发现如果我使用%c和另一个类型的参数char,那么该字符|确实存储在该参数中.

3)最后但对我来说至关重要的是,为%s格式说明符传递字符数组printf()和字符串(NULL终止字符数组)之间的区别是什么?在我的另一个程序标题中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);
}
Run Code Online (Sandbox Code Playgroud)

//字符数组vs字符串

#include<stdio.h>

int main()
{
char test[10]={'J','O','N'};
printf("%s",test);
}
Run Code Online (Sandbox Code Playgroud)

产量 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);

}
Run Code Online (Sandbox Code Playgroud)

产量 fruit,apple,lemon,and the character is |

hmj*_*mjd 6

  1. 它被终止.来自sscanf():

    转换说明符s和[除了匹配的字符外,还始终存储空终止符.目标数组的大小必须至少大于指定的字段宽度.

  2. 扫描集未消除排除的字符并仍待处理.另一种格式说明符:

    if (sscanf(ptr, "%9[^|]|%9[^|]|%9s", type,fruit1, fruit2) == 3)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 该数组实际上是空终止的,因为剩余的元素将被初始化为零:

    char test[10]={'J','O','N' /*,0,0,0,0,0,0,0*/ };
    
    Run Code Online (Sandbox Code Playgroud)

如果它不是null终止,那么它将继续打印,直到在内存中找到空字符,可能超出数组的末尾导致未定义的行为.可以打印非null终止的数组:

    char buf[] = { 'a', 'b', 'c' };
    printf("%.*s", 3, buf);
Run Code Online (Sandbox Code Playgroud)