为什么gets()读取到指针的字符数超过了我在使用calloc()初始化它时设置的限制?

为什么gets()读取到指针的字符数超过了我在使用calloc()初始化它时设置的限制?,c,memory-management,dynamic,calloc,gets,C,Memory Management,Dynamic,Calloc,Gets,我正在尝试获取动态内存分配,我只希望我的程序从用户那里获取一个字符串和应该从该字符串中打印的最大字符数,然后只输出该字符串,直到我使用calloc分配的字符数。当我运行程序时,它完全忽略了我使用calloc()为它设置的限制,只打印出整个字符串 我尝试使用malloc,但结果相同。另外,当我第一次尝试打印输入的文本时,我取消了对文本的引用,但这导致程序在您输入要打印的字符串后停止 #include <stdio.h> #include <stdlib.h> #includ

我正在尝试获取动态内存分配,我只希望我的程序从用户那里获取一个字符串和应该从该字符串中打印的最大字符数,然后只输出该字符串,直到我使用
calloc
分配的字符数。当我运行程序时,它完全忽略了我使用
calloc()
为它设置的限制,只打印出整个字符串

我尝试使用
malloc
,但结果相同。另外,当我第一次尝试打印输入的文本时,我取消了对文本的引用,但这导致程序在您输入要打印的字符串后停止

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

int main()
{
    int max;
    char *text = NULL;

    printf("\n\n");
    printf("Please enter the limit for the string as a positive integer: \n");
    scanf("%d", &max);

    text = (char *)calloc(max, sizeof(char));

    if (text != NULL)
    {
        printf("Please enter the string you want printed: \n");
        scanf(" "); //read in next character so it pauses
        gets(text);

        printf("Inputted text is : %s\n", text);
    }

    free(text);
    text = NULL;


    return 0;
}

我将代码改为使用
fgets
,并进行了一些更正。它返回的字符数比用户输入的“最大值”少1个字符。另外,使用
fgets
是否意味着我不需要为
calloc
操心?

当您分配内存并将其分配给指针时,无法从手中的指针推断内存大小。因此,
获取
没有机会(因此不会检查)它是否会超过您保留的内存量。顺便说一句:
get
不再是C标准的一部分(从C11开始)。改为使用
fgets
,并将
max
作为参数传递:

if (fgets(text, max, stdin)) {
   // something successfully read in
   text[strcspn(text, "\n")] = '\0';
}

请注意,
fgets
,与
gets
相反,保留所有输入的新行,并将其保留在
文本的末尾。要消除此问题,可以使用
text[strcspn(text,“\n”)]='\0'
,这将使字符串以新行字符(如果有)结尾

当您分配内存并将其分配给指针时,无法从手中的指针推断内存大小。因此,
获取
没有机会(因此不会检查)它是否会超过您保留的内存量。顺便说一句:
get
不再是C标准的一部分(从C11开始)。改为使用
fgets
,并将
max
作为参数传递:

if (fgets(text, max, stdin)) {
   // something successfully read in
   text[strcspn(text, "\n")] = '\0';
}

请注意,
fgets
,与
gets
相反,保留所有输入的新行,并将其保留在
文本的末尾。要消除此问题,可以使用
text[strcspn(text,“\n”)]='\0'
,这将使字符串以新行字符(如果有)结尾

我认为代码忽略max变量的确切原因是,当标准输入上提供的字符串长于max时,get()函数正在写入文本字符数组中的所有空字节。这是我们总是说“从不使用get()”的众多原因之一


更具体地说,get()将继续从stdin写入数组,直到它到达换行符或EOF字符,而不考虑它的边界。如果只是未定义的行为,您会看到整个字符串被打印出来。

我认为您的代码忽略max变量的确切原因是gets()当标准输入上提供的字符串长度超过max时,函数正在写入文本字符数组中的所有空字节。这是我们总是说“从不使用get()”的众多原因之一


更具体地说,get()将继续从stdin写入数组,直到它到达换行符或EOF字符,而不考虑它的边界。如果只是未定义的行为,您会看到整个字符串被打印。

因为它不知道该限制有多大。-这是一个问答,解释了为什么不使用以及如何处理(关键建议是“永远不要使用
get()
)。请注意,
gets()
不再是标准C的一部分-它已从C11标准中删除。有关如何安全使用
scanf()
的信息,请参阅。“只想让我的程序获得字符串”-->详细信息,
fgets()
不读取字符串。它尝试读取一行(包括
'\n'
之前键入的所有字符),然后通过显示空字符将其转换为字符串。读取3个字符和(4个字符)需要5个字符才能另存为字符串。Y.J.,具体一点。准确发布键入的内容。使用
fgets()
仍然意味着您需要分配正确的内存量(如果愿意,您可以使用
malloc()
而不是
calloc()
(我会使用
malloc()
)-您需要同时允许换行符和空终止符。如果您不允许换行符,它将留在输入流中,准备混淆下一个I/O操作。如果您希望I/O代码进行内存分配,请查看POSIX。另外,请注意,您的编辑会使答案无效-这不是犹太教的。在您完成回答,您需要更仔细地修改问题。我已恢复了原始问题文本(将“关于
fgets
不安全的警告”的引用更改为“关于
获取
不安全的警告”,这是一个更合理的警告),然后分别添加修改后的代码和注释。这使原始答案仍然有意义,而消除
get()
则没有意义。因为它不知道该限制有多大。-这是一个问答,解释了为什么不使用以及如何处理它(关键建议是“永远不要使用
get()
)。请注意,
gets()
不再是标准C的一部分-它已从C11标准中删除。有关如何安全使用
scanf()
的信息,请参阅。“只想让我的程序获取字符串”-->详细信息,
fgets()
不读取字符串。它尝试读取一行(所有键入的字符,包括
“\n”
,然后通过显示空字符将其转换为字符串。要读取3个字符,并且(4个字符)需要5个字符保存为字符串。Y.J.,请具体说明。准确地发布您键入的内容。使用
fgets()
仍然意味着您需要分配corr