如何在C语言中使用“.”、“?”和“!”来计算句子的数量?

3

我对编程还比较新手。我的 “CountSentences”函数有些问题。我将字符串与“。”、“?”和“!”进行比较,以计算句子数。但无论我在字符串中有多少个标点符号,它只会将一个加到句子计数器中。我是否使用了strcmp不当来获取所需的结果?是否有其他方法可以解决这个问题?

#include<cs50.h>
#include<ctype.h>
#include<string.h>
#include<math.h>
//计算字符数的函数 int count_letters(string s) { int numberofLetters = 0; // 计数器
//循环直至字符串长度 for(int i = 0, n = strlen(s); i < n; i++) { //如果字符是字母数字 if(isalnum(s[i]) != 0) { numberofLetters++; //增加计数器数量 }; }; return numberofLetters; //返回新计数器数量 };
//计算单词数的函数 int count_Words(string w) { int numberofWords = 0;//声明单词计数器 int i = 0; // 字符串中字符的计数器
if(w == NULL) // 如果为空 { return numberofWords; // 返回单词数为0的计数器 };
bool spaces = true; //用于表示空格的真值
//如果字符不是空字符 while(w[i] != '\0') {
if(isblank(w[i]) != 0) //如果字符为空格 { spaces = true; //是空格 } else if(spaces) //如果没有空格并且有字母,则添加到单词中 { numberofWords++; // 增加单词计数器 spaces = false; }; i++;// 增加字符串w中的字符计数器
};
return numberofWords; //返回总单词计数器 };
//函数来计算句子数量 int count_Sentences(string l) { //变量统计标点符号 int countMarks = 0;
//循环迭代使用字符串中的字符数 for(int i = 0, n = strlen(l); i < n; i++) { //检查是否为 ? , . , or ! if(strcmp(&l[i], "!") == 0 || strcmp(&l[i], ".") == 0 || strcmp(l, "?") == 0) { countMarks++;// 统计句子数 };
}; // 返回总标点符号数 return countMarks; };
int main (void) { string text = get_string ("Text: ");
//检查函数错误 printf("Number of letters: %i\n", count_letters(text)); printf("Number of words: %i\n", count_Words(text)); printf("Number of sentences: %i\n", count_Sentences(text));
//Coleman Liau指数 int grade = round(0.0588 * (100 * (count_letters(text)) / (count_Words(text))) - 0.296 * (100 *(count_Sentences(text)) / (count_Words(text))) - 15.8 );
if(grade <= 1) { printf("Before Grade 1\n"); } else if(grade < 16) { printf("Grade %i\n", grade); } else { printf("Grade 16+\n"); }; };

6
你的代码正在将输入的其余部分与一个只有一个字符的字符串进行比较。我建议使用if(l[i] == '!')等方式。另外:不建议使用变量名l(字母L),因为它很容易与数字1混淆,这会使代码难以阅读并容易出错。 - Weather Vane
1
你可能会对在 ctype.h 中声明的函数族 ispunct()isspace()isalpha() 等感兴趣。 - Weather Vane
关于: }; }; 不要在闭合大括号 } 后面加上分号 ; - user3629249
发表的代码缺少语句:#include <stdio.h>用于printf()等函数。 - user3629249
1
关于:if(strcmp(&l[i], "!") == 0 || strcmp(&l[i], ".") == 0 || strcmp(l, "?") == 0) 这段代码是无法工作的,因为 l[] 中的单个字符并不是字符串。建议修改为:if( l[i] == '!' || l[i] == '.' || i[i] == '?' ) 请注意这里使用了单引号而非双引号来比较字符而非字符串,并且适当添加了水平空格以提高可读性。 - user3629249
显示剩余2条评论
2个回答

2
    if(strcmp(&l[i], "!") == 0  || strcmp(&l[i], ".") == 0  ||  strcmp(l, "?") == 0)
strcmp比较两个字符串。在C语言中,我们的“字符串”本质上是“从此指针指向的位置开始的char大小的数据,并持续到空终止符”。cs50库不会改变这一点,也不会给你一个真正的字符串类型;它只提供了一个typedef和一些用于读取输入的帮助函数。(它也很遗憾地不能给你一个真正的文本字符类型,char也不是;但这超出了本答案的范围。) &l[i]是指向字符串l中间的一个指针,从偏移量i开始。当strcmp使用该指针时,它将把“字符串”视为“从该字符到原始字符串结尾的所有内容”,因为那里是空终止符所在的位置。特别地,它通常不会将单个l[i]字符视为单独的字符串,因为下一个字符通常不是空终止符。因此,

无论我在字符串中有多少标点符号,它都只会将句子计数器加1。

实际上,它之所以只加1,是因为你的字符串以其中一个标点符号结尾。
要比较单个字符,请不要使用strcmp。它不适用于此目的。一个char是一个单独的实体,因此可以使用==进行比较。你只需要在比较的两侧都有适当的内容即可。
请记住,在C语言中,单引号用于表示字符字面量,并且索引到char数组(等效地,“索引”到char指针,执行等效的指针算术运算)将给出一个char。因此:
if (l[i] == '!' || l[i] == '.' || l[i] == '?')

1
除此之外:“C中单引号用于字符字面量” --> 在C语言中,'!'是一个“字符常量”。C语言有两种定义的“字面量”:字符串和复合字面量,但没有“字符字面量”。这两种字面量都可以取地址,而常量则不行。在C语言中,'!'的类型为int - chux - Reinstate Monica
strchr 更加适合。 - klutt

2
您需要检查一个字符l[i]是否是.?!中的任何一个。为此,您可以测试它是否等于这些字符常量中的任何一个,即l[i] == '!' || l[i] == '.' || l[i] == '?'
或者,您可以使用函数strchr来在给定字符串中查找给定字符,并返回指向该字符的指针,如果未找到该字符,则返回空指针。空指针将被视为假值,在if语句中非空指针为真值。因此,我们可以在字符串".?!"中查找l[i]
if (strchr(".?!", l[i])) {
    ...
}

1
l[i] != 0 时,这个程序可以正常工作。由于之前的 n = strlen(l); i < n;strchr(".?!", 0) 不是 NULL,所以 l[i] 不可能为零。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接