我花了三个小时试图弄清楚为什么我在这种特殊情况下会出现分段错误&我在这个主题上经历了很多问题,但我仍然无法将其与我的案例联系起来。
现在我似乎知道问题是什么,但我不知道为什么。
我的结构数组似乎没有正确初始化。
我从用户输入的所有值都在主函数中正确显示但是当我进入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;
}
现在我已经尝试通过打印奖金和奖励的值来调试它。不同迭代的netsalary&amp;它仅适用于i = 0 &安培;给出12个分段故障核心转储。
有人能指出我在这里做错了什么吗?
当我调用calc_Bonus(..)函数时,我检查了emp变量是否已初始化,尽管主要问题在第二次迭代时开始。 emp [1] .basicsalary的值给出了这个错误,但我不知道为什么。
编辑: 我做了什么&amp;得到的输出相比应该是输出。
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
答案 0 :(得分:2)
在emp
中声明main()
,如此:
struct Employee *emp = malloc(n*sizeof(*emp));
,emp
是一个单指针(与指针数组相对),空间足够大,可用于多个struct Employee
个对象;从语义上讲,它特指第一个对象。
在这种情况下,这个电话......
calc_Bonus(&emp,i)
...对calc_NetSalary(&emp,i)
的类似调用与这些功能一致&#39;原型,但是当i
非零时,与它们的实现和它们的参数列表的联合含义(如它们的实现所暗示的)的联合含义不一致。具体来说,请考虑calc_Bonus()
:
emp[i]->basicsalary
由于emp
被声明为struct Employee **
,所以让我们重写一下,用等效的基于指针算术的表达式替换[]
操作:
(*(emp + i))->basicsalary
现在问题应该更清楚了,但是你必须要小心区分emp
calc_Bonus()
和emp
main()
,emp
两种类型都不同和价值。被调用的calc_Bonus()
中的emp
指向标量(main()
的{{1}}),因此如果向其添加非零整数并试图取消引用结果然后你得到未定义的行为。
鉴于当前的函数签名,该表达式和所有类似的表达式需要以这种形式重写:
(*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);
还有其他一些有效的替代方案也会比原始代码更好。
答案 1 :(得分:0)
您正在分配一系列struct Employee
个对象(即malloc(n * sizeof(struct Employee))
,但在函数calc_bonus
中,您将它们视为指向此类struct Employee
个对象的指针数组(和您一样)将指针传递给这样的指针序列,即struct Employee**
)。
因此,在函数calc_bonus
中,当您编写emp[i]
时,您将返回i
中的emp
指针。但是emp
不包含指针,它包含雇员对象。所以emp[i]
将返回一个被视为指针的值,但指针值将指向任意的东西,这很可能是struct Employee
- 对象。并取消引用这样一个&#34;无效&#34;指针会产生未定义的行为,这可能会成为分段错误。
要解决此问题,请按以下方式定义和使用calc_Bonus
:
int calc_Bonus(struct Employee[],int);
int calc_Bonus(struct Employee emp[],int i)
{
if(emp[i].basicsalary<=7000 && emp[i].salespercentage<=10) {
...
}
int main () {
...
emp[i].bonus=calc_Bonus(emp,i);
}
答案 2 :(得分:0)
您的calc_Bonus()方法不应将数组和索引号作为参数。 它应该只有一个参数 - 指向Employee实例的指针。 并且它不需要返回任何内容,因为您只是填写该员工的一个领域:
void calc_Bonus( Employee *e ) {
if(e->basicsalary<=7000 && e->salespercentage<=10) {
e->bonus = xxx;
} else if ( ... ) {
...
}
}
然后使用
调用它 calc_Bonus( &emp[i] );