【问题标题】:sprintf formatting - Three '%%%' before u and two '%%' before n? [closed]sprintf 格式化 - 在 u 之前有三个“%%%”,在 n 之前有两个“%%”? [关闭]
【发布时间】:2018-12-06 14:46:30
【问题描述】:

在小组作业中,我们必须读取仅包含(小)字母 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] 的意思类似于“读到新行”

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

【问题讨论】:

  • " 字符的最大长度为 255" - 这是什么意思? char 具有固定大小的 CHAR_BIT 位(通常远小于 255)。还有这是哪种语言,C 还是 C++?为什么用两种不同的语言标记它?如果你的伙伴想出了这个代码,他应该能够解释。 (除非您的合作伙伴的名字是“google”)
  • 要了解格式字符串,您可以简单地检查format_pattern 中的结果。您可以简单地打印它或在调试器中观察它。在大多数情况下,查看结果有助于了解发生了什么。
  • "但是我的伙伴找到了一个使用 sprintf 和 scanf 的解决方案,我不太明白:" --> 为什么不问问你的伙伴呢?

标签: c printf scanf string-formatting


【解决方案1】:

假设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

【讨论】:

  • 所以我的代码sprintf(format_pattern, "%%%u[^\n]%%n", *length); 的意思是:“将 %256 (*length)、[^\n] 和 %n 放入 format_pattern”对吗?
  • 对,除了 *length 是 255 :)
【解决方案2】:

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

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

%%%u 实际上是 两个 指令。第一个%% 导致printf 发出一个% 字符,然后留下%u,我想你认识它。类似地,%%none 指令(%%,如上所述)加上一个文字“n”字符,按原样发出。整个sprintf 调用准备了一个类似于"%255[^\n]%n" 的格式字符串。

那么,生成的格式如何与scanf 一起使用?您可能应该阅读它的文档,到处可用,例如here。那个恰好是用于 GLIBC 实现的,但是您没有使用任何非标准的东西,因此它应该解释您需要了解的有关特定格式的所有信息。具体来说,您费力引入的 255 是由[^\n] 描述的“扫描集中”中的字符组成的字段的最大字段宽度——除换行符之外的每个字符。 %n 不消耗任何输入;相反,它存储到目前为止由 scanf 调用读取的字符数。

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

额外提示:您发布的代码在您的printfscanf 调用中的*lengthlength 使用位置非常混乱。在您想要输出其值的地方,您必须传递该值 (length)。如果您希望scanf 修改该值,则必须传递应该存储新值的地址 (*length)。

【讨论】:

    猜你喜欢
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-02
    • 2016-12-12
    • 2019-10-18
    • 2012-12-28
    • 2016-03-07
    相关资源
    最近更新 更多