我一直在读一本自学书(http://www.amazon.com/gp/product/0321992784),我在第17章做了练习。其中一个我解决了,但我不满意,想要一些帮助。先谢谢你。
练习:编写一个程序,将cin中的字符读入您在免费商店中分配的数组中。读取个人字符,直到输入感叹号(!)。不要使用std :: string。不要担心内存耗尽。
我做了什么:
char* append(const char* str, char ch); // Add a character to the string and return a duplicate
char* loadCstr(); // Read characters from cin into an array of characters
int main()
{
char* str{ loadCstr() };
std::cout << str << '\n';
return 0;
}
我创建了2个函数,1创建一个大于1的新字符串,并在末尾添加一个字符。
char* append(const char* str, char ch)
/*
Create a new string with a size 1 greater than the old
insert old string into new
add character into new string
*/
{
char* newstr{ nullptr };
int i{ 0 };
if (str)
newstr = new char [ sizeof(str) + 2 ];
else
newstr = new char [ 2 ];
if(str)
while (str [ i ] != '\0')
newstr [ i ] = str [ i++ ]; // Put character into new string, then increment the index
newstr [ i++ ] = ch; // Add character and increment the index
newstr [ i ] = '\0'; // Trailing 0
return newstr;
}
这是使用我创建的附加功能进行练习的功能,它可以工作,但是根据我的理解每次调用append时,都会出现内存泄漏,因为我创建了一个新的字符数组并且没有删除旧的。
char* loadCstr()
/*
get a character from cin, append it to str until !
*/
{
char* str{ nullptr };
for (char ch; std::cin >> ch && ch != '!';)
str = append(str, ch);
return str;
}
我尝试添加另一个指针来保存旧数组,并在创建一个新数组后将其删除,但在此循环中大约6次调用后,我得到一个运行时错误,我想我会删除我不应该删除的内容&# 39;吨?这是我困惑的地方。
这是一个不超过6个字符的旧版本:
char* loadCstr()
/*
get a character from cin, append it to str until !
*/
{
char* str{ nullptr };
for (char ch; std::cin >> ch && ch != '!';) {
char* temp{ append(str, ch) };
if (str)
delete str;
str = temp;
}
return str;
}
所以我想知道如何修复这个功能,所以没有内存泄漏。再次感谢你。 (另请注意,我知道这些函数已经存在并且使用std :: string为我处理所有免费商店的东西,我只想了解它,这是一个学习练习。)
答案 0 :(得分:0)
要了解内存管理,还是了解字符串操作如何在内部工作?
对于第二个(学习字符串操作),你应该使用std::unique_ptr<char[]>
,它会在指针死亡时自动释放附加的数组。你仍然需要计算字符串长度,在字符串之间复制,追加 - 你现在正在做的所有事情。但std::unique_ptr<char[]>
将处理释放。
对于第一种情况,你最好编写一个RAII类(std::unique_ptr<T>
的自定义版本)并学习如何在析构函数中释放内存,而不是在代码中散布delete []
语句。在任何地方写delete []
实际上都是一个坏习惯,学习它会使你的C ++编程能力向后移动。
答案 1 :(得分:0)
您必须使用标准C函数std::strlen
而不是sizeof
运算符,因为在函数的情况下,sizeof
运算符返回指针的大小而不是字符串的长度。
您还需要删除已分配的数组。
该功能可以按以下方式查看
char* append(const char* str, char ch)
/*
Create a new string with a size 1 greater than the old
insert old string into new
add character into new string
*/
{
size_t n = 0;
if ( str ) n = std::strlen( str );
char *newstr = new char[ n + 2 ];
for ( size_t i = 0; i < n; i++ ) newstr[i] = str[i];
delete [] str;
newstr[n] = ch;
newstr[n+1] = '\0';
return newstr;
}
在函数loadCstr
中,可以像
str = append( str, ch );
也可以使用标准算法std::copy