char 对象只能包含单个字符值。要存储字符串,需要使用char1的数组:
#define MAX_NAME_LENGTH 20 // or whatever
...
char name[MAX_NAME_LENGTH+1]; // +1 for string terminator
请记住,在 C 中,字符串 是包含 0 值终止符的字符值序列 - 例如,字符串 "hello" 表示为字符序列 {'h', 'e', 'l', 'l', 'o', 0 }。因此,您的数组需要足够大以处理您期望的最长字符串加上 0 终止符的额外元素。如果您希望最大的字符串长度为 20 个字符,那么该数组需要能够容纳 至少 21 个字符。
由于各种历史原因,现在不值得一提,如果您尝试向数组中写入的字符数量超过了它可以容纳的大小,C I/O 例程将无法保护您。如果name 的大小可以容纳 20 个字符加上 0 终止符,那么您将其读取为
scanf( "%s", name );
如果有人输入了 200 个字符,那么 180 个字符将紧跟name 数组写入内存,可能会导致各种混乱。缓冲区溢出是一种流行的恶意软件利用,因此它也是一个安全问题。
为了防止这种情况,您需要指定要读取的最大字符数。不幸的是,scanf 要求您将其硬编码为转换说明符的一部分,而不是像printf 那样将其作为单独的参数提供。你不能只使用宏像
scanf( "%MAX_NAME_LENs", name );
您要么必须将其指定为数字文字:
scanf( "%20s", name );
或使用一些预处理器技巧来扩展宏并将其与格式字符串连接:
#define EXPAND(x) #x
#define STR(x) EXPAND(x)
...
scanf( "%" STR(MAX_NAME_LEN) "s", name );
在预处理之后,扩展为
scanf( "%" "20" "s", name );
评估为
scanf( "%20s", name );
或者,您可以走简单的路线并使用fgets:
fgets( name, sizeof name, stdin );
这是我推荐的。
- 或
wchar_t 用于“宽”字符串,您现在无需担心。