【发布时间】:2018-10-18 20:51:52
【问题描述】:
所以正如问题所说,每次我尝试为客户输入名称时都会遇到分段错误。该程序确实会编译并运行,直到它到达客户名称部分。我不确定问题是否与malloc有关。谁能告诉我我做错了什么?我一直试图弄清楚这一点,但没有运气。谢谢
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define END_OF_STRINGS '\0'
#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("\n\nThis 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("\n\nGet 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("\n\n******* End Of Customer Database Processing *******");
return;
}
【问题讨论】:
-
通过 valgrind 运行您的代码。如果你对内存管理不善,它会告诉你在哪里。确保使用调试符号进行编译(gcc:
-g选项)。 -
Remove * from
char *p_last_name[MAX_NAME_LENGTH + 1];你声明的指针数组。 -
谁能告诉我我做错了什么?您没有使用调试器来缩小问题范围,以便您可以提出我们可以回答的问题。跨度>
-
@PaulDann,名字的主要问题是
char *p_last_name[MAX_NAME_LENGTH + 1];。这将p_last_name声明为 指针数组(带有 21 个指针)而不是 字符数组(带有21 个字符)。正确使用malloc并没有什么魔力。它分配一块大小为您所用的内存块。 您必须将该块的起始地址分配给您将用于访问内存的指针。然后,您必须将您希望存储在那里的任何信息复制到起始地址。p_customer分配给20客户。从那里去。 -
我这样说并不是不屑一顾。为了在您的程序上下文中“向您展示如何使
malloc工作”,我基本上最终会重新编写您的程序。从教育的角度来看,这对您几乎没有帮助。更好地学习How to debug small programs 并与鸭子交谈...真的,它有帮助:)在此期间,请访问Do I cast the result of malloc?。隔离malloc有问题的地方(在代码中添加printf ("in function() at line x\n");)
标签: c segmentation-fault malloc