sprintf格式-u之前三个'%%%',n之前两个'%%'?

时间:2018-12-06 14:46:30

标签: c printf scanf string-formatting

在小组分配中,我们必须读取仅包含(小)字母 az 的输入,并且字符的最大长度为255。我想检查一下getchar和ASCII,但是我的伴侣找到了一个使用sprintf和scanf的解决方案,我对此并不完全了解:

#include <stdio.h>

int main() {

int result = 0;

unsigned int length = 255;
char input[257];

result = readInput(input, &length);

return 1;
}

int readInput(char *output, int *length) {

char format_pattern[15]; 
sprintf(format_pattern, "%%%u[^\n]%%n", *length); 

printf("Max allowed length is %d\n",*length);

scanf(format_pattern, output, length);

printf("Input length is %d\n",*length);

return 1;

}

输出: Max allowed length is 255 testinput Input length is 9

sprintf和scanf中的格式模式如何工作? 尤其是%%%之前的三个u%%之前的两个n-我试图将其更改为%u[^\n]%n,因为两个##会逃脱´ %´,但随后出现错误,因此他们必须在那里。

我唯一想到的是:

  • %n可以读取前面的字符,例如:

    int var;
    
    printf("Some Text before%n and after",&var); 
    printf("characters before percent n = %d\n", var);
    

    输出:Some Text before and aftercharacters before percent n = 16

    但是在上面的大示例中,没有指针变量,其中 因为*length%%%u的缩写,所以可以存储大量文本?

  • [^ \ n]的含义类似于“读到新行”

我在Google上搜索了很多,但是没有找到类似的例子-有人可以帮我吗?

2 个答案:

答案 0 :(得分:3)

假设x是一个(足够大的)字符数组

sprintf(x, "%%"); // put a single % (and '\0') in x
sprintf(x, "%u", 8); // put 8 (and '\0') in x

sprintf(x, "%%%u", 8); // put %8 (and '\0') in x

答案 1 :(得分:1)

您的合作伙伴正在使用sprintf()scanf()动态创建格式字符串。这有点棘手,因为printfscanf函数大多使用相同的格式语言。创建动态格式的原因似乎是在格式中插入可配置的字段宽度。这很聪明,但过于复杂,完全没有必要。

  

sprintf和scanf中的格式模式如何工作?特别是u之前的三个%%%和n之前的两个%

%%%u实际上是两个指令。第一个%%导致printf发出一个%字符,并且留下%u,我认为您可以识别。同样,%%n one 指令(如上所述,%%)加上原义的'n'字符,该字符按原样发出。整个sprintf调用会准备诸如"%255[^\n]%n"之类的格式字符串。

那么,结果格式如何与scanf一起使用?您可能应该阅读所有可用的文档,例如here。碰巧是针对GLIBC实施的,但是您没有使用任何非标准的东西,因此它应该解释您需要了解的有关特定格式的所有信息。具体来说,麻烦介绍的255是由[^\n]描述的“ scanset”中的字符组成的字段的最大字段宽度-除换行符外的每个字符。 %n不消耗任何输入;而是存储scanf调用到目前为止读取的字符数。

出于您的目的,我认为绝对没有理由动态生成scanf格式。 给定一个最大字段宽度,因此您最好在文字格式的字符串中使用它。即使您想要在运行时指定最大字段宽度,scanf()的机制也比动态编写格式字符串更好,该机制涉及将所需字段宽度作为参数传递。

奖金提示:您发布的代码在*length和{{1}中length的使用位置以及printf的使用位置上非常混乱}电话。要输出其值的地方,必须传递值(scanf)。您要length 修改值的位置,必须传递应该存储新值的地址(scanf