Merging Two Files using C++

Discussion in 'C++' started by ckoniecny@gmail.com, Sep 23, 2006.

  1. Guest

    I have the following two files:
    File1:
    11 John Doe
    33 Jane Doe
    55 Steve Smith

    File2:
    22 Joe Doe
    44 Willy Widget

    I'm trying to merge the two files to look like:

    Output:
    11 John Doe
    22 Joe doe
    33 Jane Doe
    44 Willy Widget
    55 Steve Smith

    Note: I cannot use array's to sort.

    This is the code I have thus far:

    Code:
    #include <iostream>
    #include <fstream>
    #include <string>

    using namespace std;

    int main()
    {
    ifstream File1, File2;
    string File1_FirstName, File1_LastName;
    string File2_FirstName, File2_LastName;
    int File1_num, File2_num, NumberOne, NumberTwo;
    ofstream outFile;

    File1.open("File1.txt", ios::in);
    File2.open("File2.txt", ios::in);

    outFile.open("Output.txt", ios::eek:ut);



    while (!File2.eof())
    {
    File1 >> File1_num >> File1_FirstName >> File1_LastName;
    NumberOne = File1_num;

    File2 >> File2_num >> File2_FirstName >> File2_LastName;
    while (!File1.eof())
    {
    File1 >> File1_num >> File1_FirstName >> File1_LastName;
    NumberTwo = File1_num;

    if ( NumberOne > File2_num < NumberTwo )
    {
    outFile << NumberOne << '\t'
    << FirstName << '\t'
    << LastName << '\n';
    }
    }
    }
    return 0;
    }
    My output is not what I expected, I'm having logic issues. Can anyone
    point me in the correct direction?
     
    , Sep 23, 2006
    #1
    1. Advertising

  2. Jerry Coffin Guest

    In article <>,
    says...
    > I have the following two files:
    > File1:
    > 11 John Doe
    > 33 Jane Doe
    > 55 Steve Smith
    >
    > File2:
    > 22 Joe Doe
    > 44 Willy Widget
    >
    > I'm trying to merge the two files to look like:
    >
    > Output:
    > 11 John Doe
    > 22 Joe doe
    > 33 Jane Doe
    > 44 Willy Widget
    > 55 Steve Smith


    I'd define a class that holds the data and defines operator< to sort the
    data in the desired fashion (you haven't described what should happen
    if, for example, the same number appears with two different names).

    From there, you can directly merge from input files to an output file if
    the input files are guaranteed to be sorted, as you've shown them here.
    Otherwise, you can copy from the input files to a sorted container (e.g.
    set or multiset, depending on whether duplicate keys are allowed) and
    then merge from there to the output.

    I'm not sure why can _can't_ use arrays (as you mentioned in a snipped
    portion of your post) but I'd certainly consider it ill-advised.

    As far as the code you have goes, something like this:
    while (!File2.eof())
    {
    File1 >> File1_num >> File1_FirstName >> File1_LastName;

    is essentially certain to be incorrect, and normally needs to be
    rewritten to something like:

    while (file1>>input1>>input2>>input3>>inputN)
    // whatever

    The important point is that you need to check for a problem with reading
    the input file AS you read it -- file.eof() only becomes true AFTER
    you've reached the end of the file, so your loop attempts to read the
    last data in the file twice. I'd forget about using explicit loops,
    however, and just use an std::istream_iterator to read the input.

    Your code also has a problem in that each iteration through the loop
    reads input from each file, but only writes an output from one file --
    and discards the input it read from the other file. Each iteration
    should read only ONE input, to replace the one just written out.

    As previously noted, however, I'd use std::merge() for this job -- it's
    written specifically for tasks like this, and does them quite nicely.

    class record {
    int number;
    std::string first_name, last_name;
    public:
    friend
    std::istream &operator>>(std::istream &in, record &r) {
    return in >> r.number >> r.first_name >> r.last_name;
    }

    friend std::eek:stream &operator<<(std::eek:stream &os, record const &r) {
    return os << r.number << "\t"
    << r.first_name << "\t"
    << r.last_name;
    }

    bool operator<(record const &other) const {
    return number < other.number;
    }
    };


    // ...
    std::merge(
    std::istream_iterator<record>(infile1),
    std::istream_iterator<record>(),
    std::istream_iterator<record>(infile2),
    std::istream_iterator<record>(),
    std::eek:stream_iterator<record>(outfile, "\n"));

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Sep 23, 2006
    #2
    1. Advertising

  3. Guest

    Thats a little bit above my level. Is there anyway I can email you
    what I have so you can see my actual program?

    Jerry Coffin wrote:
    > In article <>,
    > says...
    > > I have the following two files:
    > > File1:
    > > 11 John Doe
    > > 33 Jane Doe
    > > 55 Steve Smith
    > >
    > > File2:
    > > 22 Joe Doe
    > > 44 Willy Widget
    > >
    > > I'm trying to merge the two files to look like:
    > >
    > > Output:
    > > 11 John Doe
    > > 22 Joe doe
    > > 33 Jane Doe
    > > 44 Willy Widget
    > > 55 Steve Smith

    >
    > I'd define a class that holds the data and defines operator< to sort the
    > data in the desired fashion (you haven't described what should happen
    > if, for example, the same number appears with two different names).
    >
    > From there, you can directly merge from input files to an output file if
    > the input files are guaranteed to be sorted, as you've shown them here.
    > Otherwise, you can copy from the input files to a sorted container (e.g.
    > set or multiset, depending on whether duplicate keys are allowed) and
    > then merge from there to the output.
    >
    > I'm not sure why can _can't_ use arrays (as you mentioned in a snipped
    > portion of your post) but I'd certainly consider it ill-advised.
    >
    > As far as the code you have goes, something like this:
    > while (!File2.eof())
    > {
    > File1 >> File1_num >> File1_FirstName >> File1_LastName;
    >
    > is essentially certain to be incorrect, and normally needs to be
    > rewritten to something like:
    >
    > while (file1>>input1>>input2>>input3>>inputN)
    > // whatever
    >
    > The important point is that you need to check for a problem with reading
    > the input file AS you read it -- file.eof() only becomes true AFTER
    > you've reached the end of the file, so your loop attempts to read the
    > last data in the file twice. I'd forget about using explicit loops,
    > however, and just use an std::istream_iterator to read the input.
    >
    > Your code also has a problem in that each iteration through the loop
    > reads input from each file, but only writes an output from one file --
    > and discards the input it read from the other file. Each iteration
    > should read only ONE input, to replace the one just written out.
    >
    > As previously noted, however, I'd use std::merge() for this job -- it's
    > written specifically for tasks like this, and does them quite nicely.
    >
    > class record {
    > int number;
    > std::string first_name, last_name;
    > public:
    > friend
    > std::istream &operator>>(std::istream &in, record &r) {
    > return in >> r.number >> r.first_name >> r.last_name;
    > }
    >
    > friend std::eek:stream &operator<<(std::eek:stream &os, record const &r) {
    > return os << r.number << "\t"
    > << r.first_name << "\t"
    > << r.last_name;
    > }
    >
    > bool operator<(record const &other) const {
    > return number < other.number;
    > }
    > };
    >
    >
    > // ...
    > std::merge(
    > std::istream_iterator<record>(infile1),
    > std::istream_iterator<record>(),
    > std::istream_iterator<record>(infile2),
    > std::istream_iterator<record>(),
    > std::eek:stream_iterator<record>(outfile, "\n"));
    >
    > --
    > Later,
    > Jerry.
    >
    > The universe is a figment of its own imagination.
     
    , Sep 23, 2006
    #3
  4. Jerry Coffin Guest

    In article <>,
    says...
    > Thats a little bit above my level. Is there anyway I can email you
    > what I have so you can see my actual program?


    I do have email of course, but if you want help, it's generally better
    to post here. That way 1) other people can chip in, and 2) other people
    can learn from the discussion.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Sep 23, 2006
    #4
  5. Guest

    This is what I have so far and its still not working.... Any hints?

    #include <iostream>
    #include <fstream>

    using namespace std;

    int main()
    {
    ifstream File1;
    ifstream File2;
    ofstream outFile;

    string File1_fName, File1_lName;
    string File2_fName, File2_lName;
    int File1_acctNum, File2_acctNum;

    File1.open("file1", ios::in);
    File2.open("file2", ios::in);
    outFile.open("out.txt", ios::eek:ut);

    File1 >> File1_acctNum >> File1_fName >> File1_lName;
    File2 >> File2_acctNum >> File2_fName >> File2_lName;
    while (!File1.eof() && !File2.eof())
    {
    if (File2_acctNum > File1_acctNum)
    {
    outFile << File1_acctNum << '\t' << File1_fName
    << '\t'
    << File1_lName << " *\n";
    outFile << File2_acctNum << '\t' << File2_fName
    << '\t'
    << File2_lName << " *\n";
    File1 >> File1_acctNum >> File1_fName >>
    File1_lName;
    File2 >> File2_acctNum >> File2_fName >>
    File2_lName;
    cout << File2_acctNum << "\t" << File2_fName <<
    "\t" << File2_lName << endl;
    }
    else if (File1.eof())
    {
    while (!File2.eof())
    {
    outFile << File2_acctNum << '\t' <<
    File2_fName << '\t'
    << File2_lName << '\n';
    }
    }
    else if (File2.eof())
    {
    while(!File1.eof())
    {
    outFile << File1_acctNum << '\t' <<
    File1_fName << '\t'
    << File1_lName << '\n';
    }
    }

    }
    return 0;
    }
     
    , Sep 24, 2006
    #5
  6. Jerry Coffin Guest

    In article <>,
    says...
    > This is what I have so far and its still not working.... Any hints?


    Not any new ones, really.

    > while (!File1.eof() && !File2.eof())


    As already noted, code like this is almost always wrong. You want to
    check for EOF _as_ you read the data.

    I'd also split things up into a couple of functions, such as
    "copy_remainder" (or something like that) to copy the remainder of a
    file to the output.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Sep 24, 2006
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Stefan Franke

    merging two XML files

    Stefan Franke, Jan 4, 2005, in forum: XML
    Replies:
    5
    Views:
    782
    Joris Gillis
    Jan 4, 2005
  2. n o s p a m p l e a s e

    Merging two DLL files

    n o s p a m p l e a s e, Jun 18, 2007, in forum: C Programming
    Replies:
    10
    Views:
    1,289
    CBFalconer
    Jun 19, 2007
  3. triangle
    Replies:
    1
    Views:
    119
    Gunnar Hjalmarsson
    Jan 30, 2004
  4. Replies:
    8
    Views:
    201
  5. Vahid

    merging two files

    Vahid, Jun 5, 2007, in forum: Perl Misc
    Replies:
    2
    Views:
    125
    J. Gleixner
    Jun 5, 2007
Loading...

Share This Page