C语言 将字符串中的字母赋值到数组中



我试图创建一个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,但事实并非如此。输出为[104 101 108 108 111 0 0 01 0]。这个1是怎么来的?同样,如果我输入"hi"输出结果为[104 105 0 24 -3 127 0 0 10]。104和105后面的这些随机数是什么?为什么它们不是0?

对于上下文,我试图建立一个简单的代码,将检查如果两个输入词是字谜。我的想法过程是,将产生2个ASCII等效数组,然后我可以按升序排序,以便我可以比较每个相应的元素。

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

对不起,如果这是微不足道的,我是非常新的C

您将获得ASCII数字,因为这一行:

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

你需要用%c替换%d-所以问题解决了。不过,还是有一个问题。当请求用户输入时,必须使用scanf()来接受有限数量的字符:

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

您不需要在scanf()中引入&符号,并且在%s之间显式地使用(max length - 1)。

最后,迭代到数组的整个长度是一个非常糟糕的主意。考虑迭代直到检测到零终止符。总之,替换为:

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

while (word[i] != '')

你最大的问题是:

  • 错误地使用scanf()word1调用未定义行为之前添加&。由于数组/指针转换,word1已经是一个指针。参见:C11标准- 6.3.2.1其他操作数-左值、数组和函数指示符(p3)
  • 您没有使用字段宽度修饰符来保护您的数组边界,允许用户通过输入超过您的数组所能容纳的字符来利用您的代码。使用scanf()"%s"转换说明符,不带字段宽度修饰符,将输入限制为数组可以容纳的字符数,这并不比使用gets()更安全。看看:为什么gets()如此危险,它永远不应该被使用!
  • 如果数组包含少于9字符(应该是11以保存10字符串),则使用for循环超出数组的末尾。word1(如果正确读取)是一个以空结束的字符串。您只需循环,直到找到字符串的结束(例如,''字符,其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  */
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: %sn", 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加上终止null的字符。请注意,任何未读的字符都保留在stdin中未读—只是等待在下一次输入时咬您。这就是为什么应该使用fgets()或POSIXgetline()来获取输入,以便消耗整行输入。无论使用哪个输入函数,除非检查返回值,否则无法正确使用它。用于确定输入是否成功。)

请过目一遍,如果还有问题请告诉我。

原因是,数组在C中不是由默认值(如0)初始化的,因此当您输入一个不覆盖整个数组的字符串时,其余元素没有任何默认值,并且它们从内存中获得一些垃圾值。您可以像这样初始化单词数组:

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

PS:char word1[9];创建9个单元格而不是10个。还要注意,您应该考虑为字符添加另一个单元格,这将表示字符串已经结束。所以总共需要11个单元格。

相关内容

  • 没有找到相关文章

最新更新