簡體   English   中英

將字符串的字母分配到數組中

[英]Assigning the letters of a string into an array

我正在嘗試創建一個C代碼,該代碼從用戶那里獲取最大長度為 10 的輸入字符串,並將每個字母分配給大小為 10 的數組的不同元素。但是,我無法理解我的結果。 我的代碼:

char word1[9];
int i;

printf("Enter your first word: \n");
scanf("%s", &word1);
printf("your word is %s \n",word1);

for(i = 0; i < 10; i++)
    printf("%d ", word1[i]);
    
system("pause");

當我輸入單詞“hello”時, for循環顯示數組word1的前 6 個元素中的每一個都被分配了與字母 h、e、l、l、o 對應的ASCII數字。 理想情況下,最后 4 個元素應該為 0,但它們不是。 output 是 [104 101 108 108 111 0 0 0 1 0]。 那個1是從哪里來的? 同樣,如果我輸入“hi”,則 output 為 [104 105 0 24 -3 127 0 0 1 0]。 104 和 105 之后的這些隨機數是什么,為什么它們不是 0?

對於上下文,我正在嘗試構建一個簡單的代碼來檢查兩個輸入單詞是否是字謎。 我的想法是生成 2 個 ASCII 等效的 arrays 然后我可以按升序排序,以便比較每個相應的元素。

附加問題:為什么當我在 for 循環中從 i<10 增加 10 時,output 會顯示超過 10 個值? 由於數組有 10 個元素,它不應該總是只顯示 10 個輸出嗎?

對不起,如果這是微不足道的,我對C很陌生。

由於這一行,您得到了 ASCII 數字:

printf("%d ", word1[i]);

您需要將%d替換為%c - 這樣問題就解決了。 不過,還是有問題。 當要求用戶輸入時, scanf()必須用於接受有限數量的字符:

char word[11]; // to get 10 chars + '\0' (null-terminator)
scanf("%10s", word);

您無需在scanf()中引入與號並在%s之間顯式使用 (max length - 1) 。

最后,迭代直到數組的整個長度是一個非常糟糕的主意。 考慮迭代直到檢測到空終止符。 簡而言之,替換:

for(i = 0; i < 10; i++)

while (word[i] != '\0')

你最大的問題是:

  • 錯誤使用scanf()word1調用未定義行為之前添加& 由於數組/指針轉換, word1已經是一個指針。 請參閱: C11 標准 - 6.3.2.1 其他操作數 - 左值、arrays 和 function 指示符 (p3)
  • 您未能使用field-width修飾符來保護您的數組邊界,從而允許用戶通過輸入超出數組可以容納的字符數來利用您的代碼。 scanf()"%s"轉換說明符一起使用,而不使用字段寬度修飾符來將輸入限制為數組可以容納的字符數並不比使用gets()更安全。 請參閱:為什么 gets() 如此危險,永遠不應該使用!
  • 如果您的數組包含少於9字符(應該是11來保存10字符的字符串),則使用for循環在數組末尾循環。 word1 (如果正確讀取)是一個以nul 結尾的字符串。 您只需循環直到找到字符串的結尾(例如'\0'字符,其 ASCII 值只是普通的0 )。 您不會遍歷數組可以保存的最大字符數——它們可能保存未設置的值。

要糾正上述問題以及更多問題,您可以執行以下操作:

#include <stdio.h>

#define MAXCHR 10               /* if you need a constant, #define one (or more) */

int main (void) {
    
    char word1[MAXCHR + 1];     /* to treat chars as a string, you need +1 for \0 */
    int i;
    
    fputs ("Enter your first word: ", stdout);      /* no conversion, printf not needed */
    
    if (scanf ("%10s", word1) != 1) {               /* validate EVERY input, protect */
        puts ("EOF encountered on read of word1");  /* array bounds with field-width */
        return 0;
    }
    printf ("your word is: %s\n", word1);           /* output word1 */
    
    for (i = 0; word1[i]; i++)                      /* word1 is a string, loop to end */
        printf ("%c ", word1[i]);
    putchar ('\n');                                 /* tidy up with newline */
    
#if defined (_WIN32) || defined (_WIN64)
    system("pause");                                /* non-portable, only for windows */
#endif
}

注意:如果 output 字符串包含轉換,則僅 output 需要printf() ,否則,如果需要行尾控制,則puts()fputs()都可以)

示例使用/輸出

字符數內的基本輸入:

$ ./bin/word1
Enter your first word: bananas
your word is: bananas
b a n a n a s

准確輸入允許的字符數:

$ ./bin/word1
Enter your first word: 1234567890
your word is: 1234567890
1 2 3 4 5 6 7 8 9 0

輸入兩倍於數組可以作為字符串保存的字符:

$ ./bin/word1
Enter your first word: 12345678901234567890
your word is: 1234567890
1 2 3 4 5 6 7 8 9 0

注意:無論您嘗試輸入多少個字符,都只會存儲10加上 nul 終止字符。請注意,任何未讀取的字符都保留在stdin中未讀 - 只是等着下次輸入時咬你。那這就是為什么應該使用fgets()或 POSIX getline()進行輸入,以便消耗整個輸入行。無論您使用哪個輸入 function,您都無法正確使用它,除非您檢查返回以確定輸入是否成功或失敗的。)

如果您還有其他問題,請仔細查看並告訴我。

原因是,arrays 不是由 C 中的默認值(如 0)啟動的,所以當您輸入一個不覆蓋整個數組的字符串時,Z65E8800B5C6800AAD896F888B2A62AFC 的一些垃圾值元素沒有任何默認值memory。 您可以像這樣啟動單詞數組:

for(i = 0; i < 10; i++)
    word1[i] = 0;

PS: char word1[9]; 創建 9 個單元格而不是 10 個。另外請注意,您應該為\0字符考慮另一個單元格,這將指示字符串已結束。 所以總共需要 11 個單元格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM