2011-05-25 111 views
3

我一直負責對C++應用程序進行簡單的更改。不幸的是,我來自Java背景,並且遇到了一些指針問題。指針混淆 - C++

有問題的代碼讀取來自給定目錄(使用環境變量設置)的文件列表,並對每個文件執行一些操作。

char * rebuildDir = getenv("REBUILD_DIR"); 
char * currentFile; 
DIR *asciiDir; 
struct dirent *ent; 

asciiDir = opendir(rebuildDir); 
if (asciiDir != NULL) 
{ 
    while ((ent = readdir(asciiDir)) != NULL) 
    { 
     std::cout << "rebuild sensor, rebuild dir is " << getenv("REBUILD_DIR") << std::endl; 
     currentFile = rebuildDir; 
     strcat(currentFile, ent->d_name); 
     ifstream raw(currentFile); 
     while(raw) 
     { 
      ...snip... 
     } 
     raw.close(); 
    } 

    closedir(asciiDir); 
} 

正如你所看到的,其目的是保存環境變量一次,然後將其複製到currentFile,然後concatonate當前文件名currentFile,準備進入ifstream的。

的問題是,

currentFile = rebuildDir; 

沒有重置環境變量,所以strcat的不斷使用舊的文件名,並追加到它,所以:

/home/file1 
/home/file2 
/home/file3 

將執行作爲

/home/file1 
/home/file1/home/file2 
/home/file1/home/file2/home/file3 

通過循環。我在猜測我用指針犯了一個元錯誤,但我一直沒有找到它。

感謝您的任何幫助,併爲微不足道的問題道歉。

PS - 如果有一個明顯更好的方法來完成我的任務,請你這樣的修改字符串中的地方隨時指出來:)

+0

感謝您的答案每個人,都非常有用。 – Caligari 2011-05-25 03:27:27

回答

5

當前文件指向相同的內存rebuilddir。你需要複製字符串。你可以這樣做:

char currentFile[MAX_PATH]; 
snprintf(currentFile, MAX_PATH, "%s%s", rebuildDir, ent->d.name); 
+1

儘可能使用'snprintf'(儘管'MAX_PATH'是「相當大的」)。 – aschepler 2011-05-25 02:32:28

+0

好點。我必須更努力地打破sprintf的習慣。 – 2011-05-25 02:33:45

+0

「我必須更努力地打破sprintf的習慣」其實你最好更努力地打破'''''''''''''''printf'習慣並且只使用'std :: string':'std :: string currentFile(rebuildDir); currentFile + = ent-> d.name;' – 2011-05-25 06:16:01

3

「...不重置爲環境變量」。爲什麼它會「重置」任何事情?您正在將指針currentFile對準rebuildDir指向的實際環境變量值。然後你通過strcat修改指出對象,即你基本上是修改(即銷燬)你原來的環境變量值。

你不應該那樣做。如果您想從環境變量的值構建新名稱,則必須將該值複製到一邊,然後修改該副本,而不是試圖銷燬原始文件。

例如,你可以使用std::string對原值創建副本

const char *rebuildDir = getenv("REBUILD_DIR"); 
... 
std::string currentFile = rebuildDir; 
currentFile += ent->d_name; 
ifstream raw(currentFile.c_str()); 
1
int main(int argc, char *argv[]) 
{ 
    char* pDir = getenv("REBUILD_DIR"); 

    if (! pDir) 
    { 
     cerr << "did not find ENV var\n"; 
     exit(1); 
    } 

    string rebuildDir(pDir); 

    DIR* asciiDir; 

    if ((asciiDir = opendir(rebuildDir.c_str())) != NULL) 
    { 
     std::cout << "rebuild sensor, rebuild dir is " << rebuildDir << std::endl; 

     struct dirent *ent; 

     while ((ent = readdir(asciiDir)) != NULL) 
     { 
      string currentFile(rebuildDir); 

      currentFile += '/' + string(ent->d_name); 

      //probably want to skip "." and ".." entries... 

      /* 
      ifstream raw(currentFile); 

      while(raw) 
      { 
       ...snip... 
      } 

      raw.close(); 
      */ 
     } 

     closedir(asciiDir); 
    } 
    else 
    { 
     cerr << "coult not open dir\n"; 
     exit(1); 
    } 

    return 0; 
}