我目前在课堂上的项目是制作一个程序,作为使用结构的电话簿。我已经编写了“添加联系人”功能和“显示联系人”功能,但是当我有多个联系人时,“显示联系人”功能会显示最近一次联系人所期望的所有联系人的乱码。任何人都可以帮我找到问题吗?
这是我目前的代码。如果有什么问题让我知道,我会尽快回复。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct contact { // Data structure that holds contact information
char FirstName[10]; // Array for first name
char LastName[10]; // Array for last name
int PhoneNum; // Phone number
};
int main (){
// Setting up variables
int Function = 0;
int Choice = 0;
char FName[200][10];
char LName[200][10];
int PNum = 0;
int n = 1;
struct contact *con[200];
int b = 0;
do{ // Will loop through the main function until the user decides to exit the program
// Prints out the main menu of the phone book
printf("\nPhone Book");
printf("\n[1] Add a contact");
printf("\n[2] Delete a contact");
printf("\n[3] Show contacts");
printf("\n[4] Exit program");
printf("\n\nWhat function would you like to use?\n"); // Asks for user input
scanf("%d", &Choice);
switch(Choice){
case 1: // Case to add a contact into the phone book
printf("\nYou chose to add a contact.");
printf("\nFirst name: ");
scanf("%s", &FName[b]);
printf("\nLast name: ");
scanf("%s", &LName[b]);
printf("\nPhone number (Numbers only): ");
scanf("%d", &PNum);
printf("\nRecord added to the phone book");
// Records the information given into the structure
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));
int a = (n - 1);
printf("\na is %d", a);
strcpy(con[a].FirstName, FName[b]);
strcpy(con[a].LastName, LName[b]);
con[a].PhoneNum = PNum;
int b = (b+1);
n++;
printf("\nn is %d", n);
// Prints out the given information
printf("\nNew contact:");
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
break;
case 2: // Case to delete a contact from the phone book
printf("\nYou chose to delete a contact.");
break;
case 3: // Case to see all of the entered contacts
printf("\nYou chose to show the contacts.");
for(a = 0; a < (n - 1); a++){
printf("\nContact #%d", a);
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
}
break;
case 4:
printf("Goodbye!");
break;
}
}while (Choice != 4);
return 0;
}
这是我运行代码时得到的输出。
Phone Book
[1] Add a contact
[2] Delete a contact
[3] Show contacts
[4] Exit program
What function would you like to use?
1
You chose to add a contact.
First name: Test
Last name: 1
Phone number (Numbers only): 1234567
Record added to the phone book
a is 0
n is 2
New contact:
First name: Test
Last name: 1
Phone number: 1234567
Phone Book
[1] Add a contact
[2] Delete a contact
[3] Show contacts
[4] Exit program
What function would you like to use?
1
You chose to add a contact.
First name: test
Last name: 2
Phone number (Numbers only): 8901234
Record added to the phone book
a is 1
n is 3
New contact:
First name: test
Last name: 2
Phone number: 8901234
Phone Book
[1] Add a contact
[2] Delete a contact
[3] Show contacts
[4] Exit program
What function would you like to use?
3
You chose to show the contacts.
Contact #0
First name: Pq
Last name: q
Phone number: 1095516483
Contact #1
First name: test
Last name: 2
Phone number: 8901234
您的代码存在一些问题:
1>变量a,b,con的范围应该在main函数中,通过在case块代码中重新声明它们,从主函数范围到in-case范围覆盖变量a,b的范围。
int b = b+1;
int a = (n-1);
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));
如果是块代码,请为它们分配新值:
b = b+1;
a = (n-1);
con = (struct contact*)malloc(n*sizeof(struct contact));
2>应该改变con指针
struct contact *con[200];
通过为它定义初始化大小。如果大小超出范围,我们需要在添加新项目时重新分配con:
int size = 200;
struct contact *con = (struct contact *)malloc(size * sizeof(struct contact));
// in case of the size of out of range
if (n >= size)
{
size = size * 2;
con = (struct contact*)realloc(con, size * sizeof(struct contact));
}
这是我的解决方案:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct contact { // Data structure that holds contact information
char FirstName[10]; // Array for first name
char LastName[10]; // Array for last name
int PhoneNum; // Phone number
};
int main() {
// Setting up variables
int Function = 0;
int Choice = 0;
char FName[200][10];
char LName[200][10];
int PNum = 0;
int n = 1;
int size = 200;
struct contact *con = (struct contact *)malloc(size * sizeof(struct contact));
int b = 0, a = 0;
do { // Will loop through the main function until the user decides to exit the program
// Prints out the main menu of the phone book
printf("\nPhone Book");
printf("\n[1] Add a contact");
printf("\n[2] Delete a contact");
printf("\n[3] Show contacts");
printf("\n[4] Exit program");
printf("\n\nWhat function would you like to use?\n"); // Asks for user input
scanf("%d", &Choice);
switch (Choice) {
case 1: // Case to add a contact into the phone book
printf("\nYou chose to add a contact.");
printf("\nFirst name: ");
scanf("%s", &FName[b]);
printf("\nLast name: ");
scanf("%s", &LName[b]);
printf("\nPhone number (Numbers only): ");
scanf("%d", &PNum);
printf("\nRecord added to the phone book");
// Records the information given into the structure
if (n >= size)
{
size = size * 2;
con = (struct contact*)realloc(con, size * sizeof(struct contact));
}
a = (n - 1);
printf("\na is %d", a);
strcpy(con[a].FirstName, FName[b]);
strcpy(con[a].LastName, LName[b]);
con[a].PhoneNum = PNum;
b = (b + 1);
n++;
printf("\nn is %d", n);
// Prints out the given information
printf("\nNew contact:");
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
break;
case 2: // Case to delete a contact from the phone book
printf("\nYou chose to delete a contact.");
break;
case 3: // Case to see all of the entered contacts
printf("\nYou chose to show the contacts.");
for (a = 0; a < (n - 1); a++) {
printf("\nContact #%d", a);
printf("\nFirst name: %s", con[a].FirstName);
printf("\nLast name: %s", con[a].LastName);
printf("\nPhone number: %d", con[a].PhoneNum);
printf("\n");
}
break;
case 4:
printf("Goodbye!");
break;
}
} while (Choice != 4);
return 0;
}
你在con
语句中定义了一个名为switch
的新变量。此变量将屏蔽在函数顶部定义的同名变量。这是你要添加记录的那个。
当你以后去打印列表时,它实际上是从这个内部con
读取。但是,由于您正在重新输入switch
语句,因此变量的内容未初始化,因为您因为切换而跳过初始化程序并调用undefined behavior。你很幸运能够打印读入的最后一个实例,可能是因为变量仍然包含上一次迭代的旧值。
此外,con
的外部版本被声明为指针数组。您可能只需要一个指针,这样它就可以指向一个动态分配的数组。
所以定义con
像这样:
struct contact *con = NULL;
并更改“添加”案例以不定义变量。此外,您不需要单独的变量来读取值。您可以直接将它们读入结构的实例:
n++;
con = realloc(n*sizeof(struct contact));
printf("\nYou chose to add a contact.");
printf("\nFirst name: ");
scanf("%s", con[n-1].FirstName);
printf("\nLast name: ");
scanf("%s", con[n-1].LastName);
printf("\nPhone number (Numbers only): ");
scanf("%d", &con[n-1].PhoneNum );
printf("\nRecord added to the phone book");
printf("\nn is %d", n);
printf("\nNew contact:");
printf("\nFirst name: %s", con[n-1].FirstName);
printf("\nLast name: %s", con[n-1].LastName);
printf("\nPhone number: %d", con[n-1].PhoneNum);
printf("\n");
然后你还需要将a
移动到“show”部分:
for( int a = 0; a < (n - 1); a++){
正如@Some程序员老兄建议你需要重新分配你的数组,如果你想让它更大并保持你的数据。
所以基本上是这样的
// Records the information given into the structure
struct contact *con = (struct contact*)malloc(n*sizeof(struct contact));
应该在你的main
函数的开头就像这样:
// dynamically allocate memory which can hold e.g. 1 struct
struct contact *con = malloc(sizeof(struct contact));
当你在堆上调整你的内存块大小时,这就是malloc为你做的,你应该调整大小或realloc
就像这样:
// grow array
con = realloc(con, n * sizeof(struct concat));
阅读手册页以获取更多信息:realloc man page,或在终端上输入man 3 realloc
或man realloc
。
编辑@dbush建议
您声明了2个名为con的变量。在开始struct contact *con[200];
和switch语句中,您分配内存并将其保存到struct concat *con
。
所以你仍然得到选项“3”(显示所有联系人)的未定义结果的原因是,你实际上是从数组struct contact *con[200];
读取联系人而不是从struct contact *con;
指向的内存中读取联系人
问候