2017-09-03 40 views
1

我想要一個函數,它需要一個數組充滿字符串和計數單詞。我不認爲我的代碼在圖片中是錯誤的。每次出現空白時都會被計數。但是當'\0'字符出現時,while循環不會執行任何操作。是我不知道的東西?' 0'字符在一個while循環在c

int Number(char w[][20]) { 
    int i, counter, j; 
    counter = 0; 
    for (i = 0; i < 4; i++) { 
     j = 0; 
     do { 
      if ((w[i][j] == '\0') || (w[i][j] == ' ')) 
       ++counter; 
      j++; 
     } while (w[i][j] != '\0'); 
     printf("counter=%d\n", counter); 
    } 
} 
+2

如果字符串是 「空」,即,僅包括' 「\ 0」''然後\ 0'將被計數,但否則'do .. while()'循環條件將'\ 0'排除在考慮之外。我建議使用'while(){...}'循環。想一想「何時出現'\ 0'字符」。它不是* C字符串中的字符*,而是它的結束標記。 –

+0

當它到達\ 0字符時,循環停止,那麼爲什麼你認爲它會被計算? – immibis

+0

while循環不起作用。如果我沒有在一行中放入任何二維數組,那麼這一段時間根本不會被執行......儘管在我寫論壇之前,我仍嘗試過。 –

回答

0

有在你的代碼的一些問題:

  • 如果線路沒有字符(帶'\0'啓動),您的測試字符串結束前增加j。不要使用do/while循環,它們很容易出錯,而且這個bug是一個典型的錯誤。
  • 您只需計算空格的數量:這與單詞的數量不同,因爲在兩個單詞之間或在行的開始或結尾處可能有多個空格等。您應該計算從從太空開始的非空間空間。

這裏是您的2D陣列的一個簡單實現:

int Number(char w[][20]) { 
    int i, j, counter = 0; 
    for (i = 0; i < 4; i++) { 
     char c, last = ' '; 
     for (j = 0; (c = w[i][j]) != '\0'; j++) { 
      if (last == ' ' && c != ' ') 
       counter++; 
      last = c; 
     } 
    } 
    printf("counter=%d\n", counter); 
} 
+0

你是對的。在一個完整的程序中是必要的。你的方法比我的更聰明,我會重寫我的函數。我不知道爲什麼這個該死的轉義整數'\ 0'結束了我的操作...while循環結束之前,但我會有一個更好,更多的邏輯程序。謝謝你的時間。 –

1

只要遇到'\0'字符,您的內循環就會終止。唯一一次遇到'\0'時會計數的東西是當w[i][0] == '\0'i時。對於某些j > 0,位置w[i][j]上的任何將不會導致counter增加,因爲循環將被預先終止。

+0

你確定嗎?它看起來好像它計算空字節,因爲在尾部'while'之前,在循環體內出現null或空白測試。 –

+0

我確定。循環的主體也增加'j'。這意味着除非''\ 0''是'w [i]'的第一個字符,循環終止。舉一個具體的例子,假設'w [0]'是字符串'「ab \ 0cd」'(我們只是在C中避開它,字符串被NUL終止)。我們從'j == 0'開始,進入循環,並比較'if'中的'w [0] [0]'。現在我們增加'j',並繼續循環,因爲w [0] [1]'不是'''0'。在第二次迭代期間,我們檢查'if'中的'w [0] [1]'並增加'j'。現在,門衛檢查'w'[0] [2]'到'\ 0'',終止循環。 – Abigail

+0

注意''ab \ 0cd「'不是一個字符串;一個字符串停在第一個空字節處; –

0
- The first principle of programming is: divide and conquer 
- The second is: use a loop to iterate 
So: 

unsigned count_words(char*str) 
{ 
unsigned len, words; 

for(len=words=0; *str; str++){ 
     if(*str == ' ') if(len) {words++; len=0;} 
     else len += 1; 
     } 

if (len) {words++; } 
return words; 
} 

現在,調用這個函數任何你的字符串,加入的結果。

1

下面是您的代碼的工作版本和測試程序。

#include <stdbool.h> 
#include <stdio.h> 

static int wc(const char *str) 
{ 
    int count = 0; 
    bool inword = false; 

    char c; 
    while ((c = *str++) != '\0') 
    { 
     if (c == ' ') 
      inword = false; 
     else 
     { 
      if (inword == false) 
       count++; 
      inword = true; 
     } 
    } 
    return count; 
} 

static void Number(const char *tests[], int num_tests) 
{ 
    for (int i = 0; i < num_tests; i++) 
     printf("%d: [%s]\n", wc(tests[i]), tests[i]); 
} 

int main(void) 
{ 
    const char *tests[] = 
    { 
     "", 
     " ", 
     " ", 
     "a", 
     "a b", 
     " a b ", 
     " ab cd ", 
     "The quick brown fox jumps over the lazy  dog.", 
     "  The quick brown fox jumps over the lazy  dog. ", 
    }; 
    enum { NUM_TESTS = sizeof(tests)/sizeof(tests[0]) }; 
    Number(tests, NUM_TESTS); 
    return 0; 
} 

請注意,您​​函數完成兩項工作 - 並且應該只做一,委託對方一個單獨的函數。它既計算單個字符串中的單詞並打印相關信息。我將計數單詞委託給單獨的函數wc(),這極大地簡化了​​中的代碼 - 幾乎不需要該函數。還請注意,我的版本​​被告知它正在處理的數組的條目數量,而不是依賴像4這樣的幻數。請注意,我的代碼輸出允許您檢查它的準確性。只需打印輸出號碼不會讓您輕鬆檢查準確性;您必須查看代碼才能瞭解數字的含義。請注意,您的​​函數被定義爲返回int,但實際上並沒有這樣做。這個版本被定義爲不返回任何東西,而不是。

從代碼的輸出是:

0: [] 
0: [ ] 
0: [ ] 
1: [a] 
2: [a b] 
2: [ a b ] 
2: [ ab cd ] 
9: [The quick brown fox jumps over the lazy  dog.] 
9: [  The quick brown fox jumps over the lazy  dog. ] 

很顯然,你可以使用isblank()isspace()宏(功能)從<ctype.h>細化空間測試,如果你願意,也可以定義字和不可─之間的邊界用其他方式說話。儘管如此,基本的概念是可靠的,可以跨越空白和文字的相當不正確的序列。

如果你真的想要一個二維數組的字符,編寫代碼來處理這個問題並不難,儘管'懶狗'字符串將不得不簡化爲適合char data[][20]。基本思路保持不變 - wc()函數不會改變。

#include <stdbool.h> 
#include <stdio.h> 

static int wc(const char *str) 
{ 
    int count = 0; 
    bool inword = false; 

    char c; 
    while ((c = *str++) != '\0') 
    { 
     if (c == ' ') 
      inword = false; 
     else 
     { 
      if (inword == false) 
       count++; 
      inword = true; 
     } 
    } 
    return count; 
} 

static void Number(const char tests[][20], int num_tests) 
{ 
    for (int i = 0; i < num_tests; i++) 
     printf("%d: [%s]\n", wc(tests[i]), tests[i]); 
} 

int main(void) 
{ 
    const char tests[][20] = 
    { 
     "", 
     " ", 
     " ", 
     "a", 
     "a b", 
     " a b ", 
     " ab cd ", 
     "The quick brown fox", 
     " jumps over  ", 
     " the lazy dog ", 
    }; 
    enum { NUM_TESTS = sizeof(tests)/sizeof(tests[0]) }; 
    Number(tests, NUM_TESTS); 
    return 0; 
} 

輸出:

0: [] 
0: [ ] 
0: [ ] 
1: [a] 
2: [a b] 
2: [ a b ] 
2: [ ab cd ] 
4: [The quick brown fox] 
2: [ jumps over  ] 
3: [ the lazy dog ] 

測試像"  ab  cd  "例子(帶雙空格在開始,中間和結尾)往往是非常好的推邊緣情況 - 在不僅僅是字計數多個上下文。例如,許多shell腳本不會正確處理像那個字符串這樣的參數。

+0

你是絕對正確的,事實上我的功能哲學調整''和詞必須改變。 –