C语言 isalpha()检测没有输入的非字母字符

sulc1iza  于 2022-12-03  发布在  其他
关注(0)|答案(4)|浏览(201)

我目前正在上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消息,这满足了我的要求。
为什么会出现这种情况呢?我只要求消息在循环用户输入后打印一次,如果发现有非字母字符!

ao218c7q

ao218c7q1#

正如@unwind所指出的,OP for()循环的条件不正确。
最好信任isalpha(),但您的代码不必处理每个字符。另一个标准库函数strspn(),当根据您的需要提供时,可以为您执行循环工作。

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

#define MAX 12

int main() {
    char player1[ MAX + 1 + 1 ]; // buffer size for fgets() 12 + '\n' + '\0'
    char *permissible =
        "abcdefghijklmnopqrstuvwxyz"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    // Ask player 1 to type a word.
    printf("Player 1, enter a word of no more than %d letters: \n", MAX);
    fgets(player1, sizeof player1, stdin);

    if( player1[ strspn( player1, permissible ) ] != '\n' )
        printf("Sorry, the word must contain only English letters.");

    return 0;
}
tjrkku2a

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
通过使用固定大小的缓冲区,如果字符串没有占用所有空间,则在包含的字符串之后会出现垃圾。
有两个条件可以停止迭代:

  • 数组结尾,以防止数组溢出
  • 字符串结尾,以防止错误解释数组中比字符串结尾更远的字节

错误消息可能会打印多次,因为即使在发生错误后仍要继续检查,所以必须中断循环。
以下代码不符合上述问题

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

#define BUFFER_SIZE 13

#define MIN(a, b) (a < b ? a : b)

int main(void)
{
    char player1[BUFFER_SIZE];
    int maxIndex;
    int i;

    /* Ask player 1 to type a word */
    printf("Player 1, enter a word of no more than 12 letters: \n");
    fgets(player1, BUFFER_SIZE, stdin);

    /*
     * Max index for iteration, if string is lesser than 12 characters
     * (excluding null-terminating byte '\0') stop on string end, otherwise
     * loop over whole array
     */
    maxIndex = MIN(strlen(player1) - 1, BUFFER_SIZE);

    for (i = 0; i < maxIndex; i++) {
        /* Print error if non-letters were entered */
        if (isalpha(player1[i]) == 0) {
            printf("Sorry, the word must contain only English letters.");
            /* Error occured, no need to check further */
            break;
        }
    }

    /*
    for (i = 0; i < maxIndex; i++)
        printf("%d ", (int) player1[i]);
    printf("\n%s\n", player1);*/

    return 0;
}

MIN()是一个宏,一个三元表达式,它返回最小的参数,这里没有什么真正复杂的。
但请注意,当你输入这个词时,你按下,所以你的字符串包含一个“转到下一行”字符(字符'\n',ASCII表中的n°10,正如@Shawn在注解中提到的),所以你必须在它之前停下来:这就是我使用strlen(player) - 1的原因,string以“\n\0”结尾,strlen()返回'\0'之前的字节数(包括'\n')。
我已经在字符串的末尾做了一个转储,你可以在那里修改end-index来查看发送给isalpha()的内容,用BUFFER_SIZE替换maxIndex。

bxgwgixi

bxgwgixi3#

这一点:

for (int i = 0; i < player1[i]; i++) {

从0开始循环,直到(但不包括)第i个字符的码位值,每次循环时更新i。它很可能会访问数组边界之外的内容,这是未定义的行为。
它应该寻找终止符(或换行符,但让我们保持简单):

for (size_t i = 0; player1[i] != '\0'; ++i) {
xtfmy6hx

xtfmy6hx4#

使用函数isalpha()检查用户输入,以及是否包含非字母表
只需一次读取一个字符。不需要最大值。

#include <ctype.h>
#include <stdio.h>

int main(void) {
  int ch;
  int all_alpha = 1;

  printf("Player 1, enter a line\n");

  while ((ch = getchar()) != '\n' && ch != EOF) {
    if (!isalpha(ch)  {
      all_alpha = 0;
    }
  }

  if (!all_alpha) {
    printf("Sorry, the line must contain only letters.");
  }
}

相关问题