2016-03-04 86 views
0

我是C編程和指針的新手。 我做了一個簡單的程序,我可以在字符串中讀取,程序會告訴您有多少個字符以及多少個字母出現多少次。 不知何故,我的輸出是不正確的。我認爲這可能是我的指針和解引用問題。簡單的字符串計數器程序調試(指針)

這裏是我的主:

extern int* count (char* str); 

int main(int argc, char* argv[]) 
{ 
    int numOfChars =0; 
    int numOfUniqueChars = 0; 
    char str[80]; 
    int *counts; 

    strcpy(str, argv[1]); 
    printf("counting number of characters for \"%s\"..\n", str); 
    printf("\n"); 

    counts = count(str); 

    int j; 
    for (j =0; j<sizeof(counts); j++) 
    { 
    if(counts[j]) 
     printf("character %c", *str); 
     printf("appeared %d times\n", counts[j]); 
     numOfChars++; 
     numOfUniqueChars++; 
    } 

    printf("\"%s\" has a total of %d character(s)\n", str, numOfChars); 

    printf(wow %d different ascii character(s) much unique so skill\n", numOfUniqueChars); 
} 

,這是我的計數功能:

int* count(char* str) 
{ 
    int* asctb = malloc(256); 
    int numOfChars =0; 
    int i; 
    int c; 
    for(i = 0; i<strlen(str); i++) 
     c = str[i]; 
     asctb[c]++; 

    numOfChars += strlen(str); 

    return asctb; 
} 

,當我編譯並運行它,我的成績出現這樣的:

./countingCharacter doge

計數數量o f的字符爲 「公爵」 ......

出現0次

出現0次

出現0次

出現0次

「總督」 一共有4個字符的(s)

4個不同的ascii字符(s)很獨特所以技能

不過,我想我的結果是這樣的:

字符d出現1次

符號E出現1次

字摹出現1次

字符Ø出現1次

「doge」共4個字符

哇4不同ASCII字符(或多個)多唯一的,這樣技術人員

任何幫助將不勝感激。

在此先感謝!

編輯:

我加花括號我在主函數循環。

現在我得到這樣的結果:

。/ countingCharacter DOGE

字符@出現7912倍

字符d出現1次

符號E出現1次

字符克出現1次

字符ö出現1次

爲什麼我會在beginni中得到那個「@」 NG?

+2

這可能不是你唯一的問題,但一個主要問題是,你似乎認爲C縮進用於範圍界定。事實並非如此。因此,您的'for'循環和'if'塊的一些不正確,因爲它們的主體只包含下一行代碼,而不是您明確指定的整個代碼塊。您需要將循環/ if body放入大括號中:'for(...){}' – kaylum

+0

@kaylum哦,非常感謝您的提示! :) – Ananymus

+1

'for(j = 0; j

回答

0

@kaylum說,一個特別大的問題是你使用大括號。如果在控制流程語句(iffor,while等)中不使用大括號,則只有下一行被計爲該語句的一部分。因此,該段:

if (counts[j]) 
    printf("character %c", *str); 
    printf("appeared %d times\n", counts[j]); 
    /* ... */ 

...將只執行第一printf如果counts[j] != 0,但將無條件執行以下語句。

您使用malloc也是不正確的。 malloc(256)將只分配256個字節;一個int通常是4個字節,但是這取決於編譯器和機器。因此,malloc「荷蘭國際集團的任何類型的數組時,它使用以下技術好的做法:

type *array = malloc(element_count * sizeof(type)); 

在你的情況,這將是:

int *asctb = malloc(256 * sizeof(int)); 

這將確保你有房計算所有可能的值char。此外,由於sizeof (counts)不能準確地表示數組的大小(根據您的系統,它很可能是4或8),因此您必須更改通過counts進行迭代的方式。

變量numOfChars將不會像您期望的那樣工作。它看起來像你試圖在兩個函數之間分享它,但由於它聲明的方式,這不會發生。爲了全局訪問該變量,需要在全局範圍處聲明,而不是任何函數。

此外,該行:

printf("character %c ", *str); 

...既不跟蹤你打印什麼字也沒有哪你應該,而不是僅僅重複印刷的第一個字符。 *str應該是(char)j,因爲您正在打印ASCII值。

我認爲應該這樣做。

+0

非常感謝。你的答案解決了我的程序中的所有問題!我很感激! – Ananymus

0

如果您是C的新手,您的代碼中有許多問題需要注意。首先,如果函數返回一個值,則驗證該值。否則,從你的代碼中的那一點開始,你可能不確定它實際上是在你認爲的值或內存位置上運行。例如,每個以下的應被驗證(或更改留陣列允許範圍內):

strcpy(str, argv[1]); 

int* asctb = malloc(256); 

counts = count(str); 

如果argv[1]100字符?如果malloc返回NULL?你怎麼知道count成功了?始終包含代碼所需的必要驗證。

