[英]Scanf a char in C with an example
我当时在Cplusplus上教程
有这个例子:
/* scanf example */
#include <stdio.h>
int main ()
{
char str [80];
int i;
printf ("Enter your family name: ");
scanf ("%79s",str);
printf ("Enter your age: ");
scanf ("%d",&i);
printf ("Mr. %s , %d years old.\n",str,i);
printf ("Enter a hexadecimal number: ");
scanf ("%x",&i);
printf ("You have entered %#x (%d).\n",i,i);
return 0;
}
我在我的Macbook上试过它,当我做“做例子”时我得到了这个错误;
example.c: In function ‘main’:
example.c:25: warning: format ‘%79s’ expects type ‘char *’, but argument 2 has type ‘char (*)[80]’
当我做“valgrind ./example”时,我得到了这个消息;
==1326== Memcheck, a memory error detector
==1326== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==1326== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==1326== Command: ./example
==1326==
--1326-- ./example:
--1326-- dSYM directory is missing; consider using --dsymutil=yes
Enter your family name: Park
Enter your age: 20
Mr. Park, 20 years old.
==1326==
==1326== HEAP SUMMARY:
==1326== in use at exit: 8,280 bytes in 3 blocks
==1326== total heap usage: 3 allocs, 0 frees, 8,280 bytes allocated
==1326==
==1326== LEAK SUMMARY:
==1326== definitely lost: 0 bytes in 0 blocks
==1326== indirectly lost: 0 bytes in 0 blocks
==1326== possibly lost: 0 bytes in 0 blocks
==1326== still reachable: 8,280 bytes in 3 blocks
==1326== suppressed: 0 bytes in 0 blocks
==1326== Rerun with --leak-check=full to see details of leaked memory
==1326==
==1326== For counts of detected and suppressed errors, rerun with: -v
==1326== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
问题1. “ make example”给出了一个错误,但是程序执行了应做的事情。 那么这里的错误是什么?
问题2我做了很少的研究,并且我了解到你不能在C中分配一个char,因为char不可变。 这就是char与int或float或double的不同之处。 如果是这样,我怎么能在这里指定str?
问题3什么是Char数组? 我读了几篇文章,但是在这里我不明白它是如何工作的!!!
char str [80];
表示str最多可以占用80个字节,对不对? 那是什么
scanf ("%79s",str);
?
非常感谢您的帮助,并祝您2014年愉快! :)
这个:
scanf ("%79s", str);
是指“读一个字符串( s
),但不使用的空间超过79个字符从指针开始我已经给你”之类的。 这是一种在读取字符串时防止缓冲区溢出的方法。 它使用79
而不是80
来为字符串终止符留出空间。
文件说:
字符串输入转换存储一个终止的空字节(
'\\0'
)来标记输入的结尾。 最大字段宽度不包括此终止符。
我当时在Cplusplus上教程
请不要 该网站充满了错误,不正确和/或误导性的例子。 帮自己一个忙,然后选择另一个站点。
我在我的Macbook上试过它,当我做“做例子”时我得到了这个错误;
可能是您拼错了源代码,并且您写了&str
而不是str
(我认为这是一个坏习惯:抛出address-of运算符时不考虑遇到scanf()
)。 这导致指向数组的指针,而转换说明符期望指向字符的指针。
“make example”会出错,但程序会执行它应该执行的操作。 那么这里的错误是什么?
该计划没有做它应该做的事情。 而是,它调用未定义的行为,并假装正常工作。
我做了很少的研究,但我知道您不能在C中分配字符,因为字符是不可变的
错误。
什么是字符数组?
您的示例中的char数组是str
。 就是这样:80个字符阵列。 不幸的是,数组在C中有一些奇怪的属性,比如在传递给函数时隐式地衰减成指针。 这就是scanf()
希望您传递指针而不是数组参数的原因:编写时
scanf("format string", str);
那么实际传递的是指向str
第一个元素的指针(又名&str[0]
)。
此外,如果您接受另一条好建议: 不要使用scanf()
。 这很危险,其用法违反直觉,并且总体上没有任何好处。 为了接受用户输入,请考虑改用fgets()
。
错误
example.c:25: warning: format ‘%79s’ expects type ‘char *’, but argument 2 has type ‘char (*)[80]’
只有你写过类似的东西才有意义
scanf ("%79s", &str); // wrong
代替
scanf ("%79s",str); // right
您发布的代码是您实际编译的内容吗?
至于你的具体问题:
问题1.“制作示例”给出了错误,但程序执行了它应该做的事情。 那么这里的错误是什么?
首先,有一点背景知识:除非它是sizeof
或一元&
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则将转换类型为“ T
N元素数组”的表达式(“衰减”)类型为“指向T
指针”的表达式,该表达式的值将是数组第一个元素的地址。
当你写作
scanf("%79s", str);
表达式str
具有类型“80-element char
of char
”; 因为str
不是sizeof
或一元&
运算符的操作数,所以它被转换为“指向char
指针”或char *
类型的表达式,并且它的值是数组中第一个元素的地址。
如果你写过
scanf("%79s", &str);
表达式str
是一元&
运算符的操作数,因此不会发生转换; 相反,表达式&str
的类型是“指向80个元素的 char
数组 ”,或者是char (*)[80]
(看起来很熟悉?),表达式的值是数组的地址。
现在,恰好相反,数组的地址和数组的第一个元素的地址是相同的; 表达式str
和&str
将产生相同的值 ,但是两个表达式的类型不同。
因此,假设你写scanf("%79s, &str)
代码将仍然是‘工作’(该值&str
相同str
),但由于该类型是不是想让scanf
预计为%s
转换符,编译器会发出警告。
问题2我做了很少的研究,并且我了解到你不能在C中分配一个char,因为char不可变。 这就是char与int或float或double的不同之处。 如果是这样,我怎么能在这里指定str?
要么你误解了,要么你正在读一个非常糟糕的参考。 C中的字符串不是不可变的。 尝试修改字符串文字的内容会调用未定义的行为(某些平台会引发异常,有些平台不会),但这与说它们不可改变(就像Java字符串不可改变一样)不同。
C中的字符串存储为char
数组。 您可以使用strcpy
库函数或直接修改数组元素来更新字符串内容。 例如:
char str[80];
...
strcpy( str, "a string" );
将字符串文字"a string"
的内容复制到str
。 你当然可以更新这个字符串,例如
str[0] = 'A'; // str now contains "A string"
或者向它添加另一个字符串:
strcat( str, " with more stuff" ); // str now contains "A string with more stuff"
像"a string"
这样的字符串文字存储为char
数组,以便在程序启动时保存它们的存储,直到程序退出,并且它们在整个程序中可见。 尝试修改字符串文字的内容会调用未定义的行为; 它可能工作,它可能不会,编译器可能会抛出错误,您可能会在运行时收到错误。 所以你不想做类似的事情
char *p = "This is a test";
strcpy( p, "This is another test" );
问题3什么是Char数组? 我读了几篇文章,但是在这里我不明白它是如何工作的!!!表示str最多可以占用80个字节,对不对?char str [80];
它需要80个char
; char
映射到本地8位字节通常是正确的,但是也有例外(大多数情况是非常老的体系结构或奇数嵌入式系统)。
那是什么?scanf ("%79s",str);
在该调用中,所有scanf
接收的是指向目标缓冲区的第一个元素的指针; 它不知道目标缓冲区实际有多大。 如果你写
scanf("%s", str);
并且用户输入的字符串长度超过80个字符, scanf
会在str
结束后立即将这些多余的字符愉快地存储到内存中,从而可能破坏重要内容并导致崩溃(或更糟糕的是,恶意软件利用)。 %79s
指示scanf
仅从输入流中读取最多79个字符。 为什么用79代替80? 您需要保留一个可用于0终止符的元素(在C中, 字符串是由0值字节终止的字符序列)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.