首页 > 解决方案 > 将字符串的字母分配到数组中

问题描述

我正在尝试创建一个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循环显示数组的前 6 个元素中的每一个word1都被分配ASCII了字母 h、e、l、l、o 的等效数字。理想情况下,最后 4 个元素应该为 0,但它们不是。输出为 [104 101 108 108 111 0 0 0 1 0]。那个1是从哪里来的?同样,如果我输入“hi”,则输出为 [104 105 0 24 -3 127 0 0 1 0]。104 和 105 之后的这些随机数是什么,为什么它们不是 0?

对于上下文,我正在尝试构建一个简单的代码来检查两个输入单词是否是字谜。我的想法是生成 2 个 ASCII 等效数组,然后我可以按升序排序,以便比较每个对应的元素。

附加问题:为什么当我在 for 循环中从 i<10 增加 10 时,输出会显示超过 10 个值?由于数组有 10 个元素,它不应该总是只显示 10 个输出吗?

对不起,如果这是微不足道的,我对C.

标签: arrayscascii

解决方案


你最大的问题是:

  • 在调用未定义的行为之前不正确地使用scanf()添加。由于数组/指针转换,它已经是一个指针。请参阅:C11 标准 - 6.3.2.1 其他操作数 - 左值、数组和函数指示符 (p3)&word1word1
  • 您未能使用field-width修饰符来保护您的数组边界,从而允许用户通过输入超出数组可以容纳的字符数来利用您的代码。使用没有字段宽度scanf()修饰符的"%s"转换说明符将输入限制为数组可以容纳的字符数并不比使用. 请参阅:为什么 gets() 如此危险,永远不应该使用!gets()
  • for如果您的数组包含少于一个9字符(应该是11保存一个10字符串。)word1(如果正确读取),则使用循环超出数组的末尾,是一个以空结尾的字符串。您只需循环直到找到字符串结尾(例如,'\0'其 ASCII 值只是 plain-old 的字符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
}

注意: 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未读状态 - 只是等着下次输入时咬您。这就是为什么input 应该与fgets()or POSIX一起使用getline(),以便消耗整行输入。无论您使用哪个输入功能,您都无法正确使用它,除非您检查返回以确定输入是成功还是失败。)

如果您还有其他问题,请仔细查看并告诉我。


推荐阅读