尝试约1小时后,我的代码因此无法正常工作:
void s_s(string const& s, char data[10])
{
for (int i = 0; i < 10; i++)
data[i] = s[i];
}
int main()
{
string ss = "1234567890";
char data[10];
s_s("1234567890", data);
cout << data << endl;//why junk
}
我根本不明白为什么cout在char数组后显示垃圾。有人可以解释为什么以及如何解决它?
答案 0 :(得分:6)
你需要null终止你的char数组
std::cout.operator<<(char*)
使用\0
知道停止的位置
顺便说一下,char[]
衰减到char*
。
看here。
答案 1 :(得分:2)
如前所述,您希望NUL终止您的阵列,但这里还有其他需要考虑的事项:
如果s
是您的源字符串,那么您希望循环到s.size()
,这样就不会循环超过源字符串的大小。
void s_s(std::string const& s, char data[20])
{
for (unsigned int i = 0; i < s.size(); i++)
data[i] = s[i];
data[s.size()] = '\0';
}
或者,你可以试试这个:
std::copy(ss.begin(), ss.begin()+ss.size(),
data);
data[ss.size()] = '\0';
std::cout << data << std::endl;
答案 2 :(得分:2)
您只为数据分配了10个字节
该字符串实际上是11个字节,因为最后有一个隐含的'\0'
至少应该将数据大小增加到11,并更改循环以复制'\0'
答案 3 :(得分:0)
您尝试在main的最后一行使用的函数std::ostream::operator<<
会将char
数组作为指针,并将每char
打印一次,直到 null找到了sentinel 字符(字符为\0
)。
此定标字符通常在定义了C字符串文字的语句中为您生成:
char s[] = "123";
在上面的示例中,sizeof(s)
是4
,因为存储的实际字符是:
'1', '2', '3', '\0'
最后一个字符是需要在const char*
字符串的每个字符串上循环的任务的基础,因为循环终止的条件是必须读取\0
。
在您的示例中,您看到的“垃圾”是内存中0
个字节后面的字节(解释为char
)。此行为显然未定义,可能导致程序崩溃。
一个解决方案是显然在char数组的末尾添加\0
char(当然固定大小)。
但是,最好的解决方案是永远不要将const char*
用于字符串。您在示例中正确使用了std::string
,这可以防止出现此类问题以及其他许多问题。
如果您需要const char*
(例如,对于C API),您始终可以使用std::string::c_str
并检索std::string
的C字符串版本。
您的示例可以重写为:
int main(int, char*[]) {
std::string ss = "1234567890";
const char* data = ss.c_str();
std::cout << data << std::endl;
}
(在此特定情况下,std::ostream::operator<<
的{{1}}版本已定义std::string
,因此您甚至根本不需要data