我正在尝试制作一个 IT 票证系统,允许用户输入姓名、电子邮件、日期、问题的优先级和问题描述。然后,它允许用户添加另一张票证或按优先级顺序打印所有票证。目前,如果我输入一张票的信息,它就可以很好地打印。但是,如果我添加更多票证,它将用新票证的数据覆盖前一个票证中的所有数据,但优先级除外,优先级将保持不变并正确排序。
我已向我的教授展示了这段代码,我们用它进行了一些故障排除。我们认为问题出在函数 createTicket 中,尽管它也可能是 printList 的问题。我希望我的代码为每张票创建单独的数据并按正确的顺序打印它们
#include <stdio.h>
#include <stdlib.h>
typedef struct ticket {
char *name;
char *email;
char *date;
int priority;
char *issue_description;
int is_closed;
char *issue_solution;
struct ticket* next; //pointer to the next ticket
}Ticket;
Ticket* createTicket() {
Ticket* newTicket = (Ticket*)malloc(sizeof(Ticket)); // Allocate memory
if (newTicket == NULL) { // Check for memory allocation failure
printf("Memory allocation failed\n");
exit(1);
}
char email[120];
char name [120];
char date [480];
char issue [480];
int num = 0;
//name
printf("What's the name: ");
scanf("%s", &name);
newTicket->name = name;
//email
printf("What's the email: ");
scanf("%s", &email);
newTicket->email = email;
//date
printf("What's the date: ");
scanf("%s", &date);
newTicket->date = date;
//priority
while (num > 5 || num < 1){
printf("What's the priority of the issue (1-5): ");
scanf("%d", &num);
if(num > 5 || num < 1){
printf("Invalid input. Enter a number between 1 and 5\n");
} else {
newTicket->priority = num;
}
}
//issue description
printf("What's the issue? (maximum characters: 120): ");
scanf("%s", &issue);
newTicket->issue_description = issue;
newTicket->is_closed = 0;
newTicket->issue_solution = "None";
newTicket->next = NULL; // Initialize next pointer to NULL
return newTicket;
}
void addTicketAtEnd(Ticket** head, Ticket* newTicket) {
if (*head == NULL) {
*head = newTicket; // If list is empty, the new node becomes the head
return;
}
Ticket* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newTicket; // Link the last node to the new node
}
// Print the list
void printList(Ticket* head) {
if (head == NULL) {
printf("The list is empty.\n");
return;
}
printf("Ticket List:\n");
Ticket* temp = head;
while (temp != NULL) {
printf("Name: %s\n", temp->name);
printf("Email: %s\n", temp->email);
printf("Date: %s\n", temp->date);
printf("Priority: %d\n", temp->priority);
printf("Issue: %s\n", temp->issue_description);
printf("Solution: %s\n", temp->issue_solution);
temp = temp->next;
}
}
Ticket* insertTicket(Ticket* head) {
Ticket* newTicket = createTicket();
Ticket* temp = head;
//if newticket priority >= temp priority then set next and prev and change prev of next to current and change next of prev to current
if(head == NULL){ //if list is empty
return newTicket;
}
//if the priority of the head is less than the new ticket, set the newticket as the head
if (head->priority <= newTicket->priority){
newTicket->next = head; // Point the new ticket to the current head
return newTicket;
} else {
while(1){
if (temp->next == NULL){
addTicketAtEnd(&head, newTicket);
//temp->next == newTicket;
//printf("Null");
return head;
}else if(temp->next->priority <= newTicket->priority){ //if temp priority is less than new
//printf("2nd");
newTicket->next = temp->next;
temp->next = newTicket;
return head;
} else if (temp->priority > newTicket->priority){ //if temp priority is greater than new,
//printf("No result");
temp = temp->next; //get the next element
}
}
}
}
int main() {
Ticket ticket;
Ticket* head = NULL;
int option = 1; //1 to add a ticket, 2 to check off a ticket, 3 to print all tickets, 4 to exit
while (1){
if (option == 1){
head = insertTicket(head);
} else if (option == 2) {
//check off a ticket
} else if (option == 3){
printList(head);
} else if (option == 4){
break;
}
while (1){
printf("Enter a value between 1-4. 1. Add a ticket. 2. resolve a ticket. 3. print all tickets. 4. Exit: ");
scanf("%d", &option);
if(option > 4 || option < 1){
printf("Invalid input. Enter a number between 1 and 5\n");
} else {
break;
}
}
}
Ticket* temp;
while (head != NULL) {
temp = head;
head = head->next;
free(temp);
}
return 0;
}
通过添加一些“printf”语句来进行一些简单的调试来测试您的代码,发现主要问题是您的票证结构使用指向字符数组(字符串)的指针来代替定义特定大小的字符数组。 这样,输入的字符串信息的后续填充基本上在每个票证结构中提供了关于字符串引用的内存位置的未定义行为。 通常,在字符串条目的“scanf”语句中引用相同的内存位置,因此看起来多个票证具有与最后一个条目集相同的数据。
craig@Vera:~/C_Programs/Console/TicketList/bin/Release$ ./TicketList
What's the name: Craig
What's the email: [email protected]
What's the date: 11/25/24
What's the priority of the issue (1-5): 1
What's the issue? (maximum characters: 120): Dunno
Enter a value between 1-4. 1. Add a ticket. 2. resolve a ticket. 3. print all tickets. 4. Exit: 1
What's the name: Lily
What's the email: [email protected]
What's the date: 11/24/24
What's the priority of the issue (1-5): 1
What's the issue? (maximum characters: 120): Ditto
Enter a value between 1-4. 1. Add a ticket. 2. resolve a ticket. 3. print all tickets. 4. Exit: 3
Ticket List:
Name: Lily
Email: [email protected]
Date: 11/24/24
Priority: 1
Issue: Ditto
Solution: None
Name: Lily
Email: [email protected]
Date: 11/24/24
Priority: 1
Issue: Ditto
Solution: None
指针确实在结构定义中占有一席之地,但是根据您的程序尝试处理字符串信息的方式,在结构中定义字符数组并在代码中使用字符串函数要安全得多。
考虑到这一点,以下是程序的重构版本,其中包括票证结构中的“string.h”引用和字符数组定义。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct ticket
{
char name[120]; /* Assign a specific size to the various character arrays */
char email[120];
char date[480];
int priority;
char issue_description[480];
int is_closed;
char issue_solution[480];
struct ticket* next; //pointer to the next ticket
} Ticket;
Ticket* createTicket()
{
Ticket* newTicket = (Ticket*)malloc(sizeof(Ticket)); // Allocate memory
if (newTicket == NULL) // Check for memory allocation failure
{
printf("Memory allocation failed\n");
exit(1);
}
char email[120];
char name [120];
char date [480];
char issue [480];
int num = 0;
//name
printf("What's the name: ");
scanf("%s", name);
strcpy(newTicket->name, name);
//newTicket->name = name;
//email
printf("What's the email: ");
scanf("%s", email);
strcpy(newTicket->email, email);
//newTicket->email = email;
//date
printf("What's the date: ");
scanf("%s", date);
strcpy(newTicket->date, date);
//newTicket->date = date;
//priority
while (num > 5 || num < 1)
{
printf("What's the priority of the issue (1-5): ");
scanf("%d", &num);
if(num > 5 || num < 1)
{
printf("Invalid input. Enter a number between 1 and 5\n");
}
else
{
newTicket->priority = num;
}
}
//issue description
printf("What's the issue? (maximum characters: 120): ");
scanf("%s", issue);
strcpy(newTicket->issue_description, issue);
//newTicket->issue_description = issue;
newTicket->is_closed = 0;
strcpy(newTicket->issue_solution, "None");
//newTicket->issue_solution = "None";
newTicket->next = NULL; // Initialize next pointer to NULL
return newTicket;
}
void addTicketAtEnd(Ticket* head, Ticket* newTicket)
{
if (head == NULL)
{
head = newTicket; // If list is empty, the new node becomes the head
return;
}
Ticket* temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = newTicket; // Link the last node to the new node
}
// Print the list
void printList(Ticket* head)
{
if (head == NULL)
{
printf("The list is empty.\n");
return;
}
printf("Ticket List:\n");
Ticket* temp = head;
while (temp != NULL)
{
printf("Name: %s\n", temp->name);
printf("Email: %s\n", temp->email);
printf("Date: %s\n", temp->date);
printf("Priority: %d\n", temp->priority);
printf("Issue: %s\n", temp->issue_description);
printf("Solution: %s\n", temp->issue_solution);
printf("Next ticket address: %p\n", temp->next); /* Used as a simple debug output */
temp = temp->next;
}
}
Ticket* insertTicket(Ticket* head)
{
Ticket* newTicket = createTicket();
Ticket* temp = head;
//if newticket priority >= temp priority then set next and prev and change prev of next to current and change next of prev to current
if(head == NULL) //if list is empty
{
printf("First ticket %p\n", newTicket); /* Used as a simple debug output */
return newTicket;
}
//if the priority of the head is less than the new ticket, set the newticket as the head
if (head->priority <= newTicket->priority)
{
newTicket->next = head; // Point the new ticket to the current head
printf("Same priority %p and new ticket address is %p\n", head, newTicket); /* Used as a simple debug output */
return newTicket;
}
else
{
while(1)
{
if (temp->next == NULL)
{
addTicketAtEnd(head, newTicket);
//temp->next == newTicket;
//printf("Null");
return head;
}
else if(temp->next->priority <= newTicket->priority) //if temp priority is less than new
{
//printf("2nd");
newTicket->next = temp->next;
temp->next = newTicket;
return head;
}
else if (temp->priority > newTicket->priority) //if temp priority is greater than new,
{
//printf("No result");
temp = temp->next; //get the next element
}
}
}
}
int main()
{
//Ticket ticket;
Ticket* head = NULL;
int option = 1; //1 to add a ticket, 2 to check off a ticket, 3 to print all tickets, 4 to exit
while (1)
{
if (option == 1)
{
head = insertTicket(head);
}
else if (option == 2)
{
//check off a ticket
}
else if (option == 3)
{
printList(head);
}
else if (option == 4)
{
break;
}
while (1)
{
printf("Enter a value between 1-4. 1. Add a ticket. 2. resolve a ticket. 3. print all tickets. 4. Exit: ");
scanf("%d", &option);
if(option > 4 || option < 1)
{
printf("Invalid input. Enter a number between 1 and 5\n");
}
else
{
break;
}
}
}
Ticket* temp;
while (head != NULL)
{
temp = head;
head = head->next;
free(temp);
}
return 0;
}
使用“strcpy”等函数可确保不会发生不可预测的指针引用。 通过这些重构,以下是使用相同的两组票证信息的终端输出示例。
craig@Vera:~/C_Programs/Console/TicketList/bin/Release$ ./TicketList
What's the name: Craig
What's the email: [email protected]
What's the date: 11/26/24
What's the priority of the issue (1-5): 1
What's the issue? (maximum characters: 120): Dunno
First ticket 0x5652228f52a0
Enter a value between 1-4. 1. Add a ticket. 2. resolve a ticket. 3. print all tickets. 4. Exit: 1
What's the name: Lily
What's the email: [email protected]
What's the date: 11/25/24
What's the priority of the issue (1-5): 1
What's the issue? (maximum characters: 120): Ditto
Same priority 0x5652228f52a0 and new ticket address is 0x5652228f6170
Enter a value between 1-4. 1. Add a ticket. 2. resolve a ticket. 3. print all tickets. 4. Exit: 3
Ticket List:
Name: Lily
Email: [email protected]
Date: 11/25/24
Priority: 1
Issue: Ditto
Solution: None
Next ticket address: 0x5652228f52a0
Name: Craig
Email: [email protected]
Date: 11/26/24
Priority: 1
Issue: Dunno
Solution: None
Next ticket address: (nil)
Enter a value between 1-4. 1. Add a ticket. 2. resolve a ticket. 3. print all tickets. 4. Exit: 4
这次重构的收获可能是通过教程更多地深入研究结构中指针的使用以及标准“string.h”定义中标准字符串函数的使用。