使用gcc编译器为gets()函数建议一个替代方法

时间:2013-06-05 12:10:07

标签: c string gcc

尝试在我的程序的字符串数组中输入多个字符串,用于:

scanf("%80[^\r\n]", strings[i]);

fgets(string[i], MAXLEN, stdin);

还使用了自定义功能:

int getString(char s[]) {

    char ch;
    int i=0;

    while( (ch = getchar()) != '\n'   &&   ch != EOF ) {
        s[i] = ch;
        ++i;
    }

    s[i] = '\0';

    fflush(stdin);

    return i;
}

但无法输入多个字符串,每个字符串包含空格

函数gets()过去对我来说比较早,但由于它已被弃用,因此无法找到替代方案

这是使用它的地方:

int getString(char s[]) {

char ch;
int i=0;

while( (ch = getchar()) != '\n'   &&   ch != EOF ) {
    s[i] = ch;
    ++i;
}

s[i] = '\0';

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;
}

它在运行时跳过下一个字符串语句输入,“似乎”

5 个答案:

答案 0 :(得分:5)

您的问题确实不是gets()问题。

scanf("%d", ...)scanf("%lf", ...)都没有消耗该号码后的'\n',从而导致您的问题。这是stdin的下一次读取'\n'。因此,当读取下一个车型时,它会得到延迟'\n'。您的第二种车型最终为"\n"

使用fgets(data[i].vechileType, MAXLEN, stdin);会在'\n'中加data[i].vechileType。你可能不想要这个。您之前使用gets()消耗了,但没有将'\n'放回其中。

由于这些微妙的问题,我很久以前放弃了使用scanf()进行用户输入。 建议将输入与解析分开,使用fgets()然后sscanf()。例如:

char number[80];
if (fgets(number, sizeof(number), stdin)) {
  sscanf(number, "%d", &x)

gets()替换的实现方式如下:

1)它不返回s(或NULL或错误/ eof) 2)它没有在eof上设置eof指示符。 3)如果getchar()返回'\0',您的while循环会错误地继续。


建议如果您必须替换gets(),请通过fgets()执行此操作。

#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] = '\0';
    return str;
  }
  else {
    return 0;
  }
}

如果替换解决方案需要处理字符串长度&gt;固定My_gets_N,需要其他编码。

答案 1 :(得分:2)

你必须更加具体地了解fgets()方法出了什么问题,这是我推荐的方法,它确实有效。

请注意,fgets()将输入整行,包括最后的换行符/回车符,因此如果不希望保留它们,您可能需要将其清除。

答案 2 :(得分:1)

我不明白gets()是如何为你工作的,尽管K&amp; R几乎每个C书都给出了警告,因为它不仅被弃用,而且使用起来非常危险。就像其他人所说的那样,如果你正确使用它,fgets()肯定会有用。

答案 3 :(得分:0)

而不是用gets替换fgets的所有使用实例。使用以下宏:

#define TRUNCATE_NULL(strText) \
 { \
   int _strlen = strlen(strText); \
   if (_strlen > 0 && strText[_strlen - 1] == '\n') strText[_strlen - 1] = '\0'; \
   else while(fgetc(stdin)!='\n'); \
 }
#define gets(strText) fgets(strText, sizeof(strText), stdin); TRUNCATE_NULL(strText);
  1. 为什么要使用fgets

    因为它比gets更安全。

  2. gets真的不安全吗?

    是。它确实是贪婪的,它会接受尽可能多的食物,即使它不能吃 从技术上讲,正如@halfer在下面正确评论的那样,
    使用gets,程序容易出现缓冲区溢出

  3. 怎么样?

    char name[5];
    gets(name);
    

    现在提供超过5个字符的输入,它会接受它。
    这会覆盖内存中的数据,不应该以这种方式覆盖。

  4. 好的fgets,但为什么要使用TRUNCATE_NULL宏?

    fgets也不完美。它将接受\n(回车)作为要放入输入名称的字符。
    因此,为了删除不必要的\n,并确保实现gets的预期功能,我们可以使用它。

答案 4 :(得分:0)

实际上,你可以使用while((getchar())!='\n');来避免这种类型的问题,有一件事就是不需要使用fflush(stdin)函数。 这是您可以使用的代码

#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] = '\0';
    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;
}

我希望这会对你有帮助.....