我目前正在上 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.");
}
}
然而,經過測驗,我從它的結果中得出了一些案例。
案例一:無任何輸入列印輸入("Sorry, the word must contain only English letters. ")
情況 2:具有 1 個非字母字符的輸入會列印兩次“抱歉”訊息。此外,帶有 2 個非字母字符的輸入會列印三次“抱歉”訊息。這意味著案例 1 為真,因為沒有輸入會列印一次訊息,然后添加非字母字符會列印兩次訊息。
情況 3:輸入少于 10 個字符(全部為字母)也會列印出抱歉訊息。
案例4:輸入超過9個字符(全是字母)不列印出sorry資訊,滿足我的要求。
為什么會出現這些情況?如果在回圈用戶輸入后發現是一個非字母字符,我只需要列印一次訊息!
uj5u.com熱心網友回復:
正如@unwind 所指出的,OPfor()回圈的條件不正確。
值得信賴,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;
}
uj5u.com熱心網友回復:
C 中的字串以 null 結尾,這意味著它們包含一個額外的位元組 '\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
通過使用固定大小的緩沖區,如果字串沒有占用所有空間,則包含的字串后面會有垃圾。
您有 2 個條件可以停止迭代:
- 陣列結束,防止陣列溢位
- 字串結尾,以防止錯誤解釋陣列中比字串結尾更遠的位元組
錯誤訊息可能會被列印多次,因為即使在發生錯誤后您仍會繼續檢查,因此您必須中斷回圈。
下面的代碼不符合提到的問題
#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() 是一個宏,一個回傳最小引數的三元運算式,這里沒什么復雜的。
但請注意,當您輸入單詞時,您按 <Enter>,因此您的字串包含“轉到下一行”字符(字符 '\n',ascii 表中的 n°10,正如 @Shawn 在評論中提到的那樣),所以你必須在它之前停下來:這就是我使用strlen(player) - 1, 字串以“\n\0”結尾的原因,而 strlen() 回傳 '\0' 之前的位元組數(包括 '\n')。
我已經在最后轉儲了字串,您可以在那里修改 end-index 以查看發送到 isalpha() 的內容,將 maxIndex 替換為 BUFFER_SIZE。
uj5u.com熱心網友回復:
這個:
for (int i = 0; i < player1[i]; i ) {
從 0 回圈直到(但不包括)第 i 個字符的代碼點值,i每次回圈時更新。它很可能會訪問陣列邊界之外,這是未定義的行為。
它應該尋找終止符(或換行,但讓我們保持簡單):
for (size_t i = 0; player1[i] != '\0'; i) {
uj5u.com熱心網友回復:
使用函式 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.");
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/530482.html
標籤:C
上一篇:寫入用戶指定的檔案
