andrepd
andrepd

Reputation: 607

Read two files from stdio

I want to read from two files, one containing floats in three columns, and another containing ints in two columns. I have the following code to read from stdin:

int main() {
    while (scanf("%lf %lf %lf\n",&x,&y,&z) != EOF) {
        // do stuff
    }

    puts("foo");

    int a,b;
    while (scanf("%d %d\n",&a,&b) != EOF) {
        puts("bar");
    }
}

Then I call the program with cat ortho.dat pairs.dat | ./angles, ortho.dat and pairs.dat being the two files. However the output is just foo indicating that the second file is never read, presumably because it reads EOF and immediately terminates the second loop. Is this correct?

How could I read the two files, without actually opening them in the program, merely reading them from stdin?

Upvotes: 0

Views: 94

Answers (3)

R Sahu
R Sahu

Reputation: 206577

Question:

How could I read the two files, without actually opening them in the program, merely reading them from stdin?

One solution:

Insert dummy, invalid, content between the contents of two files. Use it to separate the data from the first file and the second file.

Contents of file "dummy":

===Separator===

Change your code to:

int main() {
    while (scanf("%lf %lf %lf\n",&x,&y,&z) == 3) {
        // do stuff
    }

    // Skip the line that contains the separator.
    scanf("%*[^\n]");

    puts("foo");

    int a,b;
    while (scanf("%d %d\n",&a,&b) == 2) {
        puts("bar");
    }
}

Change the invocation:

cat ortho.dat dummy pairs.dat | ./angles

Update

A C++ version:

int main() {
    while ( std::cin >> x >> y >> z ) {
        // do stuff
    }

    // Skip the line that contains the separator.
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    puts("foo");

    int a,b;
    while ( std::cin >> a >> b ) {
        puts("bar");
    }
}

Upvotes: 3

You can't do that reliably. Read about fscanf(3) (it handles every space-like character the same, including newlines). BTW, you'll better test that scanf returns the actual count (e.g. 3 for the first case, 2 for the second one).

However, you might have more constraints on the input. Perhaps the three doubles and the two integers are always on a single same line, e.g. ortho.dat containing lines like

1.0 2.0 3.0

and pairs.dat containing lines like

23 45

then you could read every line using getline(3) (or perhaps fgets) and use sscanf to parse it (and you would use its return count to separate the lines with 3 floating points from the lines with 2 integers). The %n control format could perhaps be handy (it gives the current cursor position).

However, I would instead suggest to pass the two file names ortho.dat & pairs.dat as distinct arguments (i.e. use the conventional argc & argv arguments to main(int argc, char**argv))

Upvotes: 2

fukanchik
fukanchik

Reputation: 2865

When you do "cat F1 F2 | program", cat will concatenate the files and the program will receive single continuous stream of data.

From the point of view of the program it is impossible to find where one file ends and second begins unless some marker inserted into the files.

For example, you can insert a single line after the first file saying: FILE1ENDS Then, if such a line would never be found in the file itself you can use that to terminate your first loop.

As an alternative pass file names as arguments to your program and open/read/close them yourself.

Upvotes: 2

Related Questions