Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中返回ReadLine()函数?_C_String_Function_Readline - Fatal编程技术网

如何在C中返回ReadLine()函数?

如何在C中返回ReadLine()函数?,c,string,function,readline,C,String,Function,Readline,我有点困在这里。。。当两次使用此conReadLine()函数时,它返回的地址与我前面读取的第二个字符串相同。例如,如果它两次请求一个名称,我输入“NameA”和“NameB”,则存储的结果是“NameB”和“NameB”。我理解为什么会发生这种情况,但我不知道如何解决它。将“buffer”声明为static也会做同样的事情。如何让此函数在每个字符串上返回单独的地址 const char *conReadLine(void) { char buffer[MAX_BUFFER];

我有点困在这里。。。当两次使用此
conReadLine()
函数时,它返回的地址与我前面读取的第二个字符串相同。例如,如果它两次请求一个名称,我输入“NameA”和“NameB”,则存储的结果是“NameB”和“NameB”。我理解为什么会发生这种情况,但我不知道如何解决它。将“buffer”声明为static也会做同样的事情。如何让此函数在每个字符串上返回单独的地址

const char *conReadLine(void)
{   
    char buffer[MAX_BUFFER];

    fgets(buffer, MAX_BUFFER, stdin);

    // Check for newline character.
    char *newline = strchr(buffer, '\n');
    if (newline)
        *newline = '\0';  

    return buffer;
}
这是一部经典之作

函数返回指向内部变量(缓冲区)的指针。因此,基本上,您的数据位于内存(堆栈)的一部分,对其他函数的连续调用将覆盖它

在这种情况下,当您两次调用同一个函数时,变量的位置完全相同。因此,写入
nameA
的内存将被
nameB
和以下调用覆盖

更有趣的是:创建一个函数

const char *intermediate(void) {
  char buffer[MAX_BUFFER];
  return conReadLine();
}
第一次呼叫conReadLine,第二次呼叫intermediate。额外的函数调用和局部变量将“释放”内存位置,因此它将不再覆盖它

两种解决方案:

1) 不要将数据存储在静态定义的缓冲区中,而是使用
malloc
从堆中获取一些内存(记住在不再需要时释放它)

2) 在第一次调用之后,将缓冲区的内容复制到另一个位置,以便在需要时可以对其进行分发

欢迎来到C指针的世界

这样做:

const char *conReadLine(void)
{   
    char buffer[MAX_BUFFER];
    // something
    return buffer;
}
正在返回指向解除分配堆栈的指针,这非常糟糕。它还带来了不可预知的结果,包括将同一地址与其他调用甚至其他函数一起重用

您需要这样做:

const char *conReadLine(void)
{   
    char *buffer = (char*)malloc(MAX_BUFFER);
    // something
    return buffer;
}

每次都会给你一个新的记忆位置。只需记住在使用完后释放它。

要突出显示代码,请将所有行缩进4个空格。(还有,tabs?Ew.)代码猴子,是的。如果你想要更多,你就得付钱。我正在考虑用它自己的内存分配缓冲区并返回它。但这也可能会产生一些有趣的bug。为什么它有C++标签?C++的方式会有很大的不同。2是不可接受的。返回指向自动内存的指针是不正确的。正确的方法是将缓冲区(在自动存储中)及其长度作为参数传递,并在函数中将数据复制到该缓冲区中。是的。强烈建议在生产中使用选项1。但是,如果您想了解它是如何工作的,请检查解决方案2。我可以看到它是如何“工作”的,而不是。这就像OP的解决方案一样,是一种未定义的行为,而它确实对您有效这一事实是一种侥幸。当存在一个定义更明确(并且从复制的数据量来看成本更低)的选项时,没有理由使用这个选项。如果你喜欢摆弄闪烁灯和旋钮,这就是C很有趣的原因之一。你必须认真思考你在做什么,否则结果会一团糟。编写C代码时不允许松懈。学习很好。学习正确的方法更好。为什么当你能教正确的方法时教错了方法?在C中有些人认为将代码返回> MalOC/<代码>的返回值是不好的做法,但是+1是第一个说“返回堆栈内存是坏的”。Chris Lutz:为什么他们认为这是一个坏的实践?仅仅因为它不是必需的?如果您忘记了
#包含
malloc
被隐式声明为
int malloc(size\u t)
,这在
sizeof(int)
的平台上是一个问题,指针值将被自动截断,可能会破坏
malloc
返回的所有指针。此外,如果
缓冲区的类型更改(例如,更改为
wchar\u t
),您还必须更改强制转换。这可能会变得很乏味,尤其是如果您经常使用
malloc
realloc
char*buffer=malloc(BUFSIZE*sizeof*buffer)
将起作用,无论
buffer
更改为什么类型。@Chris Lutz:malloc是隐式定义的吗?它应该来自libc,libc是平台的,甚至是特定于配置的,这是编译器不应该知道的。调用
int malloc(size\u t)
与调用
void*malloc(size\u t)
堆栈不同,因此它们无法在x64平台上组合在一起。不,它不是隐式定义的。如果您忘记了
#包含
,则在您首次使用
malloc
时,根据C89规则,它将隐式声明为返回一个
int
。调用没有什么不同,只是返回值不同,这就是为什么如果隐式声明(在意外情况下)生成的程序集将是错误的。幸运的是,GCC在隐式声明标准库函数时发出警告,但并非所有编译器都发出警告。