如果您是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;
可能僅僅是nchars
和nunique
。
接下來,您所有的if
和for
循環語法無法將所需的語句封裝在括號(例如, {...}
爲您的if
或for
創建適當的塊。例如,以下內容:
for(i = 0; i<strlen(str); i++)
c = str[i];
asctb[c]++;
僅遍歷c = str[i];
和asctb[c]++;
時才執行AFTER退出循環。
您必須初始化您的變量,(尤其是你的數組元素)之前嘗試引用它們,否則不確定的行爲結果。 (它看起來可以工作,給怪異的輸出像一個奇怪的"@"
字符,或段錯誤,這就是爲什麼它是未定義的)。這裏有個大問題:
int* asctb = malloc(256);
沒有初始化asctb
中的任何值。因此,當您將數組返回到main()
並遍歷數組中的所有值時,每個未明確賦值的元素都會導致未定義的行爲。您可以設置所有值0
與memset
,或者當你需要初始化所有值識別和使用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
過目邏輯和語法修正,讓我知道,如果您有任何進一步的問題。
這可能不是你唯一的問題,但一個主要問題是,你似乎認爲C縮進用於範圍界定。事實並非如此。因此,您的'for'循環和'if'塊的一些不正確,因爲它們的主體只包含下一行代碼,而不是您明確指定的整個代碼塊。您需要將循環/ if body放入大括號中:'for(...){}' –
kaylum
@kaylum哦,非常感謝您的提示! :) – Ananymus
'for(j = 0; j