bool功能不能在一段时间内起作用

时间:2019-09-20 10:47:31

标签: c++

我试图检查文件是否已成功打开,从文件中读取并输出我从文件中读取的所有内容,因为我有7个文件需要在同一代码中进行操作,因此我想避免一遍又一遍地写相同的代码。

所以我做了一个bool函数,并将其作为while条件。

如果成功,该函数将返回true,如果失败,则将返回false。所以while(!function)应该一直尝试直到它起作用,对吗?答案是肯定的,它可以按预期工作。

但是,如果我将while的条件更改为while(function),则可以期望重复执行该函数,直到它以某种方式失败(也许无法打开文件)。但它的行为不符合预期。它只能在第一次while迭代中正常工作。

这是示例:

#include <iostream>
#include <unistd.h>
#include <string.h>
#include <fstream>
#include <sstream>

bool readConfig(std::fstream& file, std::string (&str)[10], std::string identity) {
  if(file.is_open()) {
    if(file.seekg(0)) {
      std::cout<<"Start from 0"<<std::endl;
    }
    // Get content line by line of txt file
    int i = 0;
    while(getline(file, str[i++]));
    std::cout<<"i= "<<i<<std::endl;
    for(int k = 0; k<i; k++) {
    std::cout<<identity<<" = "<<str[k]<<std::endl;
    }
    return true;
  } else {
    std::cout<<"ERROR ! Could not open file."<<std::endl;
    return false;
  }
}

int main() {

    char configFilePath[]="test.txt";
    std::fstream configFile;

    configFile.open(configFilePath, std::fstream::in);
    std::string test[10];
    std::string id = "testing";
    while(!readConfig(configFile, test,id)) {
        usleep(1000*1000);
    };

    return 0;
}

这是test.txt的内容:

line 1
line 2
line 3
line 4

这是输出:

Start from 0
i= 5
testing = line 1
testing = line 2
testing = line 3
testing = line 4
testing = 
i= 1
testing = line 1
i= 1
testing = line 1

以此类推。

为什么它在第一次迭代中起作用,然后在i=1处停止?我问是因为我不知道自己做的事是否正确。 while(!function)有效,但也许并非一直有效,也许我的代码有缺陷。

还是while(getline(configFile, string[i++]));在这里错了?

这是我要替换的代码:

void readConfig(std::fstream& configFile, std::string (&str)[10], std::string identity) {
  if(configFile) {
    // Get content line by line of txt file
    int i = 0;
    while(getline(configFile, str[i++]));
    //for debug only
    if((i-1) == 0) {
      std::cout<<identity<<" = "<<str[i-1]<<std::endl;
    } else {
      for(int k = 0; k<i-1; k++) {
        std::cout<<identity<<" = "<<str[k]<<std::endl;
      }
    }
  } else {
    log("ERROR ! Could not get content from file.");
  }
}

int main() {
file.open(file, std::fstream::in);
    if(file.is_open()) {
      std::cout<<"Successfully opened URL Display Text file."<<std::endl;
      std::string inputs[10];
      std::string id = "url_text";
      readConfig(file, inputs, id);
      file.close();
    } else {
      // Could not open file
      log("Error ! Could not open file.");
    }
}

我执行了7次,而不是仅仅调用一次函数7次,而这全部完成了。

4 个答案:

答案 0 :(得分:1)

  

但是,如果我将while的条件更改为while(function),则可以期望重复执行该功能,直到它以某种方式失败(也许无法打开文件)。

您的推理在这里不对。该函数不会打开文件,因此在第一次迭代中成功进行下一次迭代时不会出错。

该函数的作用是:它读取文件的所有内容,然后返回true。随后的迭代没有什么可读取的,但是函数仍然返回true

您应该检查文件是否仅打开一次,而不是在每次迭代中打开。如果该函数应该读取一行,那么请使其当前读取所有行。

答案 1 :(得分:1)

将测试从if (file.is_open())更改为if (file)。无法打开文件并不是文件流最终可能处于不良状态的唯一方法。特别是,在第二次调用此函数时,流是打开的,但由于上次读取尝试失败而处于失败状态。

答案 2 :(得分:0)

如果您只想逐行读取文件,打印并存储这些行,我会这样做。

  • 使用std::vectorstd::array
  • 而不是使用c样式的数组
  • 在调用读取函数之前检查文件是否已打开

    #include <fstream>
    #include <iostream>
    #include <string>
    #include <vector>
    
    void readConfig(std::ifstream& configFile,
                    std::vector<std::string>& lines,
                    const unsigned int limit) {
        std::string line;
    
        while (std::getline(configFile, line)) {
            if (lines.size() >= limit) {
                break;
            }
            lines.push_back(line);
        }
    }
    
    int main() {
        const std::array<std::string, 3> fileNames = {"test1.txt", 
                                                      "test2.txt", 
                                                      "test3.txt"};
    
        // Iterate over all your files
        for (const auto& fileName : fileNames) {
            // Open the file
            std::ifstream configFile(fileName);
    
            if (!configFile.is_open()) {
                std::cout << "ERROR! Could not open file.\n";
                continue;
            }
    
            // Read the file
            std::vector<std::string> lines;
            constexpr unsigned int limit = 4;
            readConfig(configFile, lines, limit);
    
            if (configFile.is_open()) {
                configFile.close();
            }
    
            // Work with the file content
            std::cout << fileName << "\n";
            for (const auto& line : lines) {
                std::cout << "testing = " << line << "\n";
            }
            std::cout << "\n";
        }
        return 0;
    }
    

答案 3 :(得分:0)

您的输出可以清楚地显示正在发生的事情。您有足够的调试输出来确定已做出的选择。我要重点介绍的重点是以下顺序:

testing = 
i= 1

第一行是从四行文件中读取的第五行。毫不奇怪,那里什么都没有。下一条输出行来自readConfig在分支file.isopen()为true的某处的下一次调用。但是,请注意,在这两个之间没有 not 一行,表示“从0开始”。这意味着file在调用false之后转换为file.seekg(0)(该函数返回的值为file,而不是直接的布尔值)。这表明存在某种错误状态,应该期望该错误状态持续存在直到清除。而且没有尝试清除它。

代码的下一部分是getline循环。与seekg一样,getLine函数返回流(file)而不是布尔值。如预期的那样,错误状态一直存在,从而使循环成为false,因此没有循环迭代。

testing = line 1

输出的下一行是不明确的。这可能表明位置已成功更改为文件的开头,并且输入的第一行已成功读取。或者它可能指示在删除提供的字符串之前返回对getLine的调用,而将第一次调用中的内容留给readConfig。我正在考虑使用后者,但是您可以通过在str[0]循环之前手动擦除getline来进行检查。

通常,这样重复使用资源会使调试更加困难,因为结果可能会产生误导。如果str是局部变量而不是参数,则调试的混乱程度将降低。与file类似-除了可以使用流参数之外,您还可以传递带有要打开文件名称的字符串。