6.3.2 克服gets_s函数的缺陷

在C语言中函数gets_s是从stdin流中读取字符串的函数,此函数接受从键盘上输入的字符直到遇到Enter键时终止。函数gets_s的原型是:

    char* gets(char *buff);

例如:

    #include <stdio.h>
    int main(void)
    {
            charstr[30];
            while(! str! = gets_s (str));
            printf("%s\n", str);
            return 0;
    }

如果读取成功,gets_s函数的返回值是和str值相同的指针,否则返回空指针。

函数gets_s是一个危险的函数,原因是用户在键盘上输入的字符个数可能大于缓冲区的最大值,而函数gets_s并不对其检查。当用户在键盘上输入多个数据时,程序有可能会发生崩溃。解决方法是重写一个新的函数gets_s,原型是:

    char* Gets(int maxlen)

这个函数可让程序员指定输入字符的最大个数,在函数中为字符分配存储空间,函数返回char*。

这个函数是针对动态数组而编写的,例如:

    int main(void)
    {
            char*p;
        p=Gets(18);
    }

函数gets_s中的参数舍弃传入指针的原因是传入函数的指针可能不可靠,这样会造成程序崩溃,比如传入一个野指针。

另一个gets_s函数的原型是:

    char* const Gets(char* const array, int maxlen);

这个函数针对固定长度的字符数组进行输入,例如:

    int main(void)
    {
        charstr[20];
        Gets(str,20);
        return 0;
    }

此时函数gets_s中的有一个参数是char* const类型,原因是它允许程序员修改这个类型指针所指向的内容,但不能修改指针本身。具体实现代码如下。

    #include <string.h>
    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <io.h>
    char* Gets(int maxlen)
    //最多从键盘上读入maxlen个字符,返回字符串指针类型
    {
            int i;
            staticchar* str;
            char c;
            str=(char*)malloc(sizeof(char) *maxlen);
            if(! str)
            {
                  perror("memeoryallocation error! \n");
                  return0;
            }
            else
            {
                  for(i=0; i<maxlen; i++)
                  {
                          c=getchar();
                          if(c! ='\n')str[i]=c;
                          elsebreak;
                  }
                  str[i]='\0';
                  returnstr;
            }
    }

    char* const Gets(char* const array, int maxlen)
    {
            int i;
            char c;
            for(i=0; i<maxlen; i++)
            {
                  c=getchar();
                  if(c! ='\n')array[i]=c;
                  elsebreak;
            }
            array[i]='\0';
            returnarray;
    }

    int main(void)
    {
            char s[8];
            Gets(s,8);
            puts(s);
    fflush(stdin); //刷新输入缓冲区,这很重要,否则会影响下一个Gets函数
        char*p=Gets(8);
            puts(p);
            return 0;
    }