-2

我在编程方面相当新,我在一段代码上遇到了麻烦。我正在尝试输入一个单词,但是当我运行程序并输入该单词时它停止工作。

这是代码:

    int main(void){
    char a[]= ""; 

    printf("Enter word:\n");
    scanf_s("%s", a);

    return 0;
}

我尝试将 a[] 的大小设置为 20 并使用 %19s 作为另一个问题的建议,但这也不起作用。

编辑 1. 改为char a[]= "";char a[20]= {0};没有用。

编辑 2. 添加 sizeof(a) 并且代码有效。此外,我删除了 {0},但我不知道这是否有所作为。

最终代码:

int main(void){

    char a[20]; 

    printf("Enter word:\n");
    scanf_s("%19s", a, sizeof(a));

    return 0;

}
4

2 回答 2

3

诊断

代码中有(至少)两个问题:

  1. 您没有提供任何有用的空间来存储字符串。(最初的问题定义:char a[] = "";,它——请注意——是一个长度为 1 的数组,尽管它只能保存一个长度为 0 的字符串。)

  2. 你还没有告诉scanf_s()字符串有多大。它在指向字符串的指针之后需要一个长度参数。

Microsoft 的定义为scanf_s()

scanfand不同wscanfscanf_sand要求为包含在、、、或字符串控制集wscanf_s类型的所有输入参数指定缓冲区大小。以字符为单位的缓冲区大小作为附加参数传递,紧跟在指向缓冲区或变量的指针之后。例如,如果您正在读取一个字符串,则该字符串的缓冲区大小按如下方式传递:cCsS[]

char s[10];
scanf_s("%9s", s, _countof(s)); // buffer size is 10, width specification is 9 

缓冲区大小包括终止空值。您可以使用宽度规范字段来确保读入的令牌适合缓冲区。如果没有使用宽度规范字段,并且读入的令牌太大而无法放入缓冲区,则不会向该缓冲区写入任何内容。

笔记

size 参数的类型是unsigned,而不是size_t

_countof()运算符是 Microsoft 扩展。它大约等价于,在这种情况下,它与根据定义的sincesizeof(s) / sizeof(s[0])相同。sizeof(s)sizeof(char) == 1

请注意, size 参数是unsigned,而不是size_t您所期望的。这是TR 24731-1功能的 Microsoft 实施与 ISO/IEC 9899:2011 的附件 K 之间的差异领域之一。标准中指定的尺寸在技术上是rsize_t,但它被定义为size_t具有限制范围(因此是r):

type is rsize_twhich is type size_t

但脚注(未显示)指的是 的定义RSIZE_MAX

另请参阅您是否使用 TR 24731 的“安全”功能?

修复问题中的代码

Microsoft 引用中的示例在很大程度上展示了如何修复您的代码。你需要:

int main(void)
{
    char a[4096];
    
    printf("Enter word:\n");
    if (scanf_s("%s", a, (unsigned)sizeof(a)) != 1)  // Note cast!
        fprintf(stderr, "scanf_s() failed\n");
    else
        printf("scanf_s() read: <<%s>>\n", a);
    
    return 0;
}

请注意,我检查了结果,scanf_s()而不是仅仅假设它有效,并且报告了标准错误的错误。

于 2015-05-03T17:16:01.147 回答
2

使用

char a[]="";

创建一个足以容纳单个字节的数组。您必须分配足够的空间,例如:

char a[20] = {0}; // Can hold a string length 19 + \0 termination

使用你的方法,你会得到一个溢出,因为它scanf_s会在内存中写入比你分配的更多,从而导致分段错误。

于 2015-05-03T17:07:16.123 回答