我们在尝试解析输入文件时遇到了一个奇怪的问题。我们的想法是这个文件可以包含其他文件,这些文件也必须被解析。我们在一个定义为
的函数中递归地执行此操作 int parse_inp(const char* filename)
主文件解析没问题,但递归调用无法打开文件流。
int parse_inp(const char* filename)
{
char buffer[BUFFER_MAX+1];
char* token;
std::string tok;
int keywordSection;
bool end_of_file;
int cardNum;
...
int i;
std::string tempop;
double tempd1, tempd2;
SetSegmentCard2 tempSetSegmentCard2;
int offset;
printf("%s\n", filename);
std::ifstream inp;
inp.clear();
inp.open(filename, std::ios::in);
if(!inp.good() || !inp.is_open())
{
char path1[256];
getcwd(path1,256);
printf("CWD: %s\n", path1);
fflush(NULL);
printf("Unable to open '%s'\n", filename);
return 0;
}
std::set<std::string> unrecognized;
std::string line;
while(inp.good() && !inp.eof())
{
getline(inp, line);
strcpy(buffer, line.c_str());
if (isComments(buffer)) //skip the comments line
continue;
if (buffer[0]=='*') //this is a keyword line
{
token = strtok(buffer," \n");
keywordSection = is_inp_keyw(token);
if (keywordSection==0)
unrecognized.insert(token);
cardNum = 0;
continue;
}
//a data line
tempop="";
char* found = NULL;
char path_buffer[100] = "Dyna3DWriter\\";
int pos = 0;
switch(keywordSection)
{
case 0: //not recognized
//end of last keyword, not recognizable word
break;
case 1: //KEYWORD
//"KEYWORD didn't do anything
break;
case 2: //TITLE
break;
case 3: //INCLUDE
token = strtok(buffer, "\n");
inp.clear();
parse_inp(token);
break;
...
}
}
if(inp.is_open())
{
inp.close();
inp.clear();
}
}
递归文件永远不会解析。我环顾了很多,大多数问题似乎都是设置了失败位(这就是为什么我们大量调用inp.clear()
),或者我们对当前工作目录做出了错误的假设。
为了测试第二种理论,我们加入了:
if(!inp.good() || !inp.is_open())
{
char path1[256];
getcwd(path1,256);
printf("CWD: %s\n", path1);
fflush(NULL);
printf("Unable to open '%s'\n", filename);
return 0;
}
我们的工作目录和文件名都是正确的。使用fopen(filename, "r")
时,我们会看到相同的行为---调用perror("fopen")
会导致:
fopen: no such file or directory
编辑:填写更多代码
答案 0 :(得分:2)
您确定文件名中不包含会导致此问题的任何垃圾或错误字符吗? 如果错误是找不到文件,则表示文件名在某种程度上是错误的。
它可能来自buffer
的错误声明吗?我们在您的代码中没有看到它。
另一种可能性是在打开文件之前在初始化中再次使用strtok
。您必须避免使用基于全局存储的strtok
这样的递归方法。您应该使用strtok_r
代替。
答案 1 :(得分:0)
如果你的递归函数调用得非常深,你可以很容易地超过操作系统限制打开文件的数量。
我曾经运行过我的Gentoo Linux,每个进程的文件限制为250,但需要更多的程序除外。
Windows的限制因系统可用内存量以及系统范围内已创建的对象数而异。
这样做的聪明方法是拥有两个功能。第一个函数是其他人调用的函数,它执行设置,包括打开文件。第二个函数是递归函数,它只接受对std :: ifstream对象的引用。
我发现我误解了你的问题,而且你没有递归地打开相同的文件。无论如何,我会留下我的上段。