2013-11-01 107 views
1

我有我的語法的幾個問題,這主要是說就行了「結構CustomerInfo的「結構」之前,我有一個errror;但我不似乎找到了問題C編程結構錯誤

我的程序。應該詢問該人員首先想要做什麼,他們可以存儲第一個選項的記錄,然後將其存儲在可以通過選擇菜單的第二選項來查看的結構中,如果他們選擇第三選項他們顯然退出程序。

任何幫助,將不勝感激謝謝。

#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;

+2

你與幹嘛'無效菜單()'有不正確 - 移動出來的' main'函數,沒有它返回一個值,並將其稱爲只是'menu();' - 沒有'void'。 –

+0

@ChristianTernus,它應該返回'選擇' – Leeor

+0

我試過了,但是在 –

回答

3

讓我們先看看你創建的結構;接下來我們將嘗試查看它是否可以修復。 我離開了細節,所以我們可以看到大輪廓:

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 
    } 

。在你的代碼沒有最後結束的括號。我假設這是一個複製粘貼錯誤,所以我添加了它。與-Wall編譯(得到警告,以及報告錯誤),我得到了一些錯誤:

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 

讓我們的依次是:

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

把一個函數中另一個是「築巢」 。你很少會想這麼做 - 這意味着當你在另一個函數內(有點像局部變量,但是對於函數),函數只是「可見的」。這不是標準C - 它是gcc的延伸。使用非標準(因此不可移植)擴展幾乎總是一個壞主意。見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 

當我們聲明一個函數void,我們說,它不會返回一個值。當您有類似return 0;的聲明時,您將返回一個值。編譯器會忽略這一點 - 但它警告說你說了一件事,然後做了另一件事。只需使用return;而不帶參數,並且警告消失。

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.) 

這是最棘手的一個。你會期望你在第38行正確地聲明瞭一個變量s - 但編譯器會抱怨。原因是在優秀Q & A在 Why can't variables be declared in a switch statement?

另一方面 - 如果你可以聲明一個這樣的變量 - 你在做什麼?您的代碼當前讀入值並返回。但只要你離開變量的「範圍」(在你的情況下,因爲你在switch內聲明s,這將是它的範圍)變量消失(用於它的內存被標記爲「空閒」被重新使用。)

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

這是說你已經達到一個期望返回值的函數結束,但你沒有return someValue;類型的語句。再次 - 這隻會導致警告,因爲如果沒有給出任何值,默認行爲是返回0,但這是一個跡象表明您說了一件事,做了另一件事。

到目前爲止,我剛剛解釋了編譯器給出的錯誤。讓我們仔細看看代碼結構。我認爲你想要做的是這樣的:

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 

爲了使這項工作,我們需要作出一些改變你的計劃。首先 - 我們將menu函數定義移到main函數之外,這樣我們就可以使用便攜式代碼。其次 - 如果我們想要創建多個客戶記錄,我們需要將它們存儲在一個數組中。真的,你會想要一個列表,所以你可以無限延長,但讓我們保持簡單,並允許最多10條記錄。然後,我們需要提高菜單功能的邏輯(如果選擇不爲1,2或3,你發出的信息,然後再試一次;在當前的代碼行

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

沒有得到執行,直到你有退出測試不正確值的循環...所以當你終於到達那裏時,這個值是有效的,而不是無效的

在我們真正開始寫「正確的」代碼之前,還有另外一件值得注意的事情。使用scanf,你可以這樣做:

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

這是正確的,因爲s.FirstName是一個指向字符串開頭的指針。但是,您爲字符串分配了有限的空間(即15個字符,包括終止的'\0'),因此如果有人輸入長名稱,程序將崩潰。 「良好的防禦性編碼」要求你抓住這一點 - 例如使用

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

這說「閱讀不超過14個字符」。有更好的技巧,但至少這是一個開始。但是,你實際上犯了一個錯誤,當你做

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

由於ID被定義爲int,而現在你正在閱讀一個字符串轉換爲...不只是它的地址,而是進入一些的位置,是由指向值爲s.ID。這很可能會導致分段錯誤(訪問「不屬於你」的內存)。你應該做的事:

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

「讀整成s.ID位置」

而且 - 在一些地方使用FirstName,而在其他國家使用Firstname。同上LastName。大寫事關重大 - 當您解決其他編譯器錯誤時,這些錯誤將開始顯現。

由於您似乎希望能夠閱讀多個客戶記錄,因此我們需要一組記錄;正如我上面所說的那樣,我們必須確保該數組在switch語句的範圍內可用,並且「存活」該語句(以便您可以使用它)。考慮到所有這些東西聚在一起我們是這樣的:

#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; 
     } 
    } 
} 

測試輸出:

- 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 
+0

+ +1爲了花時間去糾正這個詳細的答案。 –

+0

@ShafikYaghmour - 有時候會失眠。我瞭解到,當我研究這個時,你不能在'switch'中聲明局部變量......所以我覺得我也從中得到了一些東西。 – Floris

+0

@弗洛利斯+1對這個問題和解決方案的一個非常令人印象深刻的故障和解釋。希望OP能從中學到一些東西。 –