【问题标题】:Can I use gets() and puts() of same string in different functions我可以在不同的函数中使用相同字符串的gets()和puts()吗
【发布时间】:2021-07-17 16:42:11
【问题描述】:

#include <stdio.h>
#include <string.h>

struct employee
{
    char ename[20];
    int sal;
};

struct employee accept(struct employee);
void display(struct employee);

void main()
{
    struct employee e,f;
    f=accept(e);
    display(f);
}

struct employee accept(struct employee e)
{
    printf("Enter employee name and his sal :");
    gets(e.ename);
    gets(e.sal);
}

void display(struct employee e)
{
    printf("Employee name :");
    puts(e.ename);
    printf("Employee salary :");
    puts(e.sal);
} 

上面的代码是从用户那里获取详细信息,而不是按照它应该做的那样显示它。谁能帮我纠正一下?

【问题讨论】:

  • 打开并注意,您的编译器警告(您的函数accept() 被定义为返回一个值,但它没有return 语句)!您的缩进可能会更好一些,以便从鹰眼中看到代码结构。
  • 我的编译器没有给出任何警告也没有错误
  • 如果你的编译器没有给出警告,也许使用另一个? (也许改变命令行开关或配置就足够了……)
  • 你永远不应该使用gets()函数——它是far too dangerous to be used, ever!
  • @AdityaBachu 你确定你在运行-Wall -Wextra(或者你的编译器用来启用警告的任何东西)?

标签: c function struct gets puts


【解决方案1】:

您忘记返回从accept 读取的内容。

struct employee accept(struct employee e)
{
printf("Enter employee name and his sal :");
gets(e.ename);
gets(e.sal);
return e; /* add this to return things read */
}

还要注意:

  • gets()puts() 用于读取和打印字符串,而不是整数。结构声明中的int sal; 应替换为char sal[128];
  • 您应该添加缩进以提高可读性。
  • gets() 有不可避免的缓冲区溢出风险。它在 C99 中已弃用并从 C11 中删除。取而代之的是,您应该使用 fgets() 并手动删除读取的换行符。

【讨论】:

  • 请注意,gets() 在 TC3:2007(技术勘误表 3)中已被弃用 - 而不是在原始 C99 标准中。
  • 另外,使用gets(e.sal) 读入一个(未初始化的)整数——几乎不是正确的行为。将e 的(副本)传递给用作局部变量的函数也很奇怪。应省略该参数,并使用并返回常规局部变量。或者可以传递指向结构的指针,然后不需要返回(如果函数声明为void accept(struct employee *ep) 并进行了相应的其他更改)。
【解决方案2】:
  1. main 应该返回 int。使用int main(void)

  1. sal 是一个intgets 用于字符串,但你永远不应该使用它,这是非常危险的,因为没有执行目标缓冲区边界检查,允许缓冲区溢出。查看 SO C 队列图例的 this post ;)

    用途:

    fgets(e.ename, sizeof e.ename, stdin);
    

    还有:

    scanf("%d", &e.sal);
    

    请注意,您应始终检查这些函数的返回值以验证输入。


  1. puts 唯一的参数是指向 char 的指针,它不接受 int 参数。

    用途:

    printf("%d", e.sal);
    

  1. 您的accept() 函数应该返回struct employee,但它没有。

    可能的修正:

    struct employee accept(void)
    {
        struct employee e;
        printf("Enter employee name and his sal :");
        if(fgets(e.ename, sizeof e.ename, stdin) != NULL)
        {
            e.ename[strcspn(e.ename, "\n")] = '\0'; // optional, removing \n
        }
        else
        {
            //handle error
        }
        if(scanf("%d", &e.sal) != 1)
        {
            //handle error
        }
        return e;
    }
    

    用法:

    struct employee e;
    e = accept();
    

    您可以删除f,因为它不需要。

【讨论】:

  • int main(void)
  • @WilliamPursell,我想,如果我们想要适当的迂腐;)
  • @JonathanLeffler ahhhh 错过了那个,我在想我的赞美不会得到回报:)
最近更新 更多