HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Iterate over a file multiple times

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
fileiteratemultipletimesover

Problem

Aim of the code is to print all of the strings from one file that match strings from another file. Names of both of the files are provided by command line arguments.

Code:

int main(int argc, char *argv[]){    
    ifstream answers(argv[1]);
    ifstream candidates(argv[2]);

    for (string s; getline(answers,s);){
        for (string h; getline(candidates,h);){
            if (!s.compare(h)){
                cout << h << ":" << s << endl;
            }
        }
        candidates.close();                 //I know theres better than this
        candidates.open(argv[2], ios::in); 
    }
}


but I feel like reloading the file into memory every time is redundant. Is there anything that could be improved?

Solution

Slightly better way:

candidates.close();                 //I know theres better than this


If improvement is based on this statement, then something like stringstream would be good fit.

Best way:

std::map will fit the job nicely. After you've done with it, just iterate through and see if anything has counter equal to 2 or higher, and print those.

Roughly this:

std::map appearance_count;
while (std::getline(answers, s)) 
{
    ++appearance_count[s];
}
while (std::getline(candidates, s)) 
{
    ++appearance_count[s];
}

for (const auto& reading: appearance_count)
{
    if (reading.second > 1)
    {
        std::cout << reading.first << '\n';
    }
}


Some edge cases:

There might be duplications in the first file, so it will require first adding into std::set, then adding to the map. Second file is unaffected by that, since any string with appearance count larger than 1 is already wanted. Though if the second file contains duplicates as well, you'll need two sets.

Code Snippets

candidates.close();                 //I know theres better than this
std::map<std::string, std::size_t> appearance_count;
while (std::getline(answers, s)) 
{
    ++appearance_count[s];
}
while (std::getline(candidates, s)) 
{
    ++appearance_count[s];
}

for (const auto& reading: appearance_count)
{
    if (reading.second > 1)
    {
        std::cout << reading.first << '\n';
    }
}

Context

StackExchange Code Review Q#156712, answer score: 2

Revisions (0)

No revisions yet.