c - 为什么这个结构数组只访问第一个元素并显示其余元素的段错误?

标签 c arrays struct

我花了三个小时试图弄清楚为什么我在这个特定案例中遇到段错误,并且我就这个主题提出了很多问题,但我仍然无法将它与我的案例联系起来。

现在我好像知道问题出在哪里了,但我不知道为什么。

我的结构数组似乎没有正确初始化。

我从用户输入的所有值都在主函数中正确显示,但是当我进入 calc_bonus(..) 函数时,它在 i=0 时正确运行,但在 i=1 时给出段错误& 那里。

这是一个简单的作业问题,我成功地解决了(使用天真的方法正确地获得了所有测试用例)但我想知道我的主要解决方案哪里出了问题。 这是我试图找出 netsalary 和奖金的初始代码。

#include <stdio.h>
#include <stdlib.h>

struct Employee
{
    char empid[50];
    int basicsalary;
    int pf;
    int mediclaim;
    float salespercentage;
    int bonus;
    float netsalary;
};

int calc_NetSalary(struct Employee**,int);
int calc_Bonus(struct Employee**,int);

int main()
{
    int n,i;
    puts("Enter total records");
    scanf("%d",&n);
    struct Employee *emp = malloc(n*sizeof(*emp));
    int flag[n];
    for(i=0;i<n;i++)
    {
        puts("Enter the employee id");
        scanf(" %[^\n]s",emp[i].empid);
        puts("Enter the basic salary");
        scanf("%d",&emp[i].basicsalary);
        puts("Enter the PF amount");
        scanf("%d",&emp[i].pf);
        puts("Enter the mediclaim amount");
        scanf("%d",&emp[i].mediclaim);
        puts("Enter the sales percentage");
        scanf("%f",&emp[i].salespercentage);
        if(emp[i].basicsalary<0||emp[i].pf<0||emp[i].mediclaim<0||emp[i].salespercentage<0)
            flag[i]=1;
        else
            flag[i]=0;
        emp[i].bonus=calc_Bonus(&emp,i);
        emp[i].netsalary=calc_NetSalary(&emp,i);
    }
    for(i=0;i<n;i++)
    {
        if(flag[i])
            printf("Unable to calculate salary for the ID %s\n",emp[i].empid);
        else
           printf("Net salary for the ID %s is Rs.%.2f\n",emp[i].empid,emp[i].netsalary);
    }
    free(emp);
}

int calc_Bonus(struct Employee **emp,int i)
{

    if(emp[i]->basicsalary<=7000 && emp[i]->salespercentage<=10)
        return 1500;
    else if(emp[i]->basicsalary<=7000 && emp[i]->salespercentage>=10)
        return 3000;
    else if(emp[i]->basicsalary<=15000 && emp[i]->basicsalary>7000 && emp[i]->salespercentage<=10)
        return 2000;
    else if(emp[i]->basicsalary<=15000 && emp[i]->basicsalary>7000 && emp[i]->salespercentage>=10)
        return 4000;
    else if(emp[i]->basicsalary>15000 && emp[i]->salespercentage<=10)
        return 2500;    
    else if(emp[i]->basicsalary>15000 && emp[i]->salespercentage>=10)
        return 4500;

}

int calc_NetSalary(struct Employee **emp,int i)
{
    int a=emp[i]->basicsalary-emp[i]->pf-emp[i]->mediclaim+emp[i]->bonus;
    return a;
}

现在我尝试通过为不同的迭代打印出 bonus 和 netsalary 的值来调试它,它只适用于 i=0 & 给出 12 段错误核心转储。

谁能准确指出我在这里做错了什么?

我检查了 emp 变量是否已初始化,但主要问题在我调用 calc_Bonus(..) 函数时的第二次迭代开始。 emp[1].basicsalary 的值给出了该错误,但我不知道为什么。

编辑: 与输出结果相比,我所做的和得到的结果。

Enter total records
2
Enter the employee id
428
Enter the basic salary
5500
Enter the PF amount
550
Enter the mediclaim amount
1203
Enter the sales percentage
8.5
Enter the employee id
430
Enter the basic salary
12000
Enter the PF amount
350
Enter the mediclaim amount
650
Enter the sales percentage
10.5
/home/p10301/.vpl_launcher.sh: line 12: 11946 Segmentation fault        (core dumped) ./vpl_execution

预期的输出应该是什么:

Net salary for the ID 428 is Rs.5247.00
Net salary for the ID 430 is Rs.15000.00

最佳答案

给定 empmain() 中声明如下:

struct Employee *emp = malloc(n*sizeof(*emp));

, emp 是一个指针(与指针数组相反),指向足够大的空间以容纳多个 struct Employee 对象;从语义上讲,它专门指向这些对象中的第一个。

在那种情况下,这个调用...

calc_Bonus(&emp,i)

...以及对 calc_NetSalary(&emp,i) 的类似调用与这些函数的原型(prototype)一致,但与它们的实现及其参数列表的 union 含义(如它们所暗示的)不一致实现)当 i 为非零时。具体来说,考虑来自 calc_Bonus() 的这个表达式:

emp[i]->basicsalary

因为 emp 在那里声明为 struct Employee **,让我们重写它以用等效指针替换 [] 操作 -基于算术的表达式:

(*(emp + i))->basicsalary

现在问题应该更清楚了,但是你要注意区分calc_Bonus()empemp main(),它们在类型和值上都不同。 calc_Bonus() 中的 emp 指向一个标量(main(的emp )),所以如果你向它添加一个非零整数并尝试取消引用结果,那么你会得到未定义的行为。

鉴于当前的函数签名,该表达式和所有类似的表达式需要以这种形式重写:

(*emp)[i].basicsalary

...或者这个...

(*emp + i)->basicsalary

但我认为更好的解决方案是通过重写函数来减少间接级别:

int calc_Bonus(struct Employee *emp, int i) {
    if (emp[i].basicsalary <= 7000 && emp[i].salespercentage <= 10)
        return 1500;
    // ...
}

然后像这样从 main() 调用它:

calc_Bonus(emp,i);

还有其他几个有效的替代方案也比原始代码更好。

关于c - 为什么这个结构数组只访问第一个元素并显示其余元素的段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43968493/

相关文章:

c++ - 打印一组 STL 列表

go - 使用来自不同包 golang 的结构

c - 如何通过指针访问全局定义的 typedef 结构?

c - GTK+ 使用前景色绘制位图作为 mask

c - 来自多个线程的 pthread_cond_signal

Java整体数组限制?

c++ - 如何在 C++ 中使用来自 dll 的结构?

c - 方程返回 1.#QO

c - 面向2D的Open Dynamics Engine

arrays - bash 在循环中分配给数组索引时遇到问题