C 程序停止使用 scanf_s

标签 c tr24731

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

这是代码:

    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;

}

最佳答案

诊断

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

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

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

Microsoft 对 scanf_s() 的定义指定:

Unlike scanf and wscanf, scanf_s and wscanf_s require the buffer size to be specified for all input parameters of type c, C, s, S, or string control sets that are enclosed in []. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable. For example, if you are reading a string, the buffer size for that string is passed as follows:

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

The buffer size includes the terminating null. You can use a width specification field to ensure that the token that's read in will fit into the buffer. If no width specification field is used, and the token read in is too big to fit in the buffer, nothing is written to that buffer.

Note

The size parameter is of type unsigned, not size_t.

_countof()运算符是 Microsoft 的扩展。它大约相当于 sizeof(s) / sizeof(s[0]) ,在本例中与 sizeof(s) 相同自 sizeof(char) == 1根据定义。

请注意,大小参数为 unsigned ,而不是 size_t正如你所期望的那样。这是 TR 24731-1 的 Microsoft 实现之间的差异领域之一。功能和 ISO/IEC 9899:2011 附录 K。标准中规定的尺寸从技术上讲是rsize_t ,但定义为 size_t范围有限(因此 r ):

The type is rsize_t which is the type size_t.

但脚注(未显示)引用 RSIZE_MAX 的定义.

另请参阅Do you use the TR 24731 'safe' functions?

修复问题中的代码

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

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() 的结果而不是仅仅假设它有效,并报告标准错误的错误。

关于C 程序停止使用 scanf_s,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30016749/

相关文章:

c - c中的不可变字符串的内存分配在哪里?

c - 将单独的 C 程序链接在一起

c - scanf_s() 缓冲区在哪里定义?

c - C中scanf和scanf_s的区别

c++ - 使用strcpy_s将字符串复制到char *

c - scanf的宽度规范和scanf_s的区别

c - 在堆栈 ADT 中声明各种类型定义

c - void 指针 = int 指针 = float 指针

C++ "Building a series to solve a function"为什么我的近似值不对?

c - 错误 : use of undeclared identifier 'errno_t'