2017-02-17 63 views
0

我有以下的方法,在兩個字符串讀取更改數據庫中的兩個條目的姓和名。該名稱總是被轉換爲小寫字母,並且只能使用帶有字母或連字符的名稱,除非連字符是字符串中的第一個或最後一個字符。出現錯誤時,它只會再次提示用戶。在我的C代碼的邏輯錯誤

/* 
Prompts for a student name, and checks if input is correct. 
Returns 0 on success, -1 onEOF. 
If the user inputs an invalid entry, the error is ignored and the user is simply asked again. 
*/ 
int get_name(char *first, char *last) 
{ 
char input[LINESIZE]; 
char buffer[LINESIZE]; 
char buffer2[LINESIZE]; 
int i; 

while (1) 
{ 
    printf("\n%s", "Enter the Student Name "); 
    if (!fgets(input, LINESIZE, stdin)) 
    { 
     clearerr(stdin); 
     return -1; 
    } 
    if (sscanf(input, "%s %s", buffer, buffer2) == 2) 
    { 
     if (strlen(buffer) < 20 && strlen(buffer2) < 20 && strlen(buffer) >= 2 && strlen(buffer2) >= 2) /*checks to see if the length is at least 2, but less than 20*/ 
     { 
      for (i = 0; i < 20; i++) /*checks every character on the string, converts it to lower and then checks if it's a letter or a hyphen, restarts if not.*/ 
      { 
       if (isalpha(buffer[i])) 
       { 
        buffer[i] = tolower(buffer[i]); 
       } 
       if (isalpha(buffer2[i])) 
       { 
        buffer2[i] = tolower(buffer2[i]); 
       } 
       if (!isalpha(buffer[i]) && buffer[i] != '-') 
       { 
        break; 
       } 
       if (!isalpha(buffer2[i]) && buffer2[i] != '-') 
       { 
        break; 
       } 
      } 
      if (buffer[0] == '-' || buffer[(strlen(buffer) - 1)] == '-') 
      { 
       i = 0; 
      } 
      if (buffer2[0] == '-' || buffer2[(strlen(buffer2) - 1)] == '-') 
      { 
       i = 0; 
      } 
      if (i == 20) 
      { 
       sscanf(buffer, "%s", first); 
       sscanf(buffer2, "%s", last); 
       return 0; 
      } 
     } 
    } 
} 

}

我已經找到了錯誤的線條與(!isalpha(buffer[i]) && buffer[i] != '-'),但我不明白,爲什麼說法是錯誤的。

因此,舉例來說,一個成功的輸入可以是「約翰·史密斯」,或「坎洱辛普森」。在這兩種情況下,函數應該返回0(成功)。 如果輸入的是一樣的東西:「丹尼白」,「-Alexa雷德菲爾德」,「偉業」或「1234 5647」的功能應該只是重新開始(再次提示用戶)。 此刻,無論輸入什麼,功能都會重新開始。

+1

請出示一個例子輸入,預期輸出和實際輸出。 –

+0

如果沒有評論,很難說出這段代碼的哪些部分是有意做的。例如,爲什麼你測試'我'達到20?你認爲這是做什麼?你認爲最後這兩個'scanf'調用怎麼辦?這兩個「break」陳述的預期目的是什麼? –

+0

我的不好,我會編輯帖子以添加更多評論。我檢查i == 20的原因是因爲我打算使用for循環來檢查字符串中的每個字符是不是字母或連字符。如果for循環成功運行,那麼它將在i = 20處停止,這意味着輸入沒有問題,並且可以返回0(表示方法成功)。 sscanf使第一個=緩衝區,最後=緩衝區2。 – Snow

回答

1

在程序中的主要邏輯錯誤是,你是在同一時間兩個陣列運行for循環與迭代的固定數目(20)的事實。您應該爲第一個和最後一個名稱數組運行兩個單獨的循環。另外,您應該只運行這兩個循環,每個陣列只有strlen。請參見下面的示例:

for (i = 0; i < strlen(buffer); i++) 
{ 
    /* your existing stuff for the "buffer" */ 
} 

for (i = 0; i < strlen(buffer1); i++) 
{ 
    /* your existing stuff for the "buffer1" */ 
} 
+0

@WeatherVane,謝謝你的輸入。 「@雪」,請閱讀。 – VHS

+0

非常感謝!我的程序現在按預期工作。我在第二個循環中將i更改爲j,因爲它需要檢查兩個循環是否成功。 另外,在Weather Vane的回覆中,我不確定這是什麼意思? – Snow

+0

@WeatherVane我明白了。這是否會像'buffer [strlen(buffer)] ='/ 0''一樣簡單,還是更加複雜? – Snow

0

警告: VHS得到的主要問題。但是,這也指出了可以改進的代碼中的結構性問題。幾乎所有的代碼都是爲每個數組重複的。

創建陣列上運行將有一個函數[大概]使它更容易看清問題。

我返工你的代碼中加入這個[請原諒無償風格清理]:

#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 

#define LINESIZE 80 

int 
bufdo(char *buf) 
{ 
    int len; 
    int idx; 
    int chr; 
    int ret; 

    len = strlen(buf); 

    do { 
     // assume non-conforming 
     ret = -1; 

     // length too great 
     if (len >= 20) 
      break; 

     // length too small 
     if (len < 2) 
      break; 

     // begins with hyphen 
     if (buf[0] == '-') 
      break; 

     // ends with hyphen 
     if (buf[len - 1] == '-') 
      break; 

     // assume it will be okay 
     ret = len; 

     // convert to lowercase and check for bad chars 
     for (idx = 0; idx < len; ++idx) { 
      chr = buf[idx]; 

      if (isalpha(chr)) { 
       chr = tolower(chr); 
       buf[idx] = chr; 
       continue; 
      } 

      // non-hyphen char in name 
      if (chr != '-') { 
       ret = -1; 
       break; 
      } 
     } 
    } while (0); 

    return ret; 
} 

int 
get_name(char *first, char *last) 
{ 

    char input[LINESIZE]; 
    char buffer[LINESIZE]; 
    char buffer2[LINESIZE]; 
    int len1; 
    int len2; 
    int ret; 

    ret = -1; 

    while (1) { 
     printf("\n%s", "Enter the Student Name "); 
     fflush(stdout); 

     if (!fgets(input, LINESIZE, stdin)) { 
      clearerr(stdin); 
      break; 
     } 

     if (sscanf(input, "%s %s", buffer, buffer2) != 2) 
      continue; 

     len1 = bufdo(buffer); 
     len2 = bufdo(buffer2); 

     if ((len1 > 0) && (len2 > 0)) { 
      strcpy(first,buffer); 
      strcpy(last,buffer2); 
      ret = 0; 
      break; 
     } 
    } 

    return ret; 
} 
+0

非常感謝!這絕對是更方便。 – Snow

+0

不客氣!請注意,我建立了零碎的功能。最初,我把它稱爲'getlen',它只是做了'strlen'和長度範圍檢查。我打算爲其他步驟創建其他funcs,但是當我意識到它們會很好地適合該函數時,一次添加其他階段/步驟。所以,最終,單一的功能就足夠了。一個很好的經驗法則是考慮「規模」(即我的代碼是否足夠好?)。隨着更多的經驗,這些設計選擇將變得更容易看到和[幾乎]公理化。快樂編程! –