-1

I'm attempting to create a program for an assignment concerning structures. The idea is to create a structure containing variables for first and last name, phone number, and email address. I think most of my code is okay - perhaps rudimentary compared to modern coding standards for C, but it's where I'm at in the class.

Anyhow, I get a compiled error on the 5 lines attempting to initialize the email address fields saying incompatible types in assignment. I don't get those errors on the first or last name fields however, and I don't get why.

Any thoughts on why this is happening, or errors with the rest of the program are greatly appreciated! I can't really debug the rest of it myself until I get this compile error fixed, so I'm not sure what else is wrong yet.

#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;
}
CDAGeek
  • 59
  • 2
  • 14
  • 1
    cont myContact[4]; gives you 4 memory slots how can you access 5 slots(0 to 4) and number is array how you assign a integer to integer array – Civa Mar 16 '13 at 05:24

2 Answers2

3

Your compiler almost certainly is complaining about these lines:

myContact[0].number = 0;
myContact[1].number = 0;
...

Not these:

strcpy(myContact[0].email, "\0");
strcpy(myContact[1].email, "\0");
...

struct contact declares its number field to be of type int[10], but you're trying to assign a single int to it.

Other unsolicited advice:

You could initialize your myContact array much more simply as:

cont myContact[4] = { { { 0 } } };

When you initialize part of an aggregate type (e.g. an array, a struct), the compiler will zero-initialize all of its remaining members automatically. For example, if you have:

char s[100] = "hello";

Then the first five bytes of s will be 'h', 'e', 'l', 'l', 'o', and each of the remaining 95 bytes will have the value 0.

int iEntry1, iEntry2, iEntry3, iEntry4, iEntry5 = 0;

This initializes only iEntry5 = 0. iEntry1 .. iEntry4 are left uninitialized, which probably is not what you intended.

When printing a prompt for input, you should call fflush(stdout) afterward.

Also, don't use scanf. It is error-prone and is hard to use correctly. You particularly need to be concerned with buffer overflows.

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
  • "The compiler will zero-initialize all members not explicitly initialized." My textbook tells us that it's important to always initialize variables because in c those variables will otherwise contain whatever data is left in the memory the variables are assigned to. So uninitialized variables aren't an issue once you compile? Is it still best practice to initialize them yourself? – CDAGeek Mar 16 '13 at 06:02
  • @CDAGeek: I specifically said that the compiler will zero-initialize the *members* not explicitly initialized. That refers to members of an *aggregate* type (e.g. an array, a `struct`). When you initialize part of an aggregate, you'll automatically zero-initialize the rest. This isn't true for individual variables, so yes, you should initialize those. (And note that you'll still need to initialize part of the aggregate.) I'll edit my answer to make this clearer. – jamesdlin Mar 16 '13 at 06:04
  • Thank you for all your help, I was able to get the thing working after the multitude of minor fixes that you pointed out. Also, thank you very much for the tip of scanf and fflush(stdout), I'm going to look into those more so my code is standards compliant. – CDAGeek Mar 16 '13 at 06:34
2

Each contact has ten numbers (int number[10], from 0 thru 9), and you are assigning as if it was a simple int number:

myContact[0].number = 0;

Also, don't do this: strcpy(myContact[0].fname, "\0");

You probably want "", not "\0", because there's always an implicit \0 at the end of a string.

(I hope fname and lname are there just as an exercise. Many people in the world have names that do not fit "first name - last name" paradigm)

marcus
  • 5,041
  • 3
  • 30
  • 36
  • @jamesdlin I fixed the null characters to just "" in those lines, as well as the int arrays into just ints. I'm fumbling my way through this thing. I understand from here not to use scanf, what is a good alternative? Scanf is the only function our text has covered for receiving input. Also, yes this is just for an exercise and not a real world application. Fixing those errors fixed the compile errors, but I'm now getting segmentation faults when I try to actually put information in using menu option 1. Any other help is appreciated. – CDAGeek Mar 16 '13 at 05:41
  • Don't forget the & before the variables that you want scanf to assign to (except for strings). You can read all of your input with fgets and parse it with sscanf (sscanf differs from scanf in that sscanf reads from an in-memory string, making it a little bit easier to inspect the program state in a debugger and recover from reading errors). Turn on your compiler's warnings and it will tell you many interesting things :-) – marcus Mar 16 '13 at 05:53
  • @CDAGeek: You replied to the wrong question. As for what to use instead of `scanf`, read the links I included in my answer. – jamesdlin Mar 16 '13 at 05:58