如何逐行读取文件,每行中的内容也用空格隔开,并将其写入新文件中

问题描述 投票:1回答:1

例如,我用以下文件读取文件:

Cat Dog Monkey 1234
A,A #$%&  No

而且我需要将每个单词保存在另一个(是另一个)文件中,例如:

word 1: cat
word 2: Dog
word 3: Money
word 4: 1234

word 1: A,A 
word 2: #$%& 
word 3: 
word 4: No

我只是示例中的ofstream基本代码,因此,如果有人可以帮助我,那将很棒。还有一种方法可以保存这些单词并进行比较(如果以数字,字母,符号开头或有逗号)? (,)。我知道这是一个漫长的请求,因此每条信息都会受到赞赏(> n

c++
1个回答
0
投票

解决方案相当简单。

首先,我们打开文件并检查是否可行。我们在for循环中逐行读取源文件,并使用std::getline提取完整的行。

为了方便处理和使用std::istream_iterator,我们将其放入std::istringstream

为了将数据从源格式转换为目标格式,我们将使用(为此目的,专用功能std::transform

基本上就是它,

请参见下面的简单示例:

#include <iostream>
#include <fstream>
#include <iterator>
#include <string>
#include <sstream>
#include <algorithm>

const std::string sourceFileName{ "source.txt" };
const std::string resultFileName{ "result.txt" };

int main() {

    // Open source file and check, if it could be opened
    if (std::ifstream sourceStream(sourceFileName); sourceStream) {

        // open destination file and check, if it could be opened
        if (std::ofstream resultStream(resultFileName); resultStream) {

            // Read the source file line by line
            for (std::string line{}; std::getline(sourceStream, line); ) {

                // Put the just read file into a istringstream for easier processing
                std::istringstream iss(line);

                // Read every sub-string in the istringstream and convert it to the expected result, using a stateful Lambda
                std::transform(std::istream_iterator<std::string>(iss), {}, std::ostream_iterator<std::string>(resultStream, "\n"),
                    [i = 1U](const std::string& s) mutable { return "word " + std::to_string(i) + " " + s; });
                resultStream << std::endl;
            }
        }
        else std::cerr << "\n*** Error: Could not open source file '" << sourceFileName << "'\n\n";
    }
    else std::cerr << "\n*** Error: Could not open result file '" << resultFileName << "'\n\n";

    return 0;
}

编辑

我刚刚指出,您也想分割两个连续的空格。为此,我创建了一个拆分功能。该函数将如下所示

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

const std::string sourceFileName{ "r:\\source.txt" };
const std::string resultFileName{ "r:\\result.txt" };

std::vector<std::string> split(std::string& s) {

    // Result as vector of string
    std::vector<std::string> splitted;

    // Start searching at the beginning
    size_t startPos{ 0U };

    // Search all spaces
    for  (size_t foundPos{ 0U }; (foundPos = s.find(' ', startPos)) != std::string::npos; ) {

        // And store the sub string before the found space
        splitted.push_back(s.substr(startPos, foundPos - startPos));
        startPos = foundPos+1;
    }
    // At the end of the string there is no space. So add last sub-string
    splitted.push_back(s.substr(startPos));
    return splitted;
}


int main() {

    // Open source file and check, if it could be opened
    if (std::ifstream sourceStream(sourceFileName); sourceStream) {

        // open destination file and check, if it could be opened
        if (std::ofstream resultStream(resultFileName); resultStream) {

            // Read the source file line by line
            for (std::string line{}; std::getline(sourceStream, line); ) {

                std::vector vs = split(line);

                // Read every sub-string  and convert it to the expected result, using a stateful Lambda
                std::transform(vs.begin(), vs.end(), std::ostream_iterator<std::string>(resultStream, "\n"),
                    [i = 1U](const std::string& s) mutable { return "word " + std::to_string(i) + " " + s; });
                resultStream << std::endl;
            }
        }
        else std::cerr << "\n*** Error: Could not open source file '" << sourceFileName << "'\n\n";
    }
    else std::cerr << "\n*** Error: Could not open result file '" << resultFileName << "'\n\n";

    return 0;
}

并且,如果您想使用C ++核心技术,则可以使用正则表达式和std::sregex_token_iterator。这个东西是用来分割字符串的,也可以使用。

这导致了一个优雅的C ++解决方案:

#include <iostream>
#include <fstream>
#include <iterator>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <regex>

const std::string sourceFileName{ "r:\\source.txt" };
const std::string resultFileName{ "r:\\result.txt" };

const std::regex re{R"([ ]{1})"};

int main() {

    // Open source file and check, if it could be opened
    if (std::ifstream sourceStream(sourceFileName); sourceStream) {

        // open destination file and check, if it could be opened
        if (std::ofstream resultStream(resultFileName); resultStream) {

            // Read the source file line by line
            for (std::string line{}; std::getline(sourceStream, line); ) {

                // Read every sub-string  and convert it to the expected result, using a stateful Lambda
                std::transform(std::sregex_token_iterator(line.begin(), line.end(), re, -1), {}, std::ostream_iterator<std::string>(resultStream, "\n"),
                    [i = 1U](const std::string& s) mutable { return "word " + std::to_string(i) + " " + s; });

                resultStream << std::endl;
            }
        }
        else std::cerr << "\n*** Error: Could not open source file '" << sourceFileName << "'\n\n";
    }
    else std::cerr << "\n*** Error: Could not open result file '" << resultFileName << "'\n\n";

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.