2013-01-03 99 views
1

我在这里做错了什么?从路径返回文件名

呼叫

printf(filename(exename)); 

我的函数返回的文件名

const char* filename(const string& str) 
{ 
    const char* path; 
    size_t found; 
    found=str.find_last_of("/\\"); 
    path = (str.substr(found+1)).c_str(); 

    cout << str.substr(found+1); // ------------> is name ok 

    printf("\n\n"); 
    printf(path); // ------------> is name not ok random numbers 
    printf("\n\n"); 
    return path; // ------------> is not ok random numbers 
} 
+0

你不应该在这里的printf使用,但还是的fputs看跌期权,或可能'的printf( “%S”,EXENAME);'。 –

+0

@WilliamPursell你能提醒我为什么又是这样吗? –

+0

如果文件名包含格式化字符,就会发生不好的事情。这在你的情况下可能不是问题,但当不需要时解析字符串是浪费的。 –

回答

2

str.substr(found+1)返回一个临时std::string。 您可以拨打c_str()方法临时std::string,并将返回的指针指定给path。 当临时销毁时(在;),您的路径指向垃圾。

请你帮个忙,并使用C++(不是C与C++混合),使用像std::string强大的字符串类存储字符串(而不是原始潜在的,晃来晃去char*指针):

std::string FileName(const std::string& str) 
{ 
    size_t found = str.find_last_of("/\\"); 
    std::string path = str.substr(found+1); // check that is OK 
    return path; 
} 

还要注意您使用path变量名称会令人困惑,因为函数似乎会返回文件名(而不是路径)。

一个简单重写(不path变量):

std::string ExtractFileName(const std::string& fullPath) 
{ 
    const size_t lastSlashIndex = fullPath.find_last_of("/\\"); 
    return fullPath.substr(lastSlashIndex + 1); 
} 


printf("Filename = %s\n", ExtractFileName("c:\\some\\dir\\hello.exe").c_str()); 

...或者只是使用cout(与std::string打得很好,并不需要c_str()方法调用来获取原始的C字符串的指针一样用C printf()功能):

std::cout << ExtractFileName("c:\\some\\dir\\hello.exe"); 
5

您在返回一个指针内存由临时(str.substr(found+1)).c_str()举行。当临时超出范围时,内存可能随时被覆盖。

str.substr(found+1)是一个表达式,返回string。该对象是一个临时值,在包含它的表达式执行结束时会消失。使用.c_str(),您将获得由此对象控制的内存指针。在该对象的生命周期之后,该指针不再有效。

尝试声明path作为string,并让您的函数返回string而不是指针。

一般而言,当您使用std::string类时,您应该避免使用原始的char *。这意味着你也应该避免使用printf;改为使用std::iostream类。

+0

请你再解释一下吗?什么时候超出范围,什么时候? – Rotem

+1

然而,函数'filename'内的打印仍应该产生可靠的输出,除非'substr'没有找到斜线。 –

+0

@WilliamPursell printf insed函数是未定义的行为。表达式'str.substr(found + 1)'返回一个临时表达式,它将在完整表达式的末尾被破坏。 –