Folks,
Most of you can see what the below segment of code is doing, the problem I have is that the program is skipping the next line in the source file (airportsMaster) after it has processed a successful match.

Is the problem because I am using getline twice or that my ignore length is wrong?

while ( !airportsMaster.eof())
    {
        airportsMaster.getline(icaoChr, 5,',');
        for ( int i=0; i<(numAirports); i++ )
        {
            if (icaoChr == icaoStr[i])
            {
                airportsList << icaoStr[i] << ",";
                airportsMaster.getline(tempChr, 35,'\n');
                airportsList << tempChr << "\n";
            }
        }
        airportsMaster.ignore(35, '\n');
    }

The source file (a simple .txt file) contains 26000+ lines in format like below ...

SKTM,N6* 27.18',W71* 45.69',1050
SKTQ,N0* 43.60',W75* 12.92',597
SKTU,N8* 3.98',W76* 44.88',7
SKUA,N5* 28.41',W68* 41.13',285

as you can see the length varies between 29-34 char.

Dani AI

Generated

The skipping comes from reading the same line twice: once to pull the remainder into a buffer, then again with ignore()—so the stream advances past the next newline. As and hinted, only consume the line once. ’s later approach (reading the whole line and searching it) is the right direction; below is a slightly cleaner, safer pattern that avoids fixed-size char buffers and the while(!eof()) anti-pattern.

Use std::getline into std::string, extract the ICAO token up to the comma, then test membership against a prebuilt set of wanted codes. This handles variable line length, avoids manual ignore() calls, and is both clear and fast for 26k lines.

Example pattern:

#include <fstream>
#include <string>
#include <unordered_set>

std::unordered_set<std::string> wanted = /* populate from icaoStr array */;
std::ifstream in("airportsMaster.txt");
std::ofstream out("airportsList.txt");
std::string line;

while (std::getline(in, line)) {
    auto pos = line.find(',');
    if (pos == std::string::npos) continue; // malformed line
    std::string icao = line.substr(0, pos);
    if (wanted.count(icao)) out << line << '\n';
}

Other practical notes: do not use while(!file.eof())—use std::getline return value to drive the loop. Prefer std::string over fixed char arrays to avoid truncation and buffer overrun. If you ever need to discard the remainder of a long line, use in.ignore(std::numeric_limits<std::streamsize>::max(), '\n'). For large lookups, std::unordered_set gives O(1) average-time checks; for small lists a linear search is fine. For reference, see std::getline and std::unordered_set on cppreference: getline and unordered_set.

Recommended Answers

All 5 Replies

Think of it this way:

This fills tempChr with data up until a newline is reached, however it also trashes the newline that follows.

airportsMaster.getline(tempChr, 35,'\n');

Now this trashes another whole line (or 35 chars, whatever comes first):

airportsMaster.ignore(35, '\n');

So of course it's going to skip some lines.

while ( !airportsMaster.eof())
{
    airportsMaster.getline(icaoChr, 5,',');
    for ( int i=0; i<(numAirports); i++ )
    {
        if (icaoChr == icaoStr[i])
        {
        airportsList << icaoStr[i] << ",";
        airportsMaster.getline(tempChr, 35,'\n');
        airportsList << tempChr << "\n";
        }
    }
    airportsMaster.ignore(35, '\n');
}

You have already extracted teh '\n' on line 10. It really isn't THAT obvious what the code is doing, but my guess is that line 13 should be in an else of the if inside for loop.

Think of it this way:

This fills tempChr with data up until a newline is reached, however it also trashes the newline that follows.

airportsMaster.getline(tempChr, 35,'\n');

Now this trashes another whole line (or 35 chars, whatever comes first):

airportsMaster.ignore(35, '\n');

So of course it's going to skip some lines.

Joe,
Because my source lines are variable lenght I don't know what else to use as a terminting character? Are you suggesting i find lenght of the line and then just getline the characters I need?
The reason I have the ignore statement is to advance my source file to the next line, is there another way of doing this without flushing out the istream buffer? (in my eronous case a second time)

Rod

You flush the line when you use that second getline() statement. Using ignore() flushes it again, skipping a line.

So... do what kashyap suggested. Create an else statement, so that ignore() only executes when the stream hasn't already been cleared.

Joe & thekashyap - thanks so much for your help.

To be honest I missed the 'else' suggestion; in the meantime in an effort to figure out how to step through the source file without using ignore I decided to take a completely different approach which works, and is tighter code ...

while ( !airportsMaster.eof())
    {
        airportsMaster.getline(tempChr, 35,'\n');
        tempStr = tempChr;
        for ( int i=0; i<(numAirports-1); i++ )
        {
            found=tempStr.find(icaoStr[i]);
            if (found!=string::npos)
            {
                airportsList << tempChr << "\n";
            }
        }
    }

I am going to go now and read up on and play with various stream handling fundamentals. Thanks again for your help.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.