C语言 建议使用 gcc 编译器替代 get() 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16939616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Suggest an alternative for gets() function, using gcc compiler
提问by amarVashishth
Trying to input more than a single string in my program's strings array, for that used :
尝试在我的程序的字符串数组中输入多个字符串,用于:
scanf("%80[^\r\n]", strings[i]);
scanf("%80[^\r\n]", strings[i]);
fgets(string[i], MAXLEN, stdin);
fgets(string[i], MAXLEN, stdin);
a custom made function was also used:
还使用了自定义函数:
int getString(char s[]) {
char ch;
int i=0;
while( (ch = getchar()) != '\n' && ch != EOF ) {
s[i] = ch;
++i;
}
s[i] = 'int getString(char s[]) {
char ch;
int i=0;
while( (ch = getchar()) != '\n' && ch != EOF ) {
s[i] = ch;
++i;
}
s[i] = 'char number[80];
if (fgets(number, sizeof(number), stdin)) {
sscanf(number, "%d", &x)
';
fflush(stdin);
return i;
}
struct vechileData
{
char vechileType[MAXLEN];
int begin_month;
int end_month;
double price;
} data[5];
int main(int argc, char const *argv[])
{
printf("Input Vechile data: \n");
int i=0;
while(i < 5) {
printf("Input vechile Type : \n");
fgets(data[i].vechileType, MAXLEN, stdin);
printf("Input begin month : \n");
scanf("%d", &data[i].begin_month);
printf("Input end monhth : \n");
scanf("%d", &data[i].end_month);
printf("Input price : \n");
scanf("%lf", &data[i].price);
++i;
}
printf("Input Vechile Type to display information about the vechile : \n");
char vech[MAXLEN];
fgets(vech, MAXLEN, stdin);
i=0;
while(i < 5) {
if (strcmp(vech,data[i].vechileType) == 0)
{
printf("vechileType: %s\n", data[i].vechileType);
printf("Begin month: %d\n", data[i].begin_month);
printf("End month: %d\n", data[i].end_month);
printf("Price : %lf\n", data[i].price);
}
++i;
}
return 0;
}
';
fflush(stdin);
return i;
}
but unable to get input with more than one string each including white spaces
但无法获得多于一个字符串的输入,每个字符串都包含空格
function gets()used to work earlier for me but since it is deprecated no alternative can be found
函数gets()以前对我有用,但由于它已被弃用,因此找不到替代方法
This is where it was used :
这是使用它的地方:
#define My_gets_N (1024 /* Some BA number */)
char *My_gets(char * str) {
char buffer[My_gets_N];
char *retval = fgets(buffer, sizeof(My_gets_N), stdin);
if (retval) {
int l = strlen(buffer);
/* fgets() saves '\n', but gets() does not */
if ((l > 0) && (buffer[l-1] == '\n')) {
l--;
}
memcpy(str, buffer, l);
str[l] = '#define?TRUNCATE_NULL(strText) \
?{ \
???int?_strlen?=?strlen(strText); \
???if?(_strlen?> 0 &&?strText[_strlen?-?1] ==?'\n')?strText[_strlen?-?1] =?'char name[5];
gets(name);
'; \
???else?while(fgetc(stdin)!='\n'); \
?}
#define?gets(strText)?fgets(strText,?sizeof(strText),?stdin);?TRUNCATE_NULL(strText);
';
return str;
}
else {
return 0;
}
}
It skips the next input to string statement during run time, "seems to"
它在运行时跳过字符串语句的下一个输入,“似乎”
回答by chux - Reinstate Monica
Your problem is really not a gets()issue.
你的问题真的不是gets()问题。
None of the scanf("%d", ...)and scanf("%lf", ...)consume the '\n'after the number and thus contribute to your issue. It is the next read of stdinto take in the '\n'. So when the next car type is read, it gets the lingering '\n'. Your 2nd car type ends up being "\n".
没有一个scanf("%d", ...)和scanf("%lf", ...)消耗'\n'后面的数字,从而导致您的问题。它是下一次读取stdin采取的'\n'。因此,当读取下一个汽车类型时,它会得到挥之不去的'\n'. 你的第二辆车类型最终是"\n"。
Use of fgets(data[i].vechileType, MAXLEN, stdin);puts a '\n'in data[i].vechileType. You likely do not want this. Your former use of gets()consumed, but did not put the '\n'in its return.
使用fgets(data[i].vechileType, MAXLEN, stdin);puts a '\n'in data[i].vechileType。你可能不想要这个。你以前的使用gets()消耗了,但没有把'\n'它归还。
I long ago gave up doing user input with scanf()due to these subtle issues.
Recommend to separate input from parsing, use fgets()and then sscanf(). Example:
scanf()由于这些微妙的问题,我很久以前就放弃了用户输入。建议将输入与解析分开fgets(),然后使用sscanf()。例子:
char name[5];
gets(name);
Your implementation of a gets()replacement differs as follows
您的gets()替换实现如下不同
1) It does not return s(or NULL or error/eof).
2) It does not set eof indicator on eof.
3) Should getchar()return a '\0', your whileloop errantly continues.
1) 它不返回s(或 NULL 或错误/eof)。
2) 它没有在 eof 上设置 eof 指示符。3) 应该getchar()返回 a '\0',您的while循环错误地继续。
Recommend that if you mustreplace gets(), do so via fgets().
建议如果您必须更换gets(),请通过fgets().
#include<stdio.h>
#include<string.h>
#define MAXLEN 50
int getString(char s[])
{
char ch;
int i=0;
while( (ch = getchar()) != '\n' && ch != EOF )
{
s[i] = ch;
++i;
}
s[i] = '##代码##';
return i;
}
struct vechileData
{
char vechileType[MAXLEN];
int begin_month;
int end_month;
double price;
}data[5];
int main(int argc, char const *argv[])
{
printf("Input Vechile data: \n");
int i=0;
while(i < 2)
{
printf("Input vechile Type : \n");
fgets(data[i].vechileType, MAXLEN, stdin);
printf("Input begin month : \n");
scanf("%d", &data[i].begin_month);
printf("Input end monhth : \n");
scanf("%d", &data[i].end_month);
printf("Input price : \n");
scanf("%lf", &data[i].price);
while((getchar())!='\n');
++i;
}
printf("Input Vechile Type to display information about the vechile : \n");
char vech[MAXLEN];
fgets(vech, MAXLEN, stdin);
i=0;
while(i < 2)
{
if (strcmp(vech,data[i].vechileType) == 0)
{
printf("vechileType: %s\n", data[i].vechileType);
printf("Begin month: %d\n", data[i].begin_month);
printf("End month: %d\n", data[i].end_month);
printf("Price : %lf\n", data[i].price);
}
++i;
}
return 0;
}
If you replacement solution needs to deal with string length > the fixed My_gets_N, other coding is needed.
如果替换解决方案需要处理 string length > the fixed My_gets_N,则需要其他编码。
回答by unwind
You must be more specific about what went wrong with the fgets()approach, that's the one I would recommend and it does work.
您必须更具体地说明该fgets()方法出了什么问题,这是我推荐的方法,并且确实有效。
Note that fgets()will input the entire line, including linefeed/carriage returns at the end, so you might need to clean those off if they're undesirable to keep.
请注意,fgets()将输入整行,包括最后的换行符/回车符,因此如果不希望保留它们,您可能需要将其清除。
回答by noobProgrammer
I don't understand how gets()worked for you, despite the warning that practically every C book post K&R gives, as it's not only deprecated, but extremely dangerous to use. Like the others have said, fgets()would definitely work if you used it correctly.
我不明白你是如何gets()工作的,尽管几乎每个 C 书帖子 K&R 都给出了警告,因为它不仅被弃用,而且使用起来非常危险。就像其他人所说的那样,fgets()如果您正确使用它肯定会起作用。
回答by prashant
Instead of replacing all the instances of uses of getswith fgets. Use following Macros:
而不是替换的用途的所有实例gets用fgets。使用以下宏:
Why use
fgets?Because it is more secure than
gets.Is
getsreally insecure?Yes. It is greedy indeed, it will accept as much food as you give, even if it can not eat.
So technically, as @halfer rightly commented below,
with the use of gets, program is prone to buffer overflow.How ?
##代码##Now provide input of more than 5 characters, it will accept it.
This would overwrite data from memory, which should not be overwritten this way.Ok with
fgets, but why use TRUNCATE_NULL macro ?fgetsis not perfect either. it will accept\n(Enter) as character to be placed in input name.
So to remove unnecessary\n, and to make sure expected functionality ofgetsis achieved we can use it.
为什么使用
fgets?因为它比
gets.是
gets真的不安全?是的。它确实是贪婪的,它会接受你给予的食物,即使它不能吃。
所以从技术上讲,正如@halfer 在下面正确评论的那样,
使用gets,程序很容易出现缓冲区溢出。如何 ?
##代码##现在提供超过 5 个字符的输入,它会接受它。
这将覆盖内存中的数据,不应以这种方式覆盖。好的
fgets,但是为什么要使用 TRUNCATE_NULL 宏?fgets也不完美。它将接受\n(Enter) 作为要放置在输入名称中的字符。
因此,为了删除不必要的\n,并确保gets实现预期的功能,我们可以使用它。
回答by Mani Shankar
Actually, there you can use while((getchar())!='\n');to avoid such type of problem and one thing there is no need to use of fflush(stdin) function.
Here's code you can use
实际上,您可以使用它while((getchar())!='\n');来避免此类问题,并且有一件事不需要使用 fflush(stdin) 函数。这是您可以使用的代码
I hope this will help you.....
我希望这能帮到您.....

