gets()和scanf(“%s”)之间的区别

时间:2019-05-24 03:07:06

标签: c pointers buffer dynamic-memory-allocation

我声明了一个字符指针,并用它来在运行时扫描字符串。我不知道要输入的字符数,因此我没有使用callocmalloc。程序到达行scanf("%s", NewMsg_au8)时结束。 我正在使用CodeBlocks 17.12编辑器。

我尝试对NewMsg_au8="0123456789ABCDEF";这样的一种输入情况进行硬编码,效果很好。

uint8 * NewMsg_au8;
scanf("%s",NewMsg_au8);//<== 
printf("Your entered message is: %s\n",NewMsg_au8);
return NewMsg_au8;

2 个答案:

答案 0 :(得分:2)

gets(s)scanf("%s", s)既不安全,又可能不正确,原因是:

  • 如图所示,这些函数都无法确定要存储到s所指向的数组中的最大字符数,因此,过长的输入将导致缓冲区溢出,从而导致未定义的行为。
  • 在您的情况下,更糟糕的是s是未初始化的指针,因此这两个函数都会尝试将数据存储到内存中的随机地址中,从而在所有情况下均导致未定义的行为。

gets()无法安全使用,已被弃用并从C标准中删除。

但是,可以为scanf()设置一个介于%s之间的数值的限制:

#include <stdio.h>
#include <string.h>

char *read_string(void) {
    char buf[100];
    if (scanf("%99s", buf) == 1) {
        printf("Your entered message is: %s\n", buf);
        return strdup(buf);  /* return an allocated copy of the input string */
    } else {
        /* no input, probably at end of file */
        return NULL;
    }
}

请注意如何仅将99个字符存储到数组buf中,以允许使用空字节终止符来标记C字符串的结尾。 %99s转换规范使scanf()最多可以将100个字节存储到buf中,包括 '\0'终止符。

答案 1 :(得分:1)

这是典型的初学者错误。您不会将数据保存在指针(使用gets()或scanf())中,而是保存在缓冲区中。

因此,您有两种解决方案:

  1. 使用足够大的数组来容纳数据。您必须根据应用程序的细节来决定“足够大”的含义。

  2. 使用指针,然后使用malloc()分配内存-大小,同样,您必须确定它。当您不再需要内存时,别忘了释放它。


  

我尝试对输入情况之一进行硬编码,例如 NewMsg_au8 =“ 0123456789ABCDEF” ; —很好。

这很正常,因为在这种情况下,编译器会自动分配足够的内存来容纳字符串。


在使用字符串时,请始终记住:您始终需要为终止空字符(字符串结尾的标记)分配一个额外的字节。否则,您将需要再次提出问题:)