[英]How to find number of occurrences in array of chars in C?
我試圖輸入一個單詞,並輸入多少次字母。
說我的輸入是“你好”
我的輸出將是:h = 1,e = 1 l = 2等等。
我已經很接近正確了,但是這段代碼有一個小問題:
#include <stdio.h>
#include <string.h>
void find_frequency(char s[], int count[]) {
int c = 0;
while (s[c] != '\0') {
if (s[c] >= 'a' && s[c] <= 'z' )
count[s[c]-'a']++;
c++;
}
}
int main()
{
char string[100];
int c, count[26] = {0};
printf("Input a string\n");
gets(string);
find_frequency(string, count);
printf("Character Count\n");
for (c = 0 ; c < 26 ; c++)
if(count[c] > 0)
printf("%c : %d\n", c + 'a', count[c]);
return 0;
}
這段代碼完成了一半的工作,但不是全部。
它的輸出按字母順序排列。 我怎樣才能改變它,使我得到的只是輸入的chararray的輸出?
正如Ry-在此評論中建議的那樣,您可以迭代回原始字符串,並使用char作為頻率表的索引。 類似於以下內容:
int len_string = strlen(string);
for (c=0; c<len_string; c++) {
char ch = string[c];
printf("%c: %d, ", ch, count[ch-'a']);
}
這不會完全符合您的預期輸出,因為此代碼將兩次輸出l: 2
,但這引發了一個問題:
當您使用abba
類的字符串時,預期輸出是什么? a:2, b:2
嗎? a:1, b:2, a:1
嗎? a: 2, b:2, a:2
? 當您問這樣一個模棱兩可的問題時,很難提供幫助。
#include <stdio.h>
#include <string.h>
size_t ASCIIfreq[256];
void CountASCII(void *buff, size_t size)
{
unsigned char *charsptr = buff;
memset(ASCIIfreq, 0, sizeof(ASCIIfreq));
while(size--)
{
ASCIIfreq[*charsptr++]++;
}
}
void print(int printall)
{
for(size_t index = 0; index < 256; index++)
{
if(ASCIIfreq[index] || printall)
{
printf("The %03zu (0x%02zx) ASCII - '%c' has occured in the buffer %zu time%c\n",
index, index, (index > 32 && index < 127) ? (char)index : ' ',
ASCIIfreq[index], ASCIIfreq[index] == 1 ? ' ' : 's');
}
}
}
int main()
{
char teststring[] = "i am trying to enter a word, and get how many times the letters were typed. Say my input is \"hello\" my output would be: h = 1, e = 1 l = 2 etc.I am very close to getting it right, but i have a small issue with this code";
CountASCII(teststring, sizeof(teststring));
print(0);
return 0;
}
目前尚不清楚您的意思是:
我怎樣才能改變它,使我得到的只是輸入的chararray的輸出?
因為無論如何這就是您要做的事情:向函數輸入一個char數組; 用字母順序更新數字; 然后按原樣輸出。
因此,我猜測您要按照首次遇到每個字符的順序輸出計數?
這將需要更多的工作。 您可以保留另一個數組,以跟蹤在find_frequency
遇到每個字符的順序。 但是,然后那個簡單的clean函數開始做太多事情了。
因此,請考慮調整輸出方式:
void output_frequency(char s[], int count[]) {
int c = 0;
//loop s for the output
while (s[c] != '\0') {
if (s[c] >= 'a' && s[c] <= 'z' ) {
//found a character, report the count only if not reported before
if (count[s[c]-'a'] > 0) {
printf("%c : %d\n", s[c], count[s[c] - 'a']);
count[s[c]-'a'] = 0; //so you don't report this char again
}
}
c++;
}
}
如果您嘗試獲取有序計數而不是按字母順序計數,則只需要將count
數組的索引與輸入緩沖區中字符的順序進行協調。 為此,只需循環遍歷輸入緩沖區中的所有字符,然后進行第二遍計算當前字符出現的次數。 這將為您提供每個字符出現次數的有序計數,例如
#include <stdio.h>
#include <string.h>
#define COUNT 128
#define MAXC 1024
int main (void) {
char buf[MAXC] = ""; /* buffer to hold input */
int count[COUNT] = {0}; /* array holding inorder count */
fputs ("enter string: ", stdout); /* prompt for input */
if (!fgets (buf, MAXC, stdin)) { /* read line into buf & validate */
fputs ("error: EOF, no valid input.\n", stderr);
return 1;
}
/* loop over each character not '\n' */
for (int i = 0; buf[i] && buf[i] != '\n'; i++) {
char *p = buf; /* pointer to buf */
size_t off = 0; /* offset from start of buf */
while ((p = strchr (buf + off, buf[i]))) { /* find char buf[i] */
count[i]++; /* increment corresponding index in count */
off = p - buf + 1; /* offset is one past current char */
}
}
for (int i = 0; count[i]; i++) /* output inorder character count */
printf (i ? ", %c: %d" : "%c: %d", buf[i], count[i]);
putchar ('\n'); /* tidy up with new line */
return 0;
}
( 注意: strchr
是為了方便起見,簡單地查找字符串中當前字符的下一個出現位置,然后使用off
(offset)從以下字符開始搜索,直到在字符串中找不到其他匹配項為止。如果需要,可以對緩沖區中的字符使用附加循環。)
使用/輸出示例
$ /bin/charcnt_inorder
enter string: hello
h: 1, e: 1, l: 2, l: 2, o: 1
但是,這確實會重新計數每個字符,如果該字符重復,則會再次計數(例如,每個'l'
l: 2, l: 2
)。 現在不清楚:
“我的輸出將是:
h = 1, e = 1 l = 2
等等。”
在這方面您打算做什么,但只需付出一點額外的努力,就可以使用單獨的索引和單獨的數組來存儲每個字符的第一個實例(例如chars[]
數組)以及每個字符的計數count[]
數組並保留您的順序數,同時消除重復的字符。 所需的更改如下所示:
#include <stdio.h>
#include <string.h>
#define COUNT 128
#define MAXC 1024
int main (void) {
char buf[MAXC] = "",
chars[COUNT] = ""; /* array to hold inorder chars */
int count[COUNT] = {0};
size_t cdx = 0; /* add count index 'cdx' */
fputs ("enter string: ", stdout);
if (!fgets (buf, MAXC, stdin)) {
fputs ("error: EOF, no valid input.\n", stderr);
return 1;
}
for (int i = 0; buf[i] && buf[i] != '\n'; i++) {
char *p = buf;
size_t off = 0;
chars[cdx] = buf[i]; /* store in chars array */
if (i) { /* if past 1st char */
int n = i;
while (n--) /* simply check all before */
if (buf[n] == buf[i]) /* if matches current */
goto next; /* bail and get next char */
}
while ((p = strchr (buf + off, buf[i]))) {
count[cdx]++; /* increment count at index */
off = p - buf + 1;
}
cdx++; /* increment count index */
next:; /* goto label to jump to */
}
for (int i = 0; count[i]; i++)
printf (i ? ", %c: %d" : "%c: %d", chars[i], count[i]);
putchar ('\n');
return 0;
}
使用/輸出示例
$ /bin/charcnt_inorder2
enter string: hello
h: 1, e: 1, l: 2, o: 1
要么
$ ./bin/charcnt_inorder2
enter string: amarillo
a: 2, m: 1, r: 1, i: 1, l: 2, o: 1
現在,您的'l'
僅報告一次,且計數正確。
注意,在每個示例中,您都應該進行額外的驗證,以確保整個輸入適合您的緩沖區,等等。... count
(和chars
)數組的大小設置為128
以覆蓋整個ASCII值范圍。 不要忽略緩沖區大小。 如果您明確將輸入限制為大寫或小寫-則可以將計數大小限制為26
,否則,您需要考慮將要遇到的其他字符和標點符號。 這同樣適用於您的輸入緩沖區。 如果您預計最大輸入將為500個字符,則將其加倍(通常為下一個可用的2的冪,對2的冪沒有實際要求,但您很可能會這樣看)。
最重要的是,我寧願將10,000個字符過長,也不要將一個字符過短...導致Undefined Behavior 。
最后,正如我在評論中提到的,從來沒有,永遠也永遠不會使用gets
。 它是如此不安全,已從C11中的C標准庫中刪除。 請改用fgets
或POSIX getline
。
仔細檢查一下,如果您還有其他問題,請告訴我。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.