在小组分配中,我们必须读取仅包含(小)字母 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上搜索了很多,但是没有找到类似的例子-有人可以帮我吗?
答案 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()
动态创建格式字符串。这有点棘手,因为printf
和scanf
函数大多使用相同的格式语言。创建动态格式的原因似乎是在格式中插入可配置的字段宽度。这很聪明,但过于复杂,完全没有必要。
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
。