我的程序需要接受人们的输入并计算工资并扣留并打印出所有内容。我有打印输出,但我在将其存储在阵列中时遇到了麻烦。
#include <stdio.h>
#include <stdlib.h>
typedef char *string;
#define MaxEmployees 100
typedef struct {
string name;
string title;
string ssnum;
double salary;
int withholding;
} employeeRecordT;
typedef struct {
string name;
string title;
string ssnum;
double salary;
int withholding;
} *employeeT;
payrollT
此类型代表整个员工集合。类型定义使用employeeT
值的动态数组,以确保该类型不存在最大限制。这种设计的代价是程序员必须使用NewArray
明确地为数组分配存储空间。
typedef struct {
int nEmployees;
employeeT *employees;
} *payrollT;
staff -- Array of employees nEmployees -- Number of employees manager -- Used to produce a figure for the code
static employeeT staff[MaxEmployees];
static int nEmployees;
static employeeRecordT manager = {
"Ebenezer Scrooge", "Partner", "271-82-8183", 250.00, 1
};
私人功能声明:
static void InitEmployeeTable(void);
static payrollT CreatePayroll(employeeT staff[], int nEmployees);
static void ListEmployees(payrollT payroll);
static double AverageSalary(payrollT payroll);
static void WeeklyPayroll(payrollT payroll);
//static void GetPayroll(void);
static double ssnum(payrollT payroll);
主程序:
int main(void)
{
payrollT payroll;
//GetPayroll(payroll);
InitEmployeeTable();
payroll = CreatePayroll(staff, nEmployees);
ListEmployees(payroll);
WeeklyPayroll(payroll);
}
static void InitEmployeeTable(void)
{
employeeT empRec;
int condition = 1;
int emp_id = 2;
empRec = (employeeT)malloc(sizeof (employeeT));
empRec->name = "Ebenezer Scrooge";
empRec->title = "Partner";
empRec->ssnum = "271-82-8183";
empRec->salary = 250.00;
empRec->withholding = 1;
staff[0] = empRec;
empRec->name = "Bob Cratchit";
empRec->title = "Clerk";
empRec->ssnum = "314-15-9265";
empRec->salary = 15.00;
empRec->withholding = 7;
staff[1] = empRec;
nEmployees = 2;
do {
//malloc(sizeof ());
char name;
char title;
char ssnum;
float salary;
double withholding;
printf("enter name or input stop to quit!\n");
printf("enter first and last name\n");
scanf("%s", empRec->name);
//empRec->name = name;
printf("\nenter title\n");
scanf("%s", empRec->title);
//empRec->title = title;
printf("\nenter social xxx-xx-xxxx\n");
scanf("%s", empRec->ssnum);
//empRec->ssnum = ssnum;
printf("\nenter salary xx.xx\n");
scanf("%lf", &empRec->salary);
//empRec->salary = salary;
printf("\nenter withhodling x\n");
scanf("%d", &empRec->withholding);
//empRec.withholding = withholding;
printf("printed %d", emp_id++);
staff[emp_id] = empRec;
emp_id++;
if (strcmp(empRec->name,"stop") == 1) {
condition = 0;
break;
}
//staff[emp_id]=empRec;
//emp_id++;
} while (condition = 1);
return 0;
}
答案 0 :(得分:2)
您没有为任何字符串分配存储空间(name
,title
,ssnum
[在您的记录中,现在我看起来也在你的do-while循环中 - 你不能使用char name;
,你需要例如char name[100];
或指针malloc
])。使用typedef
string
隐藏了这一事实。您可以分配给字符串变量并为您分配的分配的唯一时间是在声明时,因为大小在编译时已知,例如:
char *str = "Hello";
char *str2 = { 'w', 'o', 'r', 'l', 'd', '\0' };
在您的情况下,manager
的字符串分配很好,因为它们位于初始值设定项中,但您仍需要为employeeRecordT
中的字符数组提供明确的大小。
您需要做的是为这些字符数组提供明确的大小,或者为它们显式分配存储空间(malloc
等);而不是分配,您必须使用strcpy()
(<string.h>
)(或strncpy()
,以防出现溢出)。
你可以为你的title
变量做一些事情来保存空间是为了声明一个静态分配的字符串列表,然后让title
成为指向列表中相应元素的指针,例如(const
是可选的,但只是确保这个数组不会以任何方式搞乱):
const char const *titles[] = { "Partner", "Clerk", "etc." };
typedef struct {
const char *title;
// ...
} *employeeT;
// ...
empRec->title = titles[0]; // Points title to "Partner"
您甚至可以使用enum
来帮助索引(所有其余代码都是相同的):
enum { PARTNER, CLERK, ETC };
// ...
empRec->title = titles[CLERK]; // Points title to "Clerk"
您的代码的另一个问题是您只为单个employeeT
记录分配存储空间;如果不再次调用empRec
,则无法重复使用malloc()
。将要发生的事情是,每次更改empRec
时,它都会更改所有以前的staff
元素,因为它们都指向同一位置(即staff[0]
将包含确切的内容你将staff[1]
设置为)。
另一个问题是你正在使用sizeof (employeeT)
,但这是错误的,因为这只是给你结构的指针的大小。这是typedef
s使事情更加混乱的一个原因。您应该创建您的结构(并且如果需要,也可以键入def),但是当您需要指向它时,您应该诚实地在代码中使用'*'(可选地创建 second typedef
,即typedef struct { // ... } node; typedef node *node_ptr;
或甚至同时:typedef struct { // ... } node, *node_ptr;
)。您有两个选项,在开始为其成员分配第二(及后续)时间之前,您可以再次为malloc()
调用empRec
,或者您可以简单地丢弃empRec
变量并使用{直接{1}},例如:
staff
以后staff[0] = malloc(sizeof *staff[0]);
// Note I couldn't use employeeT above since you need struct size, not ptr.
// (`sizeof (employeeRecordT)` could have been used though)
strcpy(staff[0]->name, "Ebenezer Scrooge");
// ...
staff[0]->salary = 250.00;
// ...
<{1}}
此外,我不明白为什么你有这个free()
类型,它本质上是你的staff[]
数组的副本?如果你想要payrollT
,你可以只有一个指向员工记录的指针(顺便提一下,你可能不想要staff
,你可能想要payrollT
(因为它已经是指针类型)或employeeT *employees;
)。我认为这是我在程序片段中看到的另一个错误。
如果你愿意,你可以摆脱你的employeeT employees;
变量,而不是使用do-while循环,只需在你的{{employeeRecordT *employees
和condition
中使用while (1)
1}}会为你退出。这样您就可以确定它至少仍然被评估过一次。
顺便说一句,您不必转换break
的返回值。这是不必要的,因为void指针安全地自动升级到任何其他类型(反之亦然)。有关详细信息,请参阅here。另外,我看到你提到if
但从未在任何地方引用它。