scanf中特殊的格式控制符

    xiaoxiao2021-03-25  87

    scanf fscanf,均从第一个非空格的可显示字符开始读起!

    scanf以空白字符为定界符,但如果输入的字符串是以其它字符为定界符的,那怎么办?

    比如要读取一串字符串,以回车结尾,就可以采用scanf("%[^\n]", ...);

    根据TCPL中的描述,

    [...]  match the longest non-empty string of input characters from the set between brackets; A '\0' is added. []...]includes ]in the set.

     [符号可以作为扫描列表中的一个成员,但]字符除紧贴最左边的[字符或抑扬符两种情况外,其余情况下都不会被看作扫描列表的成员。例如“%[]abcd]”或者“%[^]abcd]”,上述两种情况下]字符属于扫描列表的成员,但如果是“%[ab]cd]”,中间的]字符不会被看作扫描列表的成员,而且输入输出的结果会是乱七八糟的。

    [^...]  match the longest non-empty string of input characters not from the set between brackets; A '\0' is added. []...]includes ]in the set.

    标准输入输出函数scanf具有相对较多的转换说明符,它常常作为入门级函数出现在各种教材中。但奇怪的是,[]和n这两种都为c89/c99所规定的标准说明符却鲜少在大多数教材中出现。

        在使用[]说明符之前,得先明白两个概念:一是扫描列表。扫描列表(scanlist)指的是包含在[和]两个字符之间除紧靠左边[字符的抑扬符之外的字符,例如:

    scanf("%[abcd]", ptr);

    abcd组成扫描列表。二是扫描字符集(scanset)。扫描字符集指的是结果字符集,例如上面的例子,结果字符集就是abcd。如果输入一个字符串“cbadkjf”,那么ptr得到的字符串是cbad,kjf三个字符都属于定界符,输入到k字符时输入字符串被截断,kjf三个字符被留在stdin里面。如果带有抑扬符,例如:

    scanf("%[^abcd]", ptr);

    扫描列表仍然是abcd,但扫描字符集是除abcd外的可输入字符。如果输入字符串“jksferakjjdf”,ptr得到的字符串是“jksfer”。如果想限制输入字符串的字符数量,可以象s说明符那样,在[]前面使用位域,例如:

    scanf("[^abcd]", ptr);

    这样结果字符串最多只能包含10个字符(除'/0'字符外)。

    对于减号-,只有在紧贴[字符或抑扬字符以及作为扫描列表最后一个成员时,-字符才会被视为扫描列表的成员。c标准把其余情况规定为编译器相关的。大多数编译器把这种情况的减号定义为连字符,例如:

    scanf("%[a-zA-Z]", ptr);

    那么扫描列表由大小写各26个字母组成。少数编译器仍旧把这种情况下的减号视为扫描列表成员。

    fscanf(fd,"%*[^/n]/n");// %*是虚读,没有存,只是让指针跳过了这个变量!

    %n说明符输出有效字符数量,%n在scanf和printf中都可使用。与%n相对应的形参是一个int类型的指针,%n不影响scanf和printf的返回值。例如:

    scanf("%d %d%n", &i, &j, &k);

    如果输入434 6434,则k等于8,而scanf的返回值仍然为2。又如:

    scanf("%c%n", &ch, &k);

    输入“sbcdefdg”后,k等于1,而不是8,因为%c只取一个字符,%n输出的是有效字符数量。

            %n用在printf函数里,表示输出的字符数量,例如:

    printf("i=%d, j=%d/n%n", i, j, &k);

    在i=343、j=123的情况下,k=12,同时%n不影响printf的返回值,其返回值仍然为12,而不是14。

    这个用法是在参H264 jm82考代码上看到的,用来从解码器参数配置文件中读取配置参数,代码如下:

    // read the decoder configuration file if((fd=fopen(config_filename,"r")) == NULL) { snprintf(errortext, ET_SIZE, "Error: Control file %s not found/n",config_filename); error(errortext, 300); }

    fscanf(fd,"%s",inp->infile);                // H.26L compressed input bitsream fscanf(fd,"%*[^/n]");

    fscanf(fd,"%s",inp->outfile);               // YUV 4:2:2 input format fscanf(fd,"%*[^/n]");

    fscanf(fd,"%s",inp->reffile);               // reference file fscanf(fd,"%*[^/n]");

    对应的配置文件内容如下:

    test.264                 ........H.26L coded bitstream test_dec.yuv             ........Output file, YUV 4:2:0 format test_rec.yuv             ........Ref sequence (for SNR)

    通过这种方式

    inp->infile = "test.264"

    inp->outfile = "test_dec.yuv"

    inp->reffile = "test_rec.yuv"

    而相应的配置文件中的一些注释则不会被读入,这是相当简便的用法,比起通过严格约定注释符并进行一个字符一个字符来解析,这种方式简单了许多!值得借鉴!

    转载请注明原文地址: https://ju.6miu.com/read-37873.html

    最新回复(0)