【问题标题】:Nested while loop with file c++ issues带有文件c ++问题的嵌套while循环
【发布时间】:2015-07-04 23:07:20
【问题描述】:

我必须创建一个程序,该程序接受 A 组文件中的字符串并将它们与 B 组的字符串进行比较,创建一个视频输出和与输出视频文件相等的结果。组文件的结构如下:Jhon Smith'\n'Fergus McDonald'\n'Elizabeth Harris'\n'。我有嵌套while循环的问题,最后一个检查A的名称是否等于B的名称似乎有效,但其他两个不是,第一次内部循环有效,但另一个无效,if条件似乎没有更多的工作,并在文件元素的数量中重复所有文件的名称,反之亦然,对于第二组嵌套的 while 循环,我不明白出了什么问题

#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <fstream>

using namespace std;

int main() {
    string As, Bs, Cs;
    ifstream A("Group_A.txt");
    ifstream B("Group_B.txt");
    ofstream C("Result.txt");

    if(!A)
    {
        cout<<"Group A does not exist!";
        return -1;
    }
    if(!B)
    {
        cout<<"Group B does not exist!!";
        return -1;
    }
    if(!C)
    {
        cout<<"Failed to create file!!";
        return -1;
    }

    C<<"Elements in A but not in B:"<<endl;
    while(getline (B,Bs))
    { 
      while(getline (A,As))
      { 
        if (As != Bs)
        {
            C<<As<<endl;
        }
      }
      A.clear();
      A.seekg(0);
    }
    A.close();
    B.close();
    C<<endl;

    A.open("Group_A.txt");
    B.open("Group_B.txt");
    C<<"Elements in B but not in A:"<<endl;
    while(getline (A,As))
    {
      while(getline (B,Bs))
      { 
        if (Bs != As)
        {
            C<<Bs<<endl;
        } 
      }
      B.clear();
      B.seekg(0);
    }
    A.close();
    B.close();
    C<<endl;

    A.open("Group_A.txt");
    B.open("Group_B.txt");
    C<<"Elements present in both A and B:"<<endl;
    while(getline (A,As))
    {
      while(getline (B,Bs))
      { 
        if (As == Bs)
        {
            C<<Bs<<endl;
        } 
      }
      B.clear();
      B.seekg(0);
    }

    A.close();
    B.close();
    C<<endl;
    C.close();

    ifstream res("Result.txt");
    while(res >> Cs)
    cout<<Cs<<endl;

     system ("PAUSE");
      return 0;
}

【问题讨论】:

  • 什么是视频输出?
  • 您应该使用比ABC 更具描述性的名称。
  • A 组文件字符串:Mario Franceschi Luigi Deluca Anita Sola B 组文件字符串:Mario Franceschi Enrico Santini Anita In Compagnia 输出视频:A 中的元素但 B 中没有元素:Luigi Deluca Anita Sola Mario Franceschi Luigi Deluca Anita Sola 马里奥弗朗切斯基 Luigi Deluca Anita Sola B 中的元素,但 A 中没有的元素:Enrico Santini Anita 在 Compagnia Mario Franceschi Enrico Santini Anita 在 Compagnia Mario Franceschi Enrico Santini Anita 在 Compagnia A 和 B 中都存在元素:Mario Franceschi
  • @Carcigenicate A 和 B 是要比较的组,C 是输出文件
  • Carcigenicate 的观点是没有必要有那个映射。 A、B 和 C 可以是输入 A、输入 B 和输出。不是世界上最好的名字,但至少读者可以一眼看出你想要做什么。您是否需要这些循环,如程序规范所要求的那样,还是可以用更有效的结构替换它们?

标签: c++ string file while-loop fstream


【解决方案1】:
// write a function that load your file
template <class Itr>
void read_file(std::string const& name, Itr to) {
    std::ifstream in(name);
    for (std::string line; std::getline(in, line); *itr++ = std::move(line));
}

// load your files
std::set<std::string> a;
read_file("a.txt", std::inserter(a));
std::set<std::string> b;
read_file("b.txt", std::inserter(b));

// based on what you need use one of set algorithms
// from the standard library
// I assumeed you need the union of the two in the below code
std::vector<std::string> c;
std::set_union(a.begin(), a.end(), b.begin, b.end(), std::back_inserter(c));

// dump the result
std::ofstream out("c.txt");
std::copy(c.begin(), c.end(), std::ostream_iterator(out, "\n"));

【讨论】:

  • 正确的想法,但是您应该添加一些注释来解释为什么要丢弃所有 OP 的代码:消除冗余、重复的文件 IO 并使用已经实现所需功能的库函数。还值得指出的是,这只是联合,但排除是相似的。
  • @user4581301 - +1,很高兴在你的评论中做到了:)
【解决方案2】:

问题:

foreach B in file B
    foreach A in file A
        if (A != B)
            output A 

假设文件 A 包含 1,2,3,文件 B 包含 2,3,4

测试将如下所示:

2 != 1: true, output 1
2 != 2: false, no output
2 != 3: true, output 3
3 != 1: true, output 1
3 != 2: true, output 2
3 != 3: false, no output
4 != 1: true, output 1
4 != 2: true, output 2
4 != 3: true, output 3

输出文件将包含 1,3,1,2,1,2,3

您要做的是构建文件 A 和 B 的集合交集(我们称之为 AnB)。这给了你第三个循环。 A 和 B 中的所有内容。

比较 AnB 和 A。因此,A 中而不是 AnB 中的所有内容都不能在 B 中。在 A 中而不是 B 中。对 B 重复

或者你也可以打电话给std::set_intersectionstd::set_difference

#include <iostream>
#include <fstream>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

// Not elegant, but it's pretty much what the OP was using
// and this isn't a question about proper file handling.
// Optimize as needed
bool readFile(const string &filename, set<string> &lines)
{
    ifstream input(filename.c_str());

    if (!input) // this will fail in a few cases
    {
        cout << "Group A does not exist!" << endl;
        return false;
    }

    string line;

    while (getline(input, line))
    {
        lines.insert(line);
    }
    return true;
}

void writeFile (ofstream & out,
                std::vector<string> & data,
                std::vector<string>::iterator stop,
                const std::string &message)
{
    // resizing the vectors the their actual used size makes output easy.
    data.resize(stop - data.begin());
    out << message << endl;
    for (std::vector<string>::iterator it = data.begin(); it != data.end(); ++it)
    {
        out << *it << endl;
    }
}

int main()
{
    set<string> Group_A;
    set<string> Group_B;
    ofstream Result("Result.txt");

    readFile("Group_A.txt", Group_A);
    readFile("Group_B.txt", Group_B);

    // Danger! Danger! Blows up if you do not preallocate
    // enough storage in vectors! Sized for worst case
    std::vector<string> AnB(Group_A.size() + Group_B.size());
    // really this should just be size of the larger list, but I'm lazy
    std::vector<string> AnotB(Group_A.size()); //sized for no intersection
    std::vector<string> BnotA(Group_B.size()); //sized for no intersection

    // use this to catch the true vector size after the std::set_* calls
    std::vector<string>::iterator stop;

    stop = std::set_intersection(Group_A.begin(), Group_A.end(),
                                 Group_B.begin(), Group_B.end(),
                                 AnB.begin());
    writeFile (Result, AnB, stop, "Intersection:");

    stop = std::set_difference(Group_A.begin(), Group_A.end(),
                               Group_B.begin(), Group_B.end(),
                               AnotB.begin());
    writeFile (Result, AnotB, stop, "A not B:");

    // note the exchange of A and B on the std::set_difference call
    stop = std::set_difference(Group_B.begin(), Group_B.end(),
                               Group_A.begin(), Group_A.end(),
                               BnotA.begin());
    writeFile (Result, BnotA, stop, "B not A:");
}

【讨论】:

    猜你喜欢
    • 2016-06-06
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 2021-08-21
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    相关资源
    最近更新 更多