2013-01-03 123 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)'返回一個臨時表達式,它將在完整表達式的末尾被破壞。 –