儘管沒有錯誤,但C的標準編碼風格避免了caMelCase變量,而有利於所有小寫字母。見例如NASA - C Style Guide, 1994所以

int numOfChars =0; 
int numOfUniqueChars = 0; 

可能僅僅是ncharsnunique

接下來,您所有的iffor循環語法無法將所需的語句封裝在括號(例如, {...}爲您的iffor創建適當的塊。例如,以下內容:

for(i = 0; i<strlen(str); i++) 
    c = str[i]; 
    asctb[c]++; 

僅遍歷c = str[i];asctb[c]++;時才執行AFTER退出循環。

您必須初始化您的變量,(尤其是你的數組元素)之前嘗試引用它們,否則不確定的行爲結果。 (它看起來可以工作,給怪異的輸出像一個奇怪的"@"字符,或段錯誤,這就是爲什麼它是未定義的)。這裏有個大問題:

int* asctb = malloc(256); 

沒有初始化asctb中的任何值。因此,當您將數組返回到main()並遍歷數組中的所有值時,每個未明確賦值的元素都會導致未定義的行爲。您可以設置所有值0memset,或者當你需要初始化所有值識別和使用calloc代替:

int *asctb = calloc (1, 256); 

避免在代碼中使用「魔數」的。上面的256就是一個很好的例子。不要亂丟你用這些魔法數字編碼,而是在代碼開始時用#define或數字常量爲它們定義一個常數,而改爲使用enum

最後,動態分配內存的任何代碼你寫的,你有關於分配的任何內存塊2個responsibilites:(1)總是保留一個指針的起始地址的內存塊左右,(2 )當不再需要時,可以使用free來釋放它。您應該通過在Linux上運行代碼內存錯誤檢查程序(如valgrind)來驗證您的內存使用情況。這很容易做到,並且會比你想象的更多時間爲你節省你的時間。

把所有這些碎片拼湊起來,並在你的代碼固定額外的邏輯錯誤,你看起來像你正在嘗試類似下面的內容:

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

/* constants for max characters in str and values in asctb */ 
enum { MAXC = 80, MAXTB = 128 }; 

int *count (char *str); 

int main (int argc, char **argv) { 

    if (argc < 2) { /* validate str given as argument 1 */ 
     fprintf (stderr, "error: insufficient input, usage: %s str.\n", 
       argv[0]); 
     return 1; 
    } 

    /* initialize all variables avoid CamelCase names in C */ 
    char str[MAXC] = ""; 
    int j = 0, nchars = 0, nunique = 0; 
    int *counts = NULL; 

    strncpy (str, argv[1], MAXC - 1); /* limit copy len */ 
    str[MAXC - 1] = 0; /* nul-terminate str */ 

    printf ("\ncounting number of characters for \"%s\"..\n\n", str); 

    if (!(counts = count (str))) { /* validate return */ 
     fprintf (stderr, "error: count() returned NULL.\n"); 
     return 1; 
    } 

    for (j = 0; j < MAXTB; j++) 
     if (counts[j]) { 
      printf ("character '%c' appeared: %d times\n", 
        (char)j, counts[j]); 
      nchars += counts[j]; 
      nunique++; 
     } 

    free (counts); /* free allocated memory */ 

    printf ("\n\"%s\" has a total of %d character(s)\n", str, nchars);  
    printf (" wow %d different ascii character(s) much unique so skill\n\n", 
      nunique); 

    return 0; /* main is a function of type 'int' and returns a value */ 
} 

int *count (char *str) 
{ 
    if (!str) return NULL; /* validate str */ 

    int *asctb = calloc (1, sizeof *asctb * MAXTB); 
    size_t i; /* you are comparing with size_t in loop */ 

    if (!asctb) { /* validate memory allocation - always */ 
     fprintf (stderr, "count() error: virtual memory exhausted.\n"); 
     return NULL; 
    } 

    for(i = 0; i < strlen(str); i++) 
     asctb[(int)str[i]]++; /* array indexes are type 'int' */ 

    return asctb; 
} 

注:counts第一30字符是非打印範圍,請參閱ASCIItable.com。索引保留原樣,但請注意,在實踐中,除非您有興趣計算不可打印的\t,\n等字符,否則請注意實際情況。

示例使用/輸出

$ ./bin/ccount "address 12234" 

counting number of characters for "address 12234".. 

character ' ' appeared: 1 times 
character '1' appeared: 1 times 
character '2' appeared: 2 times 
character '3' appeared: 1 times 
character '4' appeared: 1 times 
character 'a' appeared: 1 times 
character 'd' appeared: 2 times 
character 'e' appeared: 1 times 
character 'r' appeared: 1 times 
character 's' appeared: 2 times 

"address 12234" has a total of 13 character(s) 
wow 10 different ascii character(s) much unique so skill 

過目邏輯和語法修正,讓我知道,如果您有任何進一步的問題。