【问题标题】:Read file into array and return it from a function C++将文件读入数组并从函数 C++ 返回
【发布时间】:2015-04-22 19:09:55
【问题描述】:

在Lua中,我有这样一个函数可以将文件读入数组:

function readFile(file)
  local output = {}
  local f = io.open(file)
  for each in f:lines() do
    output[#output+1] = each
  end
  f:close()
  return output
end

现在在 C++ 中,我尝试这样写:

string * readFile(file) {
  string line;
  static string output[] = {};
  ifstream stream(file);
  while(getline(stream, line)) {
    output[sizeof(output)+1] = line;
  }
  stream.close();
  return output;
}

我知道你不能从函数返回数组,只能返回指针。所以我这样做了:

string *lines = readFile("stuff.txt");

它给我带来了错误cannot convert 'std::string {aka std::basic_string<char>} to' std::string* {aka std::basic_string<char>*}' in intialization string *lines = readFile("stuff.txt");

谁能告诉我这里出了什么问题,有没有更好的方法将文件读入数组?

编辑: 我将使用返回的数组使用 for 循环进行值匹配。在 Lua 中,这将被写为:

for _, each in ipairs(output) do
  if each == (some condition here) then
    --Do Something
  end
end

如何在 C++ 中使用向量来实现这一点(根据 Jerry Coffin 的回答)?

编辑 2: 由于某种原因,我无法正确匹配向量。我将代码写在一个单独的测试文件中。

int main() {
  vector<string> stuff = read_pass();
  cout << stuff.size() << endl;
  cout << stuff[0] << endl;
  if (stuff[0] == "admin") { 
    cout << "true"; 
  }
  else { 
    cout << "false"; 
  }
  return 0;
}

read_pass() 看起来像这样:

vector<string> read_pass() {
  ifstream stream("stuff.txt");
  string line;
  vector<string> lines;
  while(getline(stream, line)) {
    lines.push_back(line);
  }
  stream.close();
  return lines;
}

stuff.txt 看起来像这样:

admin
why?
ksfndj

我只是放了一些随机行来测试代码。每次我编译并运行 main.cpp 时,我得到的输出是

3
admin
false

那为什么代码没有正确匹配?

编辑 3:

因此,我没有强迫自己采用向量方法,而是决定尝试一下:

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include "basefunc.h"

using namespace std;

int main() { 
  string storedUsrnm;
  string storedPw;
  string pw = "admin";
  string usrnm = "admin";
  ifstream usernames("usrnm.accts");
  ifstream passwords("usrpw.accts");
  while(getline(usernames, storedUsrnm)) {
    getline(passwords, storedPw);
    print("StoredUsrnm " + storedUsrnm);
    print("StoredPw: " + storedPw);
    if (storedUsrnm == usrnm && storedPw == pw) {
      print("True!");
      return 0;
    }
  }
  print("False!");
  return 0;
}

print() 在哪里

void print(string str) {
  cout << str << endl;
}

这仍然打印错误,最后,它让我相信由于某种原因,ifstream 读取的"admin""admin" 字符串不同。任何解释这是怎么回事?还是这段代码也不起作用?

【问题讨论】:

  • output 不会自动调整大小。你在这里 output[sizeof(output)+1] 所做的事情是未定义的。
  • 即使您可以像这样调整数组的大小,sizeof 运算符也会产生数组中的字节数,而不是条目数,因此寻址将是错误的。
  • 此外,返回指向分配在堆栈上的数组的指针是一个坏主意,正如 here 所解释的那样。
  • @LeeYi 您的代码对我来说很好,请确保您的输入文件中没有空格,并且它是在与您编译的代码相同的操作系统上创建的。

标签: c++ arrays c++11 lua


【解决方案1】:

在我看来,您当前的代码甚至不应该编译。无论如何,我可能会做这样的事情:

std::vector<std::string> read_file(std::istream &infile) { 

    std:string line;
    std::vector<std::string> lines;

    while (std::getline(infile, line))
        lines.push_back(line);

    return lines;
}

所以这里的基本思想是从文件中读取一行,如果成功,则将该行(带有push_back)添加到结果向量中。重复直到从文件中读取一行失败。然后将所有行的向量返回给调用者。

一些注意事项:尤其是一开始,可以相当安全地假定任何指针的使用都可能是一个错误。这不应该被认为是指针非常难以使用,或者类似的东西——只是对于大多数相对初学者在 C++ 中所做的事情来说,它们几乎从来都不是必需的。

数组也是如此——首先,假设您在其他语言中可能认为的数组转换为 C++ 中的std::vector。 C++ 也有数组,但使用它们可能会等待一段时间(很长一段时间,IMO——我已经编写 C++ 几十年了,几乎从不使用原始指针 数组)。

为了简单起见,我将数据合并到程序中,所以它从字符串流中读取数据,如下所示:

#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <sstream>

using namespace std;

vector<string> read_pass(istream &is) {
    string line;
    vector<string> lines;
    while (getline(is, line)) {
        lines.push_back(line);
    }
    return lines;
}

int main() {
    istringstream input{ "admin\nwhy?\nksfndj" };
    // To read from an external file, change the preceding line to:
    // ifstream input{ "stuff.txt" };

    vector<string> stuff = read_pass(input);
    cout << stuff.size() << endl;
    cout << stuff[0] << endl;
    if (stuff[0] == "admin") {
        cout << "true";
    }
    else {
        cout << "false";
    }
    return 0;
}

至少对我来说,这会产生:

3
admin
true

...表明它已按预期工作。我对外部文件也有同样的看法。如果您对外部文件没有得到相同的结果,我的直接猜测是(至少第一行)该文件包含一些您不期望的数据。如果问题仍然存在,您可能会考虑以数字格式写出您读取的字符串的各个字符,以便更明确地了解您真正阅读的内容。

【讨论】:

  • 那么我可以像数组一样使用它吗?另外,如何将参数传递给这个函数?
  • @LeeYi:是的,主要是——也就是说,你当然可以像数组一样索引它。与数组不同,您可以使用lines.size() 获取其大小,使用.push_back() 向其中添加新项目,使用.erase() 删除项目等。
  • 我现在已经让向量工作了,但是如何匹配某个值?例如,if (lines[0] == "hi")
  • @LeeYi: if (lines[0] == "hi") 可以工作(假设linesstd::string 的向量,如建议的那样)。
  • @LeeYi:我已经添加了一个完整的演示程序。
【解决方案2】:

折腾了好久,终于想出答案了

#include <fstream>
#include <iostream>
#include <cstdlib>
#include <map>

using namespace std;

typedef map<int, string> strArr;

strArr readFile(string file) {
  ifstream stream(file);
  string line;
  strArr output;
  while(getline(stream, line)) {
    output[output.size()+1] = line;
  }
  stream.close();
  return output;
}

它不会将文件读入数组,但会返回一个基本相同的映射

【讨论】:

    猜你喜欢
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    相关资源
    最近更新 更多