gpt4 book ai didi

c - 从结构体输入字符串后出现段错误

转载 作者:行者123 更新时间:2023-11-30 20:58:23 24 4
gpt4 key购买 nike

正如问题所说,每次我尝试输入客户姓名时都会出现段错误。该程序会编译并运行,直到到达客户名称部分。我不确定问题是否出在 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;
}

最佳答案

我相信你的问题的开始就在这里:

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在你的情况下。跳转的大小仅取决于定义数组时的数据类型。在你的情况下是 char这是 1 个字节,因此跳转为 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的变量,从技术上讲,它是一个指向连续内存块的字符指针,即MAX_NAME_LENGTH + 1 bytes 因为数据类型为 char,它是指向该内存块开头的指针。
  • *last_namelast_name[0] 相同其中引用字符指针last_name,以便返回内存的内容a
  • *(last_name+2)last_name[2] 相同这是 c

另外,在

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 )

你应该做的是(struct customer *) malloc( sizeof( struct customer ))除了正确定义名为 last_name 的 21 字节字符数组之外在struct customer .

它应该逻辑地用英语读出,通常是从右到左,如果没有则怀疑有问题。另外编译时学会使用-W它可以成为您的 friend 并提醒您此类问题。

您的原始代码可能没有为您输入的字符数分配或保留足够大的内存块以存储在 p_last_name 中。 .

关于c - 从结构体输入字符串后出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52882387/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com