【问题标题】:How to write words from a file to an array [duplicate]如何将文件中的单词写入数组[重复]
【发布时间】:2019-12-10 21:04:57
【问题描述】:

我无法将文件中的单词写入数组。

我尝试过使用 char 和 strings,但我对它们都有问题。

FILE *file = fopen("films.txt", "r");
string FILMS[500];
while (!feof(file))
{
    fscanf(file, "%s", FILMS);
    //fgets(FILMS, 500, file);
}

我希望每个单元格中都会有一个单词。

【问题讨论】:

  • 危险代码,容易出现安全漏洞。
  • 既然应该是 c++,为什么你不使用任何 c++?
  • 好吧,您使用的是string,但这不是您从文件中读取string 的方式...

标签: c++


【解决方案1】:

使用 C++ 类和函数使其更容易。使用std::vector<std::string>>,而不是恰好包含 500 部电影的固定 C 样式数组,当您将电影标题放入其中时,它将动态增长。

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

std::vector<std::string> get_films() {
    std::ifstream file("films.txt");
    std::vector<std::string> FILMS;
    if(file) { // check that the file was opened ok
        std::string line;
        // read until getline returns file in a failed/eof state
        while(std::getline(file, line)) {
            // move line into the FILMS vector
            FILMS.emplace_back(std::move(line));
            // make sure line is in a specified state again
            line.clear();
        }
    }
    return FILMS;
} // an fstream is automatically closed when it goes out of scope

int main() {
    auto FILMS = get_films();
    std::cout << "Read " << FILMS.size() << " film titles\n";
    for(const std::string& film : FILMS) {
        std::cout << film << "\n";
    }
}

【讨论】:

  • 如果使用std::stringstd::vector那么还不如使用std::copy
  • 在这种情况下,实际上简单地push_back(复制)而不是move 会更有效。您希望继续重复使用 line 作为缓冲区以避免代价高昂的重新分配。
  • 我喜欢这两个建议。 std::copy 很好,使用副本可能更有效。实际上,我还没有比较这两者......我们能得到关于效率高多少的数据吗?
【解决方案2】:

由于我不确定您为什么尝试使用 c 样式的数组和文件,因此我也发布了一个类似的“不太优雅”的解决方案,希望它可能会有所帮助。您总是可以尝试使用一些malloc(或new)使其更具动态性,但我现在坚持使用简单的解决方案。

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

void readcpp(const char* fname, std::vector<std::string>& data)
{
    std::ifstream file_in(fname, std::ios::in);

    if (file_in.is_open())
    {
        std::string film;

        while (std::getline(file_in, film))
        {
            data.push_back(film);
        }

        file_in.close();
    }
    else std::cerr << "file cant be opened" << std::endl;
}

#include <cstdio>
#include <cstdlib>
#include <cstring>

void readc(const char* fname, char data[500][500])
{
    FILE* file_in = fopen(fname, "r");

    if (file_in)
    {
        char film[500];

        for (unsigned int i = 0; fgets(film, 500, file_in) && i < 500; i++)
        {
            memcpy(data + i, film, 500);
        }

        fclose(file_in);
    }
    else fprintf(stderr, "file cant be opened\n");
}

int main()
{
    const char* fname = "films.txt";
    char cFilms[500][500];
    std::vector<std::string> cppFilms;

    readc(fname, cFilms);
    readcpp(fname, cppFilms);

    return 0;
}

和前面提到的其他人一样,不要使用 feof 或 ifstream 的 eof 成员函数来检查您是否到达文件末尾,因为它可能不安全。

【讨论】:

    【解决方案3】:

    嗯,我在答案中看到了很多代码。

    算法的使用将大大减少编码工作。

    此外,它是一种“更现代”的 C++ 方法。

    OP 说,他想在某个数组中包含单词。好的。

    所以我们将使用std::vector&lt;std::string&gt; 来存储这些单词。正如您在cppreference 中看到的,std::vector 有许多不同的构造函数。我们将使用数字 4,范围构造函数。

    这将构建具有一系列相似数据的向量。在我们的案例中,类似的数据是单词或std::string。我们想读取文件的整个范围,从文件中的第一个单词开始,到最后一个单词结束。

    为了迭代范围,我们使用迭代器。对于文件中数据的迭代,我们使用std::istream_iterator。我们告诉这个函数我们想读取什么作为模板参数,在我们的例子中是std::string。然后我们告诉它,从哪个文件中读取。

    由于我们在 SO 上没有文件,我使用 std::istringstream。但这与std::ifstream 的读数相同。如果你没有打开的文件流,那么你可以把它交给std::istream_iterator

    使用这种 C++ 算法的结果是,我们只需将变量及其构造函数定义为单行,就可以将完整的文件读入向量中。

    我们对调试输出做类似的事情。

    #include <iostream>
    #include <string>
    #include <vector>
    #include <iterator>
    #include <algorithm>
    #include <sstream>
    
    std::istringstream filmFile{ R"(Film1 Film2
       Film3  Film4 Film5
    Film6
    )" };
    
    int main()
    {
        // Define the variable films and use its range constructor
        std::vector<std::string> films{ std::istream_iterator<std::string>(filmFile), std::istream_iterator<std::string>() };
    
        // For debug pruposes, show result on console
        std::copy(films.begin(), films.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
    
        return 0;
    }
    
    

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-04
      • 2012-06-07
      • 2020-01-19
      • 2020-02-23
      相关资源
      最近更新 更多