Nabil Aziz
Nabil Aziz

Reputation: 45

c programming structure error

I have a few issues with my syntax, it mainly says i have an errror before "struct" on the line "Struct CustomerInfo s; but i dont seem to find the problem.

My program is supposed to ask what the person would like to do first of all, they can store a record for the first option which is then stored in a structure which can be viewed by selecting the 2nd option of the menu, if they select the 3rd then they obviously quit the program.

any help would be appreciated thank you.

#include <stdio.h>

void menu();
int id,first,last;
struct CustomerInfo
{
char FirstName[15];        /* These are the varibles for the customer infomation */
char LastName[20];
int ID;
};

int main()
{                               /* program starts */

int selection = 0;

    void menu()
    {                    /* Menu loop              function */

        do
            {                                                                   /* menu start */
                printf("\n\n - What would you like to do?");
                printf("\n1  - Store a customer record");
                printf("\n2  - View customer Records");
                printf("\n3  - Quit program");
                scanf("%i", &selection);

            }   while (selection > 3);

                printf("You have entered an incorrect value");  /* If selection is greater than 3 then end program */
                return 0;
    }

   switch(selection)
   {
                                                                                /* switch statement starts */
        case 1:
            struct CustomerInfo s;
            printf("Please enter the customers details including First name, Lastname and ID.\n\n");
            printf("Enter First name: ");
            scanf("%s", s.FirstName);                                           /* Option 1: Asks to enter the customers details to store then loops back to program */
            printf("Enter Last name:  ");
            scanf("%s", s.LastName);
            printf("Enter Customer ID: ");
            scanf("%s", s.ID);
            void menu();
        break;

        case  2:

            printf("\nDisplaying Infomation\n");
            printf("First name: %s\n",s.Firstname);                             /* Option 2: Prints the customer details as listed in option 1 */
            printf("Last name: %s\n",s.Lastname);
            printf("Customer ID: %s\n",s.ID);
            void menu();
        break;

        case  3:                /* Option 3:     Program ends if option 3 is chosen. */
        break;
   }

return 0;

Upvotes: 1

Views: 3743

Answers (1)

Floris
Floris

Reputation: 46375

Let's start by looking at the structure you created; next we'll try to see if it can be fixed. I am leaving details out so we can see the big outline:

main {
  struct{}
  void menu(){
    do {
      stuff
    } while (selection > 3)
    printf("you have entered an incorrect value"); // if selection is > 3
   }
   switch(selection) {
    // do something if selection is 1 or 2, exit if 3
   }

There is no final closing brace in your code. I am assuming that's a copy-paste error, so I added it. Compiling with -Wall (to get warnings as well as errors reported), I get a number of errors:

sel.c:18: error: nested functions are disabled, use -fnested-functions to re-enable
sel.c: In function ‘menu’:
sel.c:31: warning: ‘return’ with a value, in function returning void
sel.c: In function ‘main’:
sel.c:38: error: expected expression before ‘struct’
sel.c:41: error: ‘s’ undeclared (first use in this function)
sel.c:41: error: (Each undeclared identifier is reported only once
sel.c:41: error: for each function it appears in.)
sel.c:61: warning: control reaches end of non-void function

Let's take those in turn:

sel.c:18: error: nested functions are disabled, use -fnested-functions to re-enable

Putting one function inside another is "nesting". It is rare that you would want to do that - it means that the function is only "visible" when you are inside the other function (a bit like local variables, but for functions). It is not standard C - it is an extension of gcc. It's almost always a bad idea to use non-standard (and thus non-portable) extensions. See http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html

sel.c: In function ‘menu’:
sel.c:31: warning: ‘return’ with a value, in function returning void

When we declare a function void, we say that it will not return a value. When you have a statement like return 0; you ARE returning a value. The compiler will ignore that - but it warns that you said one thing, and did another. Just use return; without a parameter, and the warning goes away.

sel.c:38: error: expected expression before ‘struct’
sel.c:41: error: ‘s’ undeclared (first use in this function)
sel.c:41: error: (Each undeclared identifier is reported only once
sel.c:41: error: for each function it appears in.)

This is the trickiest one. You would expect that you were properly declaring a variable s in line 38 - but the compiler complains. The reason for this is explained in the excellent Q&A at Why can't variables be declared in a switch statement?

As an aside - if you COULD declare a variable like this - what are you doing with it? Your code currently reads in values, and returns. But as soon as you leave the "scope" of the variable (in your case, since you declared s inside the switch, that would be its scope) the variable disappears (the memory that was used for it is marked "free" and will be re-used.)

sel.c:61: warning: control reaches end of non-void function

This says that you have reached the end of a function that expects to return a value, but you don't have a return someValue; type of statement. Again - this only causes a warning, since the default behavior is to return 0 if no value is given, but it's a sign that you said one thing and did another.

So far I've just explained the errors that the compiler gave. Let's look more closely at the code structure. What I think you want to do is something like this:

define customerInfo structure
define menu function
main()
  repeat:
    call menu, get selection
    switch(selection):
      case 1: create new record
      case 2: display records
      case 3: quit program

In order to make this work, we need to make some changes to your program. First - let's move the menu function definition outside of the main function so we have portable code. Second - if we want to be able to create multiple customer records, we need to store them in an array. Really you would want a list so you can extend indefinitely, but let's keep it simple and allow a maximum of 10 records. Then we need to improve the logic of the menu function (if selection is not 1, 2 or 3 you give a message and try again; in your current code the line

printf("You have entered an incorrect value");  

doesn't get executed until you have exited the loop that tested for incorrect values… so when you finally get there, the value is valid, not invalid.

Before we actually get to writing the "correct" code, there's another thing worth noting. When you read values using scanf, you do things like:

           scanf("%s", s.FirstName);    

which is correct, since s.FirstName is a pointer to the start of a string. However, you allocated a finite amount of space to your string (namely, 15 characters including the terminating '\0') so if someone enters a long name, your program will crash. "Good defensive coding" demands that you catch this - use for example

       scanf("%14s", s.FirstName); 

This says "read no more than 14 characters". There are better tricks but at least this is a start. However, you actually make a mistake when you do

       scanf("%s", s.ID);

Since ID was defined as an int, and now you are reading a string into… not just its address, but into some location that is pointed to by the value of s.ID . This is very likely to give you a segmentation error (accessing memory that "isn't yours"). You should be doing:

       scanf("%d", &s.ID);

"Read an integer into the location of s.ID"

Also - in some places you use FirstName, while in others you use Firstname. Ditto LastName. Capitalization matters - when you fix other compiler errors, these will start to show up.

Since you seem to want to be able to read in more than one customer record, we need an array of records; as I said above, we have to make sure the array is available in the scope of the switch statement, and "survives" that statement (so you can do something with it). Taking all these things together gets us to something like this:

#include <stdio.h>

// define function prototype:
int menu();

struct CustomerInfo
{
  char FirstName[15];        /* These are the variables for the customer infomation */
  char LastName[20];
  int ID;
};

int menu()
{                    /* Menu loop function */
  int flag = 0;
  int selection;
  do
  {                                                                   /* menu start */
     if(flag > 0) printf("You have entered an incorrect value");  /* If selection is greater than 3 then end program */
     printf("\n\n - What would you like to do?");
     printf("\n1  - Store a customer record");
     printf("\n2  - View customer Records");
     printf("\n3  - Quit program\n>> ");
     scanf("%i", &selection);
     flag++;
   }   while (flag < 10 && (selection < 0 ||selection > 3));

   return selection;
}

int main(void)
{                               /* program starts */

struct CustomerInfo s[10];
int selection;
int customerCount = 0;

while(1) {
  int ii; // loop counter we will need later
  selection = menu();
  switch(selection)
  {
    case 1:
      printf("Please enter the customers details including First name, Lastname and ID.\n\n");
      printf("Enter First name: ");
      scanf("%s", s[customerCount].FirstName);                                           /* Option 1: Asks to enter the customers details to store then loops back to program */
      printf("Enter Last name:  ");
      scanf("%s", s[customerCount].LastName);
      printf("Enter Customer ID: ");
      scanf("%d", &s[customerCount].ID);
      customerCount++;
      break;

    case  2:
      printf("\nDisplaying Infomation\n");
      for(ii = 0; ii < customerCount; ii++) {
        printf("First name: %s\n",s[ii].FirstName);                             /* Option 2: Prints the customer details as listed in option 1 */
        printf("Last name: %s\n",s[ii].LastName);
        printf("Customer ID: %d\n---\n",s[ii].ID);
      }
      break;

      case  3:                /* Option 3:     Program ends if option 3 is chosen. */
        return 0; // program returns
        break;
      }
   }
}

Test output:

 - What would you like to do?
1  - Store a customer record
2  - View customer Records
3  - Quit program
>> 1
Please enter the customers details including First name, Lastname and ID.

Enter First name: John
Enter Last name:  Smith
Enter Customer ID: 123


 - What would you like to do?
1  - Store a customer record
2  - View customer Records
3  - Quit program
>> 5
You have entered an incorrect value

 - What would you like to do?
1  - Store a customer record
2  - View customer Records
3  - Quit program
>> -1
You have entered an incorrect value

 - What would you like to do?
1  - Store a customer record
2  - View customer Records
3  - Quit program
>> 1
Please enter the customers details including First name, Lastname and ID.

Enter First name: Harry
Enter Last name:  Jones
Enter Customer ID: 654


 - What would you like to do?
1  - Store a customer record
2  - View customer Records
3  - Quit program
>> 2

Displaying Infomation
First name: John
Last name: Smith
Customer ID: 123
---
First name: Harry
Last name: Jones
Customer ID: 654
---


 - What would you like to do?
1  - Store a customer record
2  - View customer Records
3  - Quit program
>> 3

Upvotes: 3

Related Questions