我正在阅读一些C ++教程并发现有时候字符串被初始化('初始化'可能不是正确的术语),有时候不是。
为什么以及何时?
我正在阅读的代码是:
char name[50];
char lastname[50];
char fullname[100];
...
cin.getline ( name, 50 );
...
cin.getline ( lastname, 50 );
fullname[0] = '\0'; // strcat searches for '\0' to cat after
strcat ( fullname, name ); // Copy name into full name
strcat ( fullname, " " ); // We want to separate the names by a space
strcat ( fullname, lastname ); // Copy lastname onto the end of fullname
请有人解释一下。
答案 0 :(得分:2)
在C ++中,有像char name[50]
这样的字符数组,还有像std::string
这样的字符串类。
字符数组根据它们在C中的相同规则进行初始化 - 也就是说,如果它们是堆栈变量,则它们不会被初始化,如果它们是静态/全局变量,它们在加载时被初始化为零 - 那里然而,基于系统细节是例外,因此最好假设它们从未被初始化。
字符串类(如std :: string)被初始化为对象的构造函数阶段的一部分 - 因此它们始终被初始化。
在您的特定代码中,您使用的是固定长度的字符数组。它们通常是空终止的,但它们可能并不总是 - 特别是cin.getline ( name, 50 );
将读取完整的50个字符,如果输入中有49个字符或更少,它将使数据空终止,但是没有空格超过50个字符如果有50个字符或更多字符,它将不会终止 - 这会对您的strcat
产生影响,因为strcat
假设数据为空终止 - 您必须使用strncat
来改善代码安全。
答案 1 :(得分:1)
与任何其他数据类型相同。默认情况下,局部变量包含垃圾值。因此,如果您要阅读其值,则将其初始化。但是如果你知道你将写入变量,那么你可以跳过初始化部分。
例如:
char a[20]; //local variable
包含垃圾,因此在阅读之前需要先写一些有意义的数据。但是如果你只是写它,那么你可以跳过初始化。
答案 2 :(得分:0)
你有什么在堆栈上的分配。 编译器不保证分配的内存为空,因此你可以使用垃圾,这就是你需要填0以清除垃圾的原因。
你可以用
做到这一点memset(pointer, '0', size);
例如
char a[50]
memset(a, NULL, sizeof(char)*50);
当你取决于你在做什么时,如果你想在里面写一些数据并阅读,那么\ 0可能会保存你,因为它是截止日期,如果你想读取所有数据,char [50]忽略\ 0的50个字节,所以你需要清除数据。要走的路是清除^^中的数据。
答案 3 :(得分:0)
first_name
,last_name
不会立即初始化,因为接下来的两个
行首先立即初始化它们,full_name
得到一个0终止符
它将表示一个空字符串,可以与std :: strcat连接。
char first_name[50];
char last_name[50];
// There is no need to initialize first_name and last_name,
// they will contain garbage as with any uninitialized values but they get
// overwritten here when reading from stdin anyways.
cin.getline ( first_name, 50 );
cin.getline ( last_name, 50 );
char full_name[100];
// Again full_name contains garbage, so it gets a 0 terminator here in order
// to have it represent an empty string.
full_name[0] = '\0';
// full_name had to be an empty string in order to concatenate
// onto it using strcat
strcat ( full_name, first_name );
strcat ( full_name, " " );
strcat ( full_name, last_name );
话虽这么说,这些是C风格的字符串,你很可能只是喜欢
请改用std::string
。
答案 4 :(得分:0)
cin.getline
不使用或检查传入的缓冲区的原始值,因此对于该函数,缓冲区不需要初始化。
strcat
检查现有的缓冲区内容,以确定它应该在指定的字符串字符上应用的位置。因此,对于strcat
,缓冲区必须初始化,而不是任意,但有一些零字节标记逻辑字符串结束位置。
正如其他人所说,所显示的代码非常不安全。这是不安全的,因为(在我写这篇文章时尚未评论)维护程序员可能没有意识到full_name
正好所需的缓冲区大小以保持最大长度的名字加上空格加上姓氏的最大大小。这应该至少在评论中得到解释。
但是比评论更好,应该使用更安全的长度检查功能。
除了学习之外,更好的方法是使用std::string
等字符串类。