在为更大的项目进行文件路径操作之前,我想更好地理解内存和指针。这是简单的替换字符串测试函数的一部分,我需要将其重写为struct来调用。我使用作用域来测试内存泄漏和更改,我在Windows7、CygWin和notepad++上工作。
由于以下原因,我使用std::size_t作为大小表示:
一个大小不能由std::size_t表示的类型是优先选择提到的"std::size_t通常用于数组索引和循环计数“的错误形式。
我决定选择c样式的空终止字符数组,因为通过main(int argc, char **argv)传递的参数是空终止字符,系统调用接受最好的参数。对于我自己需要的代码部分来说,这似乎是有益的,而不是依赖于另一个库,而且跟踪用c_str()转换的代码和没有转换的代码是很累人的。
如前所述,此函数是项目的一部分,用于操作、更改和创建文件的完整或相对路径。字符数组帮助我使用stat ( CygWin附带的)能够自动测试路径、目录或文件是否是不可访问的。我可以使用std::string,但这是一个额外的头,我计划对文件路径进行认真的扩展,以包括一些自定义行为--这与此函数无关。
#include <iostream>
size_t get_str_size(const char* temp){
size_t s=0;
while( temp[s] != '\0' )s++;
return s;
}
int main(int argc, char **argv){
const char * temp = "sublime/subliminal/sfit.exe"; // example string
std::cout << &temp << "\t" << temp << std::endl; // prints out address and value
{ // wild scope to help me navigate and debug
const char* shitcake = "sfitcake"; // string to be put in place of sfit
size_t ldelim = 0; // / last delimiter
size_t edelim = 0; // . end delimiter
size_t original_size = get_str_size(temp);
// finding the necessary indexes of charachters
for( int i =0 ; i <= original_size; i++ ){
if( temp[i]=='/' ){ldelim=i;}
if( temp[i]=='.' ){edelim=i;}
}
// calculating size that influences the char array
size_t old_size = edelim - ldelim -1; // current char array size(-1 to remove last delimiter)
size_t new_size = get_str_size(shitcake); // new char array size
// char array duplication , since original string is const
char* tempcopy = new char[original_size]; // holds the copy of the temp
for( int i =0 ; i < original_size; i++ ){ tempcopy[i] = temp[i]; }
// value to be constructed
char *new_version = new char[ original_size + (new_size-old_size) ];
// filling the part before replacement happen
for( int i =0 ; i <=ldelim; i++ ) { new_version[i] = tempcopy[i]; }
// filling replaced char array
for( int i =0 ; i <= new_size;i++ ) { new_version[i+1+ldelim] = shitcake[i]; }
// the rest of original string
for( int i =edelim ; i < original_size;i++ ) { new_version[i+old_size] = tempcopy[i];}
//conversion back to const char* with expanded size and new value
temp = (const char*)new_version;
//deleting pointers
delete tempcopy;
delete new_version;
}
std::cout << &temp << "\t" << temp << std::endl;
return 0;
}我得到的输出是:
0xffffcbb8 sublime/subliminal/sfit.exe
0xffffcbb8 sublime/subliminal/sfitcake.exe这意味着它可以工作,但我害怕指针不会改变内存地址,即使大小和值发生了变化。
对守则的主要关切和愿望:
发布于 2019-09-16 16:46:08
size_t的作用域没有定义。因为描述意味着您需要std::size_t,所以您需要
#include <cstddef>
using std::size_t但我建议您只在使用std::size_t的地方完整地编写它--这对读者来说要清楚得多。
size_t get_str_size(const char* temp){ size_t s=0;while( tempS != '\0‘)s++;返回s;}
您只是无缘无故地重新实现了std::strlen()。
char\* tempcopy = new char[original\_size]; // holds the copy of the temp char \*new\_version = new char[ original\_size + (new\_size-old\_size) ]; delete tempcopy; delete new\_version;
使用new[]分配的内存必须使用delete[] (而不是delete)释放。瓦兰会帮你抓到这个错误的。
如果第一次分配成功,而第二次分配失败,则会出现内存泄漏,因为如果抛出一个delete[] tempcopy,则不存在std::bad_alloc。
我们在这里引用已删除的内存:
temp = (const char\*)new\_version; delete new\_version; std::cout << &temp << "\t" << temp << std::endl;
这是一种未定义的行为(而且也被Val差尔捕获--我确实建议您在Memcheck或您选择的任何类似工具下运行代码)。
int main(int argc,char **argv){
因为我们从不使用参数,所以没有必要给它们命名;而且,我们可以在没有参数的情况下使用main()的签名:
int main()for( int i =0 ; i <= original\_size; i++ ){
避免将有符号值(如i)与无符号值(如original_size)进行比较。我们可能也希望i的范围匹配,所以这两种类型都使用相同的类型。
该代码对一系列输入不太健壮。特别是,如果edelim小于ldelim,则在计算old_size时会得到(无符号)整数溢出,并给出不正确的结果。
总的来说,代码看起来非常类似于C代码--而糟糕的C代码(例如,一次复制一个字符,而不是使用memcpy())。C++实现(使用std::string)要短得多,而且更自然。
发布于 2019-09-18 13:40:08
您标记了这个C++,但是您的代码看起来一点也不像C++。它看起来像C,malloc由new代替,printf由std::cout代替。您可以使用C++标准库工具来简化代码。在这种情况下,您可以使用std::string简化代码:
#include <string>
#include <string_view>
std::string replace(std::string_view string, std::string_view pattern, std::string_view replace)
{
std::string result;
while (true) {
auto index = string.find(pattern);
result.append(string, 0, index);
if (index == string.npos)
break;
string.remove_prefix(index + pattern.size());
result += replace;
}
return result;
}(现场演示)
https://codereview.stackexchange.com/questions/229117
复制相似问题