计算一个句子的字母给出随机输出

时间:2017-04-11 10:02:13

标签: c arrays string scanf fgets

我需要我的程序输入用户想要输入的句子数,然后输入这些句子。然后,通过传递函数letter(),我希望它计算在字符串中看到每个字母的次数。但是,我遇到了以下问题:

  1. 当我输入行数时,程序只要求用户输入比输入的数字少1(即如果我想要2个句子,我只会提示一个)。
  2. 字母数不起作用。看起来好像是随机的。
  3. 此外,我想知道我是否正确使用我的2D数组(即我正确填充它并且我正确地通过该功能)。对于数组str[][],我希望第一个框表示句子数,第二个框表示每行中的字符数。

    这是我的代码:

    #include <stdio.h>
    
    void letter(int n, char str[][80]){
        char c = 'a';
        char alpha[26];
        int ltrcnt[26];
    
        for(int i = 0; i < 26; i++){
            ltrcnt[i] = 0;
        }
    
        for(int i = 0; i < 26; i++){
            for(int j = 0; j < 26; j++){
                for(int k = 0; k < 26; k++){
                    if(str[i][j] == c){
                        ltrcnt[k]++;
                    }
                    c++;
                }
            }
        }
    
        c = 'a';
        for(int i = 0; i < 26; i++){
            printf("%c: %d\n", c, ltrcnt[i]);
            c++;
        }
    }   
    
    int main(void){
        int n;
    
        printf("Enter number of lines: ");
        scanf("%d", &n);
    
        char str[n][80];
        printf("Enter a sentecne: ");
        for(int i = 0; i < n; i++){
            fgets(str[i], 80, stdin);
        }
    
        letter(n, str);
    }
    

2 个答案:

答案 0 :(得分:3)

第一个问题fgets()跳过一次迭代是因为在第一次输入后按 ENTER 键的剩余newline。< / p>

从换行符清除输入缓冲区的一个简单例子是

 scanf("%d%*c", &n);  //eat the newline.

对于第二个问题,在函数内部,你有三个嵌套循环没有意义。你没有在任何地方使用n的值。这没有任何意义,导致垃圾输出。

例如,

  • 您将索引j限制为25,但实际上您接受它的时间与79一样长。
  • 您有循环变量k,但未正确使用。

合理的循环条件是,

  • i最多n-1i<n)作为第一个索引。
  • j最多终止null,(arr[i][j]
  • k,从a开始,直到z,(int k = 'a'; k < ('z' + 1 ) ; k++)[注意:这只计算小写字母]

答案 1 :(得分:1)

  

当我输入行数时,程序只要求用户输入的数字少于输入的数字

我猜你在执行scanf时,它不会在数字末尾吞下新行。因此,第一个fgets获取该行的(空)剩余部分

  

字母数不正常。看起来好像是随机的。

在您的循环中,i应从0计算到n - 1(即str中的行数)和j应从0到0 strlen(str[i]) - 1或更高,j应从0计算到str[i][j] == '\0',因为strlen需要遍历所有字符本身,因此效率低下。

然后,您的内部循环应该看str[i][j]azA之间是否Z,如果是,则减去'a' }或'A'来自它,并将其用作ltrcnt

的索引

通过&#34;内循环&#34;,我的意思是j的那个,就我所见,你不需要for (k ...循环。

如果您坚持使用k循环,请务必在每次启动之前将c重置为'a'

第二个问题的最小修正是:

for(int i = 0; i < n; i++){
    for(int j = 0; str[i][j] != '\0'; j++){
        c = 'a'; // << was missing
        for(int k = 0; k < 26; k++){
            if(str[i][j] == c){
                ltrcnt[k]++;
            }
            c++;
        }
    }
}

消除最内层循环的更好的修复是

for(int i = 0; i < n; i++){
    for(int j = 0; str[i][j] != '\0'; j++){
        if (str[i][j] >= 'a' && str[i][j] <= 'z')
        {
            ltrcnt[str[i][j] - 'a']++;
        }
    }
}