sprintf 格式 - u 前三个 '%%%' 和 n 前两个 '%%'?
sprintf formatting - Three '%%%' before u and two '%%' before n?
在小组作业中,我们必须读取仅包含(小)字母 a-z 且字符的最大长度为 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] 的意思类似于 "read till new Line"
我在谷歌上搜索了很多,但没有找到类似的例子 - 有人可以帮助我吗?
假设 x
是一个(足够大的)字符数组
sprintf(x, "%%"); // put a single % (and '[=10=]') in x
sprintf(x, "%u", 8); // put 8 (and '[=10=]') in x
sprintf(x, "%%%u", 8); // put %8 (and '[=10=]') in x
您的合作伙伴正在使用 sprintf()
为 scanf()
动态创建格式字符串。这有点棘手,因为 printf
和 scanf
函数主要使用相同的格式化语言。动态格式创建的原因似乎是在格式中插入可配置的字段宽度。这很聪明,但过于复杂且完全没有必要。
How does the format pattern in sprintf and scanf work? Especially the three %%% before u and the two %% before n
%%%u
实际上是两个指令。第一个 %%
导致 printf
发出单个 %
字符,然后剩下 %u
,我想你已经认出了。同样,%%n
是 一个 指令(%%
,如上所述)加上文字 'n' 字符,按原样发出。整个 sprintf
调用准备了一个类似于 "%255[^\n]%n"
.
的格式字符串
那么,生成的格式如何与 scanf
一起使用?您可能应该阅读它的文档,随处可见,例如 here。那个恰好是针对 GLIBC 实现的,但是您没有使用任何非标准的东西,因此它应该解释您需要了解的有关您的特定格式的所有信息。具体来说,您费心介绍的 255 是由 [^\n]
描述的 "scanset" 中的字符组成的字段的最大字段宽度——除换行符外的每个字符。 %n
不消耗任何输入;相反,它存储了该 scanf
调用到目前为止读取的字符数。
出于您的目的,我认为绝对没有理由动态生成 scanf
格式。您 给定了 最大字段宽度,因此您不妨在文字格式字符串中使用它。即使您想要在运行时指定最大字段宽度,scanf()
也有比动态编写格式字符串更好的机制,包括将需要的字段宽度作为参数传递。
额外提示:您发布的代码在使用 *length
和 printf
中的 length
方面混淆不清和 scanf
个电话。在你想输出它的值的地方,你必须传递值(length
)。在你想要scanf
去修改值的地方,你必须传递应该存储新值的地址(*length
)。
在小组作业中,我们必须读取仅包含(小)字母 a-z 且字符的最大长度为 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] 的意思类似于 "read till new Line"
我在谷歌上搜索了很多,但没有找到类似的例子 - 有人可以帮助我吗?
假设 x
是一个(足够大的)字符数组
sprintf(x, "%%"); // put a single % (and '[=10=]') in x
sprintf(x, "%u", 8); // put 8 (and '[=10=]') in x
sprintf(x, "%%%u", 8); // put %8 (and '[=10=]') in x
您的合作伙伴正在使用 sprintf()
为 scanf()
动态创建格式字符串。这有点棘手,因为 printf
和 scanf
函数主要使用相同的格式化语言。动态格式创建的原因似乎是在格式中插入可配置的字段宽度。这很聪明,但过于复杂且完全没有必要。
How does the format pattern in sprintf and scanf work? Especially the three %%% before u and the two %% before n
%%%u
实际上是两个指令。第一个 %%
导致 printf
发出单个 %
字符,然后剩下 %u
,我想你已经认出了。同样,%%n
是 一个 指令(%%
,如上所述)加上文字 'n' 字符,按原样发出。整个 sprintf
调用准备了一个类似于 "%255[^\n]%n"
.
那么,生成的格式如何与 scanf
一起使用?您可能应该阅读它的文档,随处可见,例如 here。那个恰好是针对 GLIBC 实现的,但是您没有使用任何非标准的东西,因此它应该解释您需要了解的有关您的特定格式的所有信息。具体来说,您费心介绍的 255 是由 [^\n]
描述的 "scanset" 中的字符组成的字段的最大字段宽度——除换行符外的每个字符。 %n
不消耗任何输入;相反,它存储了该 scanf
调用到目前为止读取的字符数。
出于您的目的,我认为绝对没有理由动态生成 scanf
格式。您 给定了 最大字段宽度,因此您不妨在文字格式字符串中使用它。即使您想要在运行时指定最大字段宽度,scanf()
也有比动态编写格式字符串更好的机制,包括将需要的字段宽度作为参数传递。
额外提示:您发布的代码在使用 *length
和 printf
中的 length
方面混淆不清和 scanf
个电话。在你想输出它的值的地方,你必须传递值(length
)。在你想要scanf
去修改值的地方,你必须传递应该存储新值的地址(*length
)。