#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
int length;
char **lines, buffer[80];
printf("How many lines do you want to enter?.\n");
scanf("%d", &length);
getchar();
lines = (char**)malloc(length * sizeof(char*));
for (i = 0; i < length; ++i) { //Scan user's lines
gets(buffer);
lines[i] = (char*)malloc(strlen(buffer) * sizeof(char) + 1);
if (!lines[i]) { //Check if allocation available
printf("Error! Out of memory!");
return endProgram;
}
strcpy(lines[i], buffer);
}
return 0;
}
我想知道为什么gets()
函数给出了关于假设extern返回int的错误,我只是试图扫描一个字符串。
答案 0 :(得分:8)
最可能的原因是gets()
function has been deprecated有一段时间了。它看起来已从您系统上的<stdio.h>
中删除。
幸运的是,这种情况很容易解决:用fgets()
替换呼叫,如下所示:
fgets(buffer, sizeof(buffer), stdin);
注意: fgets
不是gets
的替代品,因为它会在最后保留'\n'
个字符它返回的字符串中的行。这个Q&A讨论了这个问题,并提供了解决方案。
答案 1 :(得分:2)
已从C标准中删除gets()
功能。它从来都不是一个好的函数,因为没有办法告诉gets
参数缓冲区有多大,如果输入文件来自不受信任的来源,很容易导致缓冲区溢出甚至恶意攻击。您的编译器抱怨假设extern返回int 的原因是gets
系统头中不再存在<stdio.h>
的原型。
以这种方式修改代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
int length;
char **lines, buffer[81];
printf("How many lines do you want to enter?.\n");
if (scanf("%d", &length) != 1)
return 1;
getchar(); // consuming the line feed typed by the user.
lines = malloc(length * sizeof(char*));
if (lines == NULL) {
printf("Error! Out of memory!\n");
return 2;
}
for (i = 0; i < length; i++) { //Scan user's lines
if (!fgets(buffer, sizeof buffer, stdin)) {
printf("Error! Premature end of file!\n");
return 2;
}
buffer[strcspn(buffer, "\n")] = '\0'; // overwrite the final \n
lines[i] = strdup(buffer);
if (lines[i] == NULL) {
printf("Error! Out of memory!\n");
return 2;
}
}
// perform other work on the buffer.
return 0;
}
答案 2 :(得分:0)
gets()
在C99中已弃用,并从标准C中删除了C11。
OP收到警告“关于假设extern返回int”,因为它不是标准包含文件中的原型。
使用gets()
@dasblinkenlight
fgets()
使用新代码,请使用fgets()
及其怪癖。
要推广您自己的my_gets(char *dest, size_t size)
,具有高度的gets()
兼容性,代码应该:
获取与目标数组大小匹配的大小参数。
在为目标数组读取太多字符时,my_gets()
可以自由执行任何合理的功能,因为此前gets()
会导致未定义的行为。建议尽可能地填充数组,消耗字符直至'\n'
或EOF
,并返回NULL
以指示错误(可能的设置errno
)。
简单使用fgets()
是有问题的,因为传递给fgets()
的大小是字符的空间,'\n'
和'\0'
,而传递的大小到my_gets()
真的应该是角色和'\0'
所需的空间。 '\n'
被消费而未保存。
使用VLA满足这些目标的候选函数位于https://stackoverflow.com/a/34031881/2410359。