2013-03-16 110 views
-1

我正在尝试为有关结构的赋值创建程序。这个想法是创建一个包含姓名,电话号码和电子邮件地址变量的结构。我认为我的大部分代码都可以 - 与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; 
} 
+1

cont myContact [4];给你4个内存插槽你如何访问5个插槽(0到4)和数组是如何分配一个整数到整数阵列 – Civa 2013-03-16 05:24:46

回答

3

你的编译器几乎可以肯定在抱怨这些线路:

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 = 0iEntry1 .. iEntry4未被初始化,这可能不是你想要的。

打印提示输入时,you should call fflush(stdout) afterward

另外,请勿使用scanfIt is error-prone and is hard to use correctly.您特别需要关注缓冲区溢出问题。

+0

“编译器将零初始化未明确初始化的所有成员。”我的教科书告诉我们,始终初始化变量很重要,因为在c中,那些变量将包含变量分配给内存中的任何数据。因此,一旦编译,未初始化的变量不是问题吗?自己初始化它们仍然是最佳实践吗? – CDAGeek 2013-03-16 06:02:21

+0

@CDAGeek:我特别说过,编译器会将未初始化的* members *初始化为零。这指的是一个* aggregate *类型的成员(例如一个数组,一个'struct')。初始化聚合的一部分时,您将自动初始化其余部分。对于个体变量这不是真的,所以是的,你应该初始化这些变量。 (并且请注意,您仍然需要初始化部分聚合。)我将编辑我的答案以使其更清晰。 – jamesdlin 2013-03-16 06:04:37

+0

非常感谢您的帮助,在您指出的众多小修复之后,我能够获得工作。此外,非常感谢scanf和fflush(stdout)的提示,我将更深入地研究这些代码,以便我的代码符合标准。 – CDAGeek 2013-03-16 06:34:01

2

每个联系人都有十个数字(int number[10],从0至9),并且您分配,如果它是一个简单的int number

myContact[0].number = 0;

而且,不这样做: strcpy(myContact[0].fname, "\0");

您可能想要“”,而不是“\ 0”,因为在字符串末尾总是有一个隐含的\ 0。

(我希望FNAME和LNAME在那里只是作为一个练习,许多人在世界上有不适合的名字。“第一个名字 - 姓氏”范式)

+0

@jamesdlin我在这些行中固定空字符“”,以及int数组只是整数。我正在摸索着通过这件事的方式。我从这里明白不使用scanf,什么是好的选择? Scanf是我们的文本用于接收输入的唯一功能。此外,是的,这只是一个练习,而不是一个真实世界的应用程序。修复这些错误修复了编译错误,但是当我尝试使用菜单选项1实际上放置信息时,我现在正在出现分段错误。任何其他帮助表示赞赏。 – CDAGeek 2013-03-16 05:41:18

+0

不要忘记您希望scanf分配给的变量(字符串除外)之前的&。您可以使用fgets读取所有输入,并使用sscanf解析它(sscanf与scanf的不同之处在于sscanf从内存字符串中读取数据,从而更容易检查调试器中的程序状态并从读取错误中恢复) 。打开你的编译器的警告,它会告诉你很多有趣的事情:-) – marcus 2013-03-16 05:53:22

+0

@CDAGeek:你回答了错误的问题。至于用什么来代替'scanf',请阅读我在答案中包含的链接。 – jamesdlin 2013-03-16 05:58:01

相关问题