2011-05-25 113 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; 
}