C:尝试初始化结构中的char数组时出现赋值错误时的不兼容类型
我正在尝试为有关结构的赋值创建程序。这个想法是创建一个包含姓名,电话号码和电子邮件地址变量的结构。我认为我的大部分代码都可以 - 与C的现代编码标准相比,可能是最基本的代码,但这是我在课堂上的地方。C:尝试初始化结构中的char数组时出现赋值错误时的不兼容类型
无论如何,我试图初始化电子邮件地址字段中的5行上出现编译错误,说明赋值中的不兼容类型。但是,我不会在首字母或姓氏字段中看到这些错误,但我不明白为什么。
任何想法,为什么发生这种情况,或与程序其余部分的错误,非常感激!我不能真正调试它的其余部分,直到我解决了这个编译错误,所以我不确定还有什么问题。
#include <stdio.h>
#include <string.h>
/*****************************************
Structure declaration, creating type cont
*****************************************/
typedef struct contact {
char fname[20];
char lname[20];
int number[10];
char email[30];
} cont;
/*****************************************
Start of main function
*****************************************/
int main() {
int iMenu; //variable required for the menu
int iStorage; //variable used to store array entry chosen by the user
int iEntry1, iEntry2, iEntry3, iEntry4, iEntry5 = 0; //variables used for flagging assigned entries
/*******************************************
because of the typedef declaration, the struct command
isn't necessary in creating an instance of the structure.
*******************************************/
cont myContact[4];
/*******************************************
we initialize the arrays contained within the structures
*******************************************/
strcpy(myContact[0].fname, "\0");
strcpy(myContact[0].lname, "\0");
myContact[0].number = 0;
strcpy(myContact[0].email, "\0");
strcpy(myContact[1].fname, "\0");
strcpy(myContact[1].lname, "\0");
myContact[1].number = 0;
strcpy(myContact[1].email, "\0");
strcpy(myContact[2].fname, "\0");
strcpy(myContact[2].lname, "\0");
myContact[2].number = 0;
strcpy(myContact[2].email, "\0");
strcpy(myContact[3].fname, "\0");
strcpy(myContact[3].lname, "\0");
myContact[3].number = 0;
strcpy(myContact[3].email, "\0");
strcpy(myContact[4].fname, "\0");
strcpy(myContact[4].lname, "\0");
myContact[4].number = 0;
strcpy(myContact[4].email, "\0");
/*****************************************
Creation of the menu to allow the users
to add entries or view them
*****************************************/
while (iMenu != 3) {
printf("Please select one of the following menu options: \n");
printf("\n1. Input new entries into the phonebook");
printf("\n2. View entries stored in the phonebook");
printf("\n3. Exit the Program\n");
scanf("%d", &iMenu);
/*******************************************
First menu option allows the selection of which
entry, and the storage of phonebook data
********************************************/
if (iMenu == 1) {
printf("Please input the entry in the phonebook you wish to change (0-4): \n");
scanf("%d", iStorage);
printf("Please input the first name of your new contact: \n");
scanf("%s", myContact[iStorage].fname);
printf("Please input the last name of your new contact: \n");
scanf("%s", myContact[iStorage].lname);
printf("Please input the phone number of your new contact: \n");
scanf("%d", myContact[iStorage].number);
printf("Please input the e-mail address of your new contact: \n");
scanf("%s", myContact[iStorage].email);
/**************************************
Nested if statement sets the variable to
flag if an entry has been made
**************************************/
if (iStorage == 0)
iEntry1 = 1;
else if (iStorage == 1)
iEntry2 = 1;
else if (iStorage == 2)
iEntry3 = 1;
else if (iStorage == 3)
iEntry4 = 1;
else if (iStorage == 4)
iEntry5 = 1;
}
/***************************************
Menu option 2 allows the user to display
stored phonebook entries, using the iEntry
variables as flags to determine which ones
to display
***************************************/
else if (iMenu == 2) {
if (iEntry1 == 1)
printf("%s %s phone number: %d e-mail address: %s", myContact[0].fname, myContact[0].lname, myContact[0].number, myContact[0].email);
if (iEntry2 == 1)
printf("%s %s phone number: %d e-mail address: %s", myContact[1].fname, myContact[1].lname, myContact[1].number, myContact[1].email);
if (iEntry3 == 1)
printf("%s %s phone number: %d e-mail address: %s", myContact[2].fname, myContact[2].lname, myContact[2].number, myContact[2].email);
if (iEntry4 == 1)
printf("%s %s phone number: %d e-mail address: %s", myContact[3].fname, myContact[3].lname, myContact[3].number, myContact[3].email);
if (iEntry5 == 1)
printf("%s %s phone number: %d e-mail address: %s", myContact[4].fname, myContact[4].lname, myContact[4].number, myContact[4].email);
}
else if (iMenu > 3) {
printf("Invalid Entry.");
}
}
return 0;
}
你的编译器几乎可以肯定在抱怨这些线路:
myContact[0].number = 0;
myContact[1].number = 0;
...
不这些:
strcpy(myContact[0].email, "\0");
strcpy(myContact[1].email, "\0");
...
struct contact
宣布其number
字段的类型为int[10]
,但您正在尝试为其分配单个int
。
其他不请自来的建议:
你可以为更简单的初始化myContact
阵列:
cont myContact[4] = { { { 0 } } };
当初始化一个聚合类型的一部分(例如数组,struct
),编译器会自动初始化其余所有成员。例如,如果你有:
char s[100] = "hello";
接着的s
前5个字节将是'h'
,'e'
,'l'
,'l'
,'o'
,并且每个余下的95个字节的将具有值0。
int iEntry1, iEntry2, iEntry3, iEntry4, iEntry5 = 0;
这只初始化iEntry5 = 0
。 iEntry1
.. iEntry4
未被初始化,这可能不是你想要的。
打印提示输入时,you should call fflush(stdout)
afterward。
另外,请勿使用scanf
。 It is error-prone and is hard to use correctly.您特别需要关注缓冲区溢出问题。
“编译器将零初始化未明确初始化的所有成员。”我的教科书告诉我们,始终初始化变量很重要,因为在c中,那些变量将包含变量分配给内存中的任何数据。因此,一旦编译,未初始化的变量不是问题吗?自己初始化它们仍然是最佳实践吗? – CDAGeek 2013-03-16 06:02:21
@CDAGeek:我特别说过,编译器会将未初始化的* members *初始化为零。这指的是一个* aggregate *类型的成员(例如一个数组,一个'struct')。初始化聚合的一部分时,您将自动初始化其余部分。对于个体变量这不是真的,所以是的,你应该初始化这些变量。 (并且请注意,您仍然需要初始化部分聚合。)我将编辑我的答案以使其更清晰。 – jamesdlin 2013-03-16 06:04:37
非常感谢您的帮助,在您指出的众多小修复之后,我能够获得工作。此外,非常感谢scanf和fflush(stdout)的提示,我将更深入地研究这些代码,以便我的代码符合标准。 – CDAGeek 2013-03-16 06:34:01
每个联系人都有十个数字(int number[10]
,从0至9),并且您分配,如果它是一个简单的int number
:
myContact[0].number = 0;
而且,不这样做: strcpy(myContact[0].fname, "\0");
您可能想要“”,而不是“\ 0”,因为在字符串末尾总是有一个隐含的\ 0。
(我希望FNAME和LNAME在那里只是作为一个练习,许多人在世界上有不适合的名字。“第一个名字 - 姓氏”范式)
@jamesdlin我在这些行中固定空字符“”,以及int数组只是整数。我正在摸索着通过这件事的方式。我从这里明白不使用scanf,什么是好的选择? Scanf是我们的文本用于接收输入的唯一功能。此外,是的,这只是一个练习,而不是一个真实世界的应用程序。修复这些错误修复了编译错误,但是当我尝试使用菜单选项1实际上放置信息时,我现在正在出现分段错误。任何其他帮助表示赞赏。 – CDAGeek 2013-03-16 05:41:18
不要忘记您希望scanf分配给的变量(字符串除外)之前的&。您可以使用fgets读取所有输入,并使用sscanf解析它(sscanf与scanf的不同之处在于sscanf从内存字符串中读取数据,从而更容易检查调试器中的程序状态并从读取错误中恢复) 。打开你的编译器的警告,它会告诉你很多有趣的事情:-) – marcus 2013-03-16 05:53:22
@CDAGeek:你回答了错误的问题。至于用什么来代替'scanf',请阅读我在答案中包含的链接。 – jamesdlin 2013-03-16 05:58:01
cont myContact [4];给你4个内存插槽你如何访问5个插槽(0到4)和数组是如何分配一个整数到整数阵列 – Civa 2013-03-16 05:24:46