如果我的输入是多行的,我需要输出也是多行的

时间:2019-06-09 16:16:41

标签: c++

我创建了一个程序,该程序可以反转句子中每个单词的字母。我正在通过4行将文本输入到输入文本文件中。输出文本全部在一行上,但我需要这样,以便当输入转到下一行时,输出也是如此。

string reversed(string word)
{
    int n;

    for(int i=0; i<word.length()/2; i++)
    {
        swap(word[i],word[word.length()-1-i]);
    }

    return word;
}

int main()
{
    ifstream in;
    ofstream out;

    in.open("input.txt");
    out.open("output.txt");

    string word;

    while(in>>word){
        out << reversed(word) << " ";
    }

    in.close();
    out.close();

    return 0;
}

输入示例:

Expecting the world to treat you
fairly because you are a good person
is a little like expecting the bull not to
attack you because you are a vegetarian.

输出示例:

gnitcepxE eht dlrow ot taert uoy
ylriaf esuaceb uoy era a doog nosrep
si a elttil ekil gnitcepxe eht llub ton ot
kcatta uoy esuaceb uoy era a nairategev.

3 个答案:

答案 0 :(得分:1)

使用std::getline()从输入中读取文本的各个行,然后使用std::istringstream遍历每行的各个单词:

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

std::string reversed(std::string word) {
    std::reverse(word.begin(), word.end());
    return word;
}

int main() {
    std::ifstream in("input.txt");
    std::ofstream out("output.txt");
    std::string line, word;

    while (std::getline(in, line)) {
        std::istringstream iss(line);
        if (iss >> word) {
            out << reversed(word);
            while (iss >> word) {
                out << " " << reversed(word);
            }
        }
        out << std::endl;
    }

    return 0;
}

Live Demo

答案 1 :(得分:0)

我想有很多可能的解决方案。我将向您展示一段代码,该代码大量使用了std库,因此仅用几行代码就结束了。有趣的工作将仅在main函数中的3条代码语句中完成。不需要像dowhilefor之类的循环结构或其他控制结构。

这更像是现代C ++风格。

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

struct WordsInLine  // The words in one line + proxy for output iterator
{
    std::vector<std::string> wordsInLine;   // Container for words in one line

    friend std::ostream& operator<< (std::ostream& os, const WordsInLine& w) { 
        std::copy(
            w.wordsInLine.begin(), w.wordsInLine.end(),
            std::ostream_iterator<std::string>{os, " "}); 
        return os; 
    }
};

// Make reading easier
using AllLines = std::vector<WordsInLine>;

struct Line      // ! This is a proxy for the input_iterator ! 
{   // Input function. Read on line of text file and split it
    friend std::istream& operator>>(std::istream& is, Line& line) { 
        std::string wholeLine;
        std::regex space("[ \\.\\,]");
        line.words.wordsInLine.clear();
        std::getline(is, wholeLine);    // Read one complete line and split it into parts
        std::copy(
            std::sregex_token_iterator(wholeLine.begin(), wholeLine.end(), space, -1),
            std::sregex_token_iterator(),
            std::back_inserter(line.words.wordsInLine)
        );
        return is;
    }

    operator WordsInLine() const { return words; }  // cast to needed result
    WordsInLine words;  // Local storage for all words in line
};

int main()
{
    std::ifstream inFileStream{ "r:\\input.txt" };      // Open input file. Will be closed by destructor
    std::ofstream outFileStream{ "r:\\output.txt" };    // Open output file. Will be closed by destructor

    // 1. Read complete input file into memory and organize it in words by lines
    AllLines allLines{ std::istream_iterator<Line>(inFileStream), std::istream_iterator<Line>() };

    // 2. For all lines: Reverse all words in a line
    std::for_each(
        allLines.begin(), allLines.end(),
        [](WordsInLine& w) {
            std::for_each(
                w.wordsInLine.begin(), w.wordsInLine.end(),
                [](std::string& s) { std::reverse(s.begin(), s.end()); }
            );
        }
    );

    // 3. Output result to file
    std::copy(
        allLines.begin(), allLines.end(),
        std::ostream_iterator<WordsInLine>{outFileStream, "\n"}
    );

    return 0;
}

我将代理用于输入和输出迭代器。输入迭代器还解析行并提取所有单词。请注意:使用正则表达式时,我还会删除“。”。和“,”(在解析的单词中)。

反向操作是通过嵌套的std::for_each()和嵌套的lambda来实现的。

希望这会有所帮助。

答案 2 :(得分:0)

避免使用正则表达式的替代解决方案可以简单地反转每个单词(如果需要,class BlockchainUT : DescribeSpec({ var blockchain = Blockchain() @BeforeEach fun beforeEach() { blockchain = Blockchain() blockchain.addBlock(listOf("foo1", "bar1")) blockchain.addBlock(listOf("foo2", "bar2")) blockchain.addBlock(listOf("foo3", "bar3")) } describe("isValidChain()") { context("when the chain does not start with the genesis block") { blockchain.chain[0] = Block( System.currentTimeMillis(), "---", "xxx", listOf("foo", "bar")) it("returns false") { Blockchain.isValid(blockchain) shouldBe false } } context("when the chain starts with the genesis block and has multiple blocks") { context("and a lastHash reference has changed returns false") { blockchain.chain[2] = Block( blockchain.chain[2].timestamp, "broken-lastHash", blockchain.chain[2].hash, blockchain.chain[2].data) it("returns false") { Blockchain.isValid(blockchain) shouldBe false } } context("and the chain contains a block with an invalid field") { blockchain.chain[2] = Block( blockchain.chain[2].timestamp, blockchain.chain[2].lastHash, blockchain.chain[2].hash, listOf("some-bad-and-evil-data")) it("returns false") { Blockchain.isValid(blockchain) shouldBe false } } } } }) 包含标点符号列表和.find_first_of()从该位置开始)。一种相当简单的方法是使用.erase()读取每一行,然后从该行创建一个getline,然后从stringstream中读取每个单词,然后输出到您的输出文件。可以使用一个简单的标志来控制每个单词之间的空格添加。

不删除标点符号的简短实现可能是:

stringstream

示例输入文件

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

std::string reverse (const std::string& s)
{
    return std::string (s.rbegin(), s.rend());
}

int main (int argc, char **argv)
{
    std::string line;   /* string to hold each line */

    if (argc < 3) {     /* validate 2 arguments given */
        std::cerr << "error: insufficient input.\nusage: ifile ofile\n";
        return 1;
    }

    std::ifstream ifs {argv[1]};        /* open input file */
    std::ofstream ofs {argv[2]};        /* open output file */

    while (getline (ifs, line)) {       /* read each line */
        std::istringstream ss {line};   /* create stringstream from line */
        std::string word;               /* string to hold word */
        size_t wc = 0;                  /* flag to control space output */
        while (ss >> word)              /* read each word */
            ofs << (wc++ ? " " : "") << reverse (word); /* output rev'ed */
        ofs << '\n';    /* tidy up with newline */
    }
}

示例用法

$ cat ../dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

示例输出文件

$ ./bin/words_reverse ../dat/captnjack.txt ../dat/captnjack_rev.txt

根据您的输入/输出信息进行编辑

如果要删除单词末尾的标点符号,可以使用$ cat ../dat/captnjack_rev.txt sihT si a elat fO niatpaC kcaJ worrapS A etariP oS evarB nO eht neveS .saeS .find_first_of()来删除。由于您现在将标点符号移到找到该单词的末尾,因此您需要先从该单词.erase()将该字符保存下来。然后,您可以在单词后面添加它。通过删除标点符号并将其移到单词的末尾,您可以执行以下操作:

.erase()

示例输入文件

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

std::string reverse (const std::string& s)
{
    return std::string (s.rbegin(), s.rend());
}

int main (int argc, char **argv)
{
    std::string line;   /* string to hold each line */
    const std::string rmchars {".,!?"}; /* punctuation to remove */

    if (argc < 3) {     /* validate 2 arguments given */
        std::cerr << "error: insufficient input.\nusage: ifile ofile\n";
        return 1;
    }

    std::ifstream ifs {argv[1]};        /* open input file */
    std::ofstream ofs {argv[2]};        /* open output file */

    while (getline (ifs, line)) {       /* read each line */
        std::istringstream ss {line};   /* create stringstream from line */
        std::string word;               /* string to hold word */
        size_t wc = 0;                  /* flag to control space output */
        while (ss >> word) {            /* read each word */
            size_t rmpos = word.find_first_of (rmchars);  /* index or npos */
            char punc = 0;              /* char to hold punctuation */
            if (rmpos != std::string::npos) { /* if not npos */
                punc = word[rmpos];     /* save punctuation char */
                word.erase (rmpos);     /* erase punctuation */
            }
            ofs << (wc++ ? " " : "") << reverse (word); /* output rev'ed */
            if (punc)
                ofs << (char)punc;      /* output punctuation char */
        }
        ofs << '\n';                    /* tidy up with newline */
    }
}

示例用法

$ cat dat/sentences.txt
Expecting the world to treat you
fairly because you are a good person
is a little like expecting the bull not to
attack you because you are a vegetarian.

示例输出文件

$ ./bin/words_reverse_w_punc dat/sentences.txt dat/sentences_rev.txt

有很多方法可以解决此问题。您可以根据需要使它变得简单或复杂。