字符串指针数组上的字符频率

时间:2016-01-19 11:49:31

标签: c string pointers

我正在进行一项练习,要求我:

  1. 读取用户的20个字,
  2. 将它们保存在指针数组上,具体取决于它们的内存大小, 分配
  3. 找到字母的频率,
  4. 在直方图上打印出来。
  5. 第1步和第2步可以正常运行我的代码。问题在于频率。我已经放置了一个测试printf来查看它是否正常工作,结果表明它不计算字符。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define N         20
    #define MAX_SIZE  200
    
    int main() {
        char *words[N];
        int i, c = 0, length;
        char *temp;
        int freq[26] = { 0 };
    
        temp = (char *)malloc(MAX_SIZE * sizeof(char));
    
        for (i = 0; i < N; i++) {
            printf("Give a word:");
            gets(temp);
            length = strlen(temp);
            *(words + i) = (char *)malloc((length + 1) * sizeof(char));
            strcpy(*(words + i), temp);
            printf("%s\n", *(words + i));
        }
        free(temp);
    
        while (*words[c] != '\0' && c < 20) {
            if ((*words[c] >= 'a' && *words[c] <= 'z') || (*words[c] >= 'A' &&  *words[c] <= 'Z')) {                    
                freq[*words[c] - 'a']++;
                words[c]++;
            }
            c++;
        }
    
        for (i = 0; i < 26; i++) {
            printf("%c occurs %d times in the entered string.\n", i + 'a', freq[c]);
        }
        return 0;
    }
    

3 个答案:

答案 0 :(得分:2)

您的代码有几个问题:

  • 修改words数组中的指针,而不是通过索引进行迭代。
  • 您检查大写字母,但在这种情况下使用freq[*words[c]-'a']访问其边界之外的偏移量。
  • 最后一个循环中有拼写错误:如果freq[i],则应为freq[c]
  • 您不需要分配数组temp
  • 您不得使用已从标准中删除的getsgets无法检查缓冲区溢出,任何恶意输入都可能产生无法估量的后果。
  • 您应该检查malloc失败

以下是更正后的版本:

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

#define N         20
#define MAX_SIZE  200

int main(void) {
    char *words[N];
    int n, i, j, c, length;
    char temp[MAX_SIZE];
    int freq[26] = { 0 };

    for (n = 0; n < N; n++) {
        printf("Give a word:");
        if (!fgets(temp, sizeof temp, stdin))
            break;
        temp[strcspn(temp, "\n")] = '\0';  /* strip the \n if present */
        length = strlen(temp);
        words[n] = malloc(length + 1);
        if (words[n] == NULL) {
            printf("cannot allocate memory\n");
            exit(EXIT_FAILURE);
        }
        strcpy(words[n], temp);
        printf("%s\n", words[n]);
    }

    for (i = 0; i < n; i++) {
        for (j = 0; (c = words[i][j]) != '\0'; j++) {
            if (c >= 'a' && c <= 'z')
                freq[c - 'a']++;
            else
            if (c >= 'A' && c <= 'Z')
                freq[c - 'A']++;
        }
    }

    for (i = 0; i < 26; i++) {
        if (freq[i] > 0)
            printf("%c occurs %d times in the entered strings.\n", i + 'a', freq[c]);
    }
    return 0;
}

答案 1 :(得分:1)

你似乎只检查每个单词的第一个字母,然后继续下一个单词。显然你需要在那里工作2个循环。

或类似的东西:

while (c<N) {
    if(( *words[c]>='a' && *words[c]<='z') || (*words[c]>='A' &&  *words[c]  <='Z')) {                    

        freq[*words[c]-'a']++;
    }
    words[c]++;
    if(*words[c] == '\0')
        c++;
}

但我认为你最终会得到一系列字符串的结尾,这似乎并不重要,但它仍然很奇怪。

答案 2 :(得分:0)

首先区分大小写。这可能不是完整的解决方案,但它只是一个开始。

    if (*words[c]>='a' && *words[c]<='z'){                       
        freq[*words[c]-'a']++;
        words[c]++;
    }
    else if (*words[c]>='A' &&  *words[c]  <='Z'){                       
        freq[*words[c]-'A']++;
        words[c]++;
    }