【问题标题】:Can I use scanf to capture a directive with a width specified by a variable?我可以使用 scanf 来捕获具有由变量指定的宽度的指令吗?
【发布时间】:2010-12-05 17:08:48
【问题描述】:

我有以下代码:

scanf(" %Xs %Ys", buf1, buf2);

其中 X 和 Y 应该是整数。问题是 X 和 Y 的值是编译时常量,即使我想将值硬编码到格式字符串中,我也做不到,因为我不知道这些值。在 printf 中,您可以发送一个宽度变量以及带有“%*s”的参数。 scanf 有什么类似的吗?

编辑:澄清一下,常量在 compile 时是已知的,但在 coding 时是已知的,而且我根本不知道。它们可能因平台或实现而异,并且在我完成后它们可能会发生变化。即使他们没有,我仍然不希望在格式字符串中重复缓冲区大小,准备好在我忘记保持同步时进行段错误。

【问题讨论】:

  • 编译时常量在编译时是已知的,不是吗,所以这些值可以内置到字符串中?但是后来你说你不知道这些值,所以你不能对它们进行编码......这个问题似乎自相矛盾。
  • 您可能知道,scanf() 中的“”表示“禁止对该值进行任何分配”。对于scanf()printf() 中没有任何类似于 '' 的内容。 Kernighan 和 Pike 按照 @sambowry 在“编程实践”中的建议进行操作。

标签: c scanf


【解决方案1】:

您可以使用 sprintf() 生成格式字符串:

sprintf( format, " %%%is %%%is", X, Y );
scanf(format, buf1, buf2);

编辑:太棒了,但是下面的 gcc 代码正在运行:

#include <stdio.h> 

#define LIST(...) __VA_ARGS__ 

#define scanf_param( fmt, param, str, args ) {  \ 
  char fmt2[100]; \ 
  sprintf( fmt2, fmt, LIST param ); \ 
  sscanf( str, fmt2, LIST args  ); \ 
} 

enum { X=3 };
#define Y X+1 

int main(){
  char str1[10], str2[10];

  scanf_param( " %%%is %%%is", (X,Y), " 123 4567", (&str1, &str2) );

  printf("str1: '%s'   str2: '%s'\n", str1, str2 );
}

【讨论】:

  • 如果数字是常量,会浪费运行时资源,你不觉得吗?
  • 确实如此,但更灵活。当 X 和 Y 从文件中读取等时它正在工作。
  • @LIraNuna: 不-不浪费运行时资源(因为问题的一部分说“在编译时未知的值”-尽管另一部分说“值是编译时常量”) .这就是 Kernighan 和 Pike 在“编程实践”中处理问题的方式,因为没有一个简单可靠的替代方案。
  • 我认为您需要将 LIST param 更改为 LIST(param) - 任何接受第一种形式的编译器都是错误的,需要修复。
  • @Chris:“参数”包含必要的括号。 [ 'LIST 参数' --> 'LIST (X,Y)' --> 'X,Y' ]
【解决方案2】:

你的问题不清楚。如果您不知道这些值,那么它们可能是运行时 常量,而不是编译时常量。

如果是这样(即它们是运行时常量),那么不,'scanf' 中没有这样的功能。您唯一能做的就是在运行时使用“sprintf”生成完整的格式字符串(其中嵌入了具体值),然后将该格式字符串传递给您的“scanf”。

【讨论】:

  • 很容易出现未知的编译时常量——听说过#ifdef 吗?
  • 嗯,当我说“未知”时,我的意思是“编译器在编译时未知”,因为在我看来,这是“未知”的唯一相关形式。编译时已知的“#define”清单常量可以由预处理器嵌入到格式字符串中(已在此处回答)。
【解决方案3】:

问题在于 X 的值 和 Y 是编译时常量

然后使用宏粘贴功能:

#include <stdio.h>

#define TEST 2

#define CONST_TO_STRING_(x) #x
#define CONST_TO_STRING(x) CONST_TO_STRING_(x)

int main() {
    printf("1 " CONST_TO_STRING(TEST) " 3\n");
    return 0;
}

【讨论】:

  • 如果编译时常量被定义为不是简单的无修饰整数,例如sizeof foo10 * 2500UL0x20和@987654326,这将不起作用@ 将全部失败。
  • OP 没有说明这些常量是如何声明的。如果这不是他/她的情况,则应编辑问题。
  • OP 说它们是“编译时常量”,这个术语涵盖了我的示例中的所有常量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 2013-10-22
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多