我目前正在上C语言的初级课程,有一个练习要求我的程序检查用户输入是否包含非字母。我想使用函数isalpha()
来检查用户输入,如果它包含非字母,程序应该要求用户输入另一个输入。
下面是我目前的代码:
#include <stdio.h>
#include <ctype.h>
#define MAX 13
int main() {
char player1[MAX];
int k = 0;
// Ask player 1 to type a word.
printf("Player 1, enter a word of no more than 12 letters: \n");
fgets(player1, MAX, stdin);
// // Loop over the word entered by player1
for (int i = 0; i < player1[i]; i++) {
// if any chars looped through is not an alphabet, print message.
if (isalpha((unsigned char)player1[i]) == 0) {
printf("Sorry, the word must contain only English letters.");
}
}
然而,在测试它之后,我从它的结果中推导出了几个案例。
情况1:在没有任何输入的情况下输入将打印("Sorry, the word must contain only English letters. ")
情况2:输入1个非字母字符会打印两次'sorry'消息。此外,输入2个非字母字符会打印三次'sorry'消息。这意味着情况1为真,因为没有输入会打印一次消息,那么添加非字母字符会打印两次消息。
情况3:输入少于10个字符(全部为字母)也会打印出sorry消息。
案例4:输入9个以上的字符(全部为字母)不会打印出sorry消息,这满足了我的要求。
为什么会出现这种情况呢?我只要求消息在循环用户输入后打印一次,如果发现有非字母字符!
4条答案
按热度按时间ao218c7q1#
正如@unwind所指出的,OP
for()
循环的条件不正确。最好信任
isalpha()
,但您的代码不必处理每个字符。另一个标准库函数strspn()
,当根据您的需要提供时,可以为您执行循环工作。tjrkku2a2#
C中的字符串是以空值结尾的,这意味着它们包含一个额外的字节'\0'来标记字符串的结尾(ASCII表中的字符0),因此在大小为13的char数组中只能存储12个字符。
如果数组包含一个小于12个字符的字符串,因为循环遍历整个数组,所以会遇到空终止字节,它会失败isalpha():它会检查字符是否在['A','Z']或['a','z']范围内。字符对于您的计算机来说只是整数,所以isalpha()会检查接收到的值是否在[65,90]或[97,122]范围内,而0不是。更准确地说,整数的概念对于您的计算机来说没有意义,这只是我们解释信息的方式。它只是你电脑的一堆比特。
参见ascii表:https://www.rapidtables.com/code/text/ascii-table.html
通过使用固定大小的缓冲区,如果字符串没有占用所有空间,则在包含的字符串之后会出现垃圾。
有两个条件可以停止迭代:
错误消息可能会打印多次,因为即使在发生错误后仍要继续检查,所以必须中断循环。
以下代码不符合上述问题
MIN()是一个宏,一个三元表达式,它返回最小的参数,这里没有什么真正复杂的。
但请注意,当你输入这个词时,你按下,所以你的字符串包含一个“转到下一行”字符(字符'\n',ASCII表中的n°10,正如@Shawn在注解中提到的),所以你必须在它之前停下来:这就是我使用
strlen(player) - 1
的原因,string以“\n\0”结尾,strlen()返回'\0'之前的字节数(包括'\n')。我已经在字符串的末尾做了一个转储,你可以在那里修改end-index来查看发送给isalpha()的内容,用BUFFER_SIZE替换maxIndex。
bxgwgixi3#
这一点:
从0开始循环,直到(但不包括)第i个字符的码位值,每次循环时更新
i
。它很可能会访问数组边界之外的内容,这是未定义的行为。它应该寻找终止符(或换行符,但让我们保持简单):
xtfmy6hx4#
使用函数isalpha()检查用户输入,以及是否包含非字母表
只需一次读取一个字符。不需要最大值。