我需要我的程序输入用户想要输入的句子数,然后输入这些句子。然后,通过传递函数letter()
,我希望它计算在字符串中看到每个字母的次数。但是,我遇到了以下问题:
此外,我想知道我是否正确使用我的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);
}
答案 0 :(得分:3)
第一个问题,fgets()
跳过一次迭代是因为在第一次输入后按 ENTER 键的剩余newline
。< / p>
从换行符清除输入缓冲区的一个简单例子是
scanf("%d%*c", &n); //eat the newline.
对于第二个问题,在函数内部,你有三个嵌套循环没有意义。你没有在任何地方使用n
的值。这没有任何意义,导致垃圾输出。
例如,
j
限制为25
,但实际上您接受它的时间与79
一样长。 k
,但未正确使用。合理的循环条件是,
i
最多n-1
(i<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]
和a
或z
和A
之间是否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']++;
}
}
}