所以问题说,每次我尝试为客户输入名称时,我都会遇到分段错误。该程序确实编译并工作,直到它到达客户名称部分。我不确定问题是否出在 malloc 上。谁能告诉我我做错了什么?我一直试图解决这个问题一段时间,但没有运气。谢谢
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define END_OF_STRINGS ' '
#define NEWLINE 'n'
#define MAX_CUSTOMERS 100
#define MIN_CUSTOMERS 2
#define MAX_NAME_LENGTH 20
#define DB_ALLOC_ERR 1
#define QUIT 0
struct customer
{
char *p_last_name[MAX_NAME_LENGTH + 1];
float amount_owed;
int priority;
};
void print_instructions();
int number_of_customers();
void get_accounts(struct customer *p_customer_start, int
customer_amount);
void clean_names(struct customer *p_customer_start, int
customer_amount);
void sort_names(struct customer *p_customer_start, int
customer_amount);
void print_results(struct customer *p_customer_start, int
customer_amount);
int main()
{
struct customer *p_customer;
int customer_amount;
while (print_instructions(), (customer_amount =
number_of_customers()) != QUIT)
{
if ((p_customer = (struct customer *)malloc(sizeof(*p_customer) *
MAX_NAME_LENGTH)) == NULL)
{
printf("nError #%d occurred in main()", DB_ALLOC_ERR);
printf("nCannot allocate memory for database of customer ");
printf("naccountable records");
printf("nThe program is aborting");
exit (DB_ALLOC_ERR);
}
get_accounts (p_customer, customer_amount);
clean_names (p_customer, customer_amount);
sort_names (p_customer, customer_amount);
print_results(p_customer, customer_amount);
printf("%c", NEWLINE);
free(p_customer);
}
return 0;
}
void print_instructions()
{
printf("nnThis program allows you to input customers which owe");
printf("nyou money (your accounts receivable), and manage these");
printf("naccounts in a database. You will enter the following:");
printf("n Customer last name (1-20 characters)");
printf("n Amount the customer owes (to the exact cent)");
printf("n Customer priority (1=VIP, 2=Important, 3=Regular)");
printf("nFrom 2 to 100 customers may be processed.");
return;
}
int number_of_customers()
{
int user_choice;
printf("nnGet the customers for the database");
printf("n--------------------------------------------------");
do
{
printf("nHow many customers do you have (%d to %d, %d=quit): ", MIN_CUSTOMERS, MAX_CUSTOMERS, QUIT);
scanf ("%d", &user_choice);
} while ((user_choice < MIN_CUSTOMERS ||
user_choice > MAX_CUSTOMERS) && user_choice != QUIT);
return user_choice;
}
void get_accounts(struct customer *p_customer_start, int
customer_amount)
{
struct customer *p_customer;
for (p_customer = p_customer_start; (p_customer - p_customer_start)
< customer_amount; p_customer++)
{
printf("nCustomer number %d", (int)(p_customer -
p_customer_start + 1));
printf("n Enter the customer's last name: ");
scanf ("%20s", p_customer->p_last_name[MAX_NAME_LENGTH + 1]);
getchar();
do
{
*p_customer->p_last_name[MAX_NAME_LENGTH] = getchar();
p_customer->p_last_name[MAX_NAME_LENGTH]++;
} while (!NEWLINE);
p_customer->p_last_name[MAX_NAME_LENGTH + 1] = END_OF_STRINGS;
printf("n Enter the amount owed: ");
scanf ("%f", &p_customer->amount_owed);
do
{
printf("n Enter the customer's priority (1-3): ");
scanf ("%d", &p_customer->priority);
} while (p_customer->priority < 1 || p_customer->priority > 3);
}
return;
}
void clean_names(struct customer *p_customer_start, int
customer_amount)
{
char *p_fast = p_customer_start->p_last_name[MAX_NAME_LENGTH],
*p_slow = p_customer_start->p_last_name[MAX_NAME_LENGTH];
if (tolower(*p_fast))
*p_slow++ = toupper(*p_fast);
while (*p_fast != END_OF_STRINGS)
{
if (!isspace(*p_fast) || isalpha(*p_fast))
*p_slow++ = tolower(*p_fast);
p_fast++;
}
*p_slow = END_OF_STRINGS;
return;
}
void sort_names(struct customer *p_customer_start, int
customer_amount)
{
char *p_inner[MAX_NAME_LENGTH],
*p_outer[MAX_NAME_LENGTH],
temp[MAX_NAME_LENGTH];
for (p_outer[MAX_NAME_LENGTH] = p_customer_start ->
p_last_name[MAX_NAME_LENGTH]; (p_outer - p_customer_start ->
p_last_name)
< customer_amount; p_outer[MAX_NAME_LENGTH]++)
{
for (p_inner[MAX_NAME_LENGTH] = p_outer[MAX_NAME_LENGTH + 1];
(p_inner - p_customer_start ->
p_last_name) < customer_amount; p_inner[MAX_NAME_LENGTH]++)
{
if (strcmp(p_outer[MAX_NAME_LENGTH],
p_inner[MAX_NAME_LENGTH]))
{
temp[MAX_NAME_LENGTH] = *p_outer[MAX_NAME_LENGTH];
*p_outer[MAX_NAME_LENGTH] = *p_inner[MAX_NAME_LENGTH];
*p_inner[MAX_NAME_LENGTH] = temp[MAX_NAME_LENGTH];
}
}
}
return;
}
void print_results(struct customer *p_customer_start, int
customer_amount)
{
char last_name[MAX_NAME_LENGTH];
float amount_owed = p_customer_start->amount_owed;
printf("n Here is the accounts receivable customer database");
printf("n=====================================================");
printf("n Customer Name Amount Priority");
printf("n-------------------- --------- -------------");
printf("n %s $ %.2f ", last_name,
amount_owed);
switch (p_customer_start->priority)
{
case 1:
printf("1 (VIP)");
break;
case 2:
printf("2 (Important)");
break;
case 3:
printf("3 (Regular)");
break;
}
printf("nn******* End Of Customer Database Processing *******");
return;
}
我相信你的问题的开始就在这里:
struct customer
{
char *p_last_name[MAX_NAME_LENGTH + 1];
float amount_owed;
int priority;
};
使用该代码,您可以创建 21 个指向 char的指针。
你想要的是指向空间的字符指针,该指针将容纳MAX_NAME_LENGTH + 1
个字符
因此,您需要一些简单的内容:
struct customer
{
char last_name[MAX_NAME_LENGTH + 1];
float amount_owed;
int priority;
};
我还p_last_name改为只是last_name,所以在眼睛看来,它读起来更合乎逻辑,但你可以随心所欲地称呼它,但说p_last_name是暗示它是一个不需要的指针,而且读起来很差
声明或定义变量时,从右到左阅读, 然后它将是一个数组,因为[]
它是 21 大,称为last name
它是char
数据类型的数组。
现在 C 的事情是数组和指针有一些共同点,或者经常会混淆......因为它们在技术上是一回事。 您定义的任何数组,反过来在内存中分配空间,只不过是指向数组开头的指针,就是这样!
当你做类似last_name[7]
的事情时,7
是从数组的开头跳跃多少次,这在你的例子中总是被称为last_name
。 跳转的大小完全取决于数组定义时的数据类型。 在您的情况下,它是 1 个字节的char
,因此last_name[7]
的跳跃距离last_name
指向的位置有 7 个字节。
For example if the contents in memory where `last_name` points to is abcdefghijklmnopqrst
- 然后
char last_name[MAX_NAME_LENGTH + 1];
定义一个名为 last_name 的变量,从技术上讲,它是指向连续内存块的字符指针,由于数据类型 char,该内存块为MAX_NAME_LENGTH + 1
字节,它是指向该内存块开头的指针。 *last_name
与last_name[0]
相同,后者last_name尊重字符指针,以便返回内存的内容
,该内存*(last_name+2)
与last_name[2]
相同,c
a
此外,在
int main()
{
struct customer *p_customer;
int customer_amount;
此语句struct customer *p_customer;
创建一个名为p_customer的指针,该指针将指向某个内存块(尚未发生(,该内存块的数据类型struct customer
上面定义。 好的。 然后在
if ((p_customer = (struct customer *)malloc(sizeof(*p_customer) *
MAX_NAME_LENGTH)) == NULL)
当你使用malloc
为你正在做的事情保留一些内存块时,你实际上是在做sizeof( a pointer )
除了正确定义一个 21 字节的字符数组,称为last_name
instruct customer
之外,您应该做的是(struct customer *) malloc( sizeof( struct customer ))
。
它应该用英语逻辑地读出来,通常是从右到左读,如果没有,那么就会怀疑有问题。 此外,在编译时学习使用-W
它可以成为您的朋友并提醒您注意此类问题。
您的原始代码可能没有为您键入的字符数分配或保留足够大的内存块以存储在p_last_name
中。