opening multiple files using freopen in c++ - c++

I'm trying to use freopen() multiple times to read and close different files.
So here's what I did inside my main function:
if (argc != 5) {
std::cerr << "Wrong format of arguments given." << endl;
return -1;
}
std::string command, command2;
freopen(argv[1], "r", stdin);
// do something...
fclose(stdin);
freopen(argv[2], "r", stdin);
freopen(argv[3], "w", stdout);
while (std::cin >> command) {
std::cin >> command2;
// run some function...
}
fclose(stdin);
fclose(stdout);
But it turns out that the first part, // do something..., works fine (reads from std::cin without a problem) but the while loop in the second doesn't seem to run.
The input files are of correct formats, so I don't know why std::cin >> command returns false.

In line freopen(argv[2], "r", stdin); you are trying to reopen stdin. But you have already closed stdin in line fclose(stdin); just before that. Also, stdin is now dangling pointer after closing the file.
Following is an extract from www.cplusplus.com:
If a new filename is specified, the function first attempts to close any file already associated with stream (third parameter) and disassociates it. Then, independently of whether that stream was successfuly closed or not, freopen opens the file specified by filename and associates it with the stream just as fopen would do using the specified mode.
You should use fopen() function after closing stdin.

Related

Reading user input after reading a file from stdin

I have a program that I start from a command line with a file pushed to stdin:
main.exe < file.bin
I read all the contents from the file like so:
freopen(NULL, "rb", stdin); // it's a binary file
long* buffer = new long[16000];
while ( fread(buffer, sizeof(long), 16000, stdin) == 16000);
After all numbers are read, I would like the user to confirm continuation in the program by pressing any key but at that point stdin probably contains EOF and the program skips the confirmation from the user.
printf("Press any key to continue");
getchar(); // user doesn't get a chance to press anything, program flows right through
Here's the whole program if you want to reproduce it. But to reproduce you have to push a file to stdin before execution.
#include <stdio.h>
int main()
{
freopen(NULL, "rb", stdin);
long* buffer = new long[16000];
while ( fread(buffer, sizeof(long), 16000, stdin) == 16000);
printf("Press any key to continue");
getchar();
delete[] buffer;
return 0;
}
The question is how to make the getchar() call take an character from the user's keyboard and not the file that was already read.
The program runs as C++17 but uses a lot of C style code. If you know a way how to do this with C++ streams feel free to post that as well. I use Windows 10 but I would also like to see some portable code.
If you use a file file.bin as a stdin via main.exe < file.bin, you cannot simultaneously use console as a stdin using standard C or C++ libraries. Maybe you could try it with WinAPI https://learn.microsoft.com/en-us/windows/console/readconsoleinput
And using std::cin to read binary data is unfortulately not possible: Read binary data from std::cin

Can cout be associated with anything other than monitor?

'cout is an output stream object that is attached to the process's standard output device,often to the terminal from which the program is run'-my book says so.Just curious about the following:
Is there any case where cout is made to be attached to any other output devices such as may be printer?Or it is like cout refers to monitor and cin to keyboard all the time.
cin is the standard input, and while most systems get their input from the keyboard it is not necessary. cout is standard output, most systems again have stdout (standard output) set to console. But you can redirect it.
For instance to file:
std::ofstream file;
file.open ("test.txt"); // open file
std::streambuf *orig_out = std::cout.rdbuf(); // save cout
std::streambuf *buf = file.rdbuf(); // get file's streambuf
std::cout.rdbuf(buf); // redirect cout to file
std::cout << "This is written to the file";
std::cout.rdbuf(orig_out); // restore cout's original output
file.close(); // close file
Short answer is "yes". Cout is just an output stream. In unix you can create a pipeline
command1 | command2
Command 1's stdout goes to command 2's stdin - i.e. not monitor and keyboard.
stdout (and thus cout) can also be redirected:
command > some_file_or_device.
Yes.
cin and cout are iostreams, they are standard but they are normal too, i.e. you can close stdin and stdout and reopen some other device as the stdin or out.

C++ Read/write file on Unix

I know this is a very specific question. I am compiling a c++ code using g++ compiler on a unix machine.
I have the following one line code to read a text file specified as parameter in C++: test.cc
int main(int argc, char *argv[])
{
ifstream inputfile(argv[1]);
}
Now after compiling with g++, I will call it as:
./test file.txt
But what should I do, if I want to call it as
./test <file.txt
In short how do I do a file read using default input/output
You should check the arguments to main to see if there is an argument given to the program. If it is then you can use that as the file, otherwise you use std::cin.
Here is an example:
void do_something(istream &input)
{
// Read some stuff from the input
}
int main(int argc, char *argv[])
{
if (argc == 1)
do_something(cin);
else if (argc == 2)
do_something(ifstream(argv[1]));
else
{
cout << "Error: Must supply a file\n";
return 1;
}
}
The reason I call another function to read and process the input, is because you can not assign streams, but must use references or pointers. It's also good to put separate tasks in separate functions, because it will increase readability of the code.
When you want to read from standard input, use std::cin instead of opening your own stream.
For example:
std::string s;
std::getline(std::cin, s);
Using < redirects that file to stdin, so you'd get at it via std::cin in c++.
You need instead to read from stdin, da file.
in other words read from the keyboard.
when you pipe stuff in, it will be read as if typed from the keyboard.
You can do what most of the Unix commands do: read from the file if the filename is specified. If the file name is missing read from standard input.
The cin object is already defined in iostream. Just read from cin instead of inputfile.
Perhaps
ifstream &myin;
if (argc>1) {
ifstream* inputfilep = new infstream(argv[1]);
myin = *inputfile;
}
else myin = cin;
/* do your input on myin */
you will need to modify your example to check argc to see if any command line arguments are passed in, as the input redirection is stripped off by the shell so if argc is 0 then read from standard in as given by the other examples, otherwise as your example code.
You don't have to do anything.
Just write your program as if your are reading from the command line.

How to restore stdout after using freopen

I try to redirect output in my c++ program from stdout with the following:
freopen(cmd.c_str(),"w",stdout);
Then I call system to execute cmd. I have also tried forking and then calling execvp. Either way, when program control returns to my program, things written to stdout are no longer showing. How can normal behavior be restored?
Here is solution for stdin if doing in loop, needed to figure this out for a program wherein freopen of stdin happens in a loop on some condition. Took some time for me to figure out (with help of search and all) and so posting here
savestdin = dup(STDIN_FILENO);
while (1) {
.
.
if (inputfile) {
savestdin = dup(savestdin);
freopen(inputfile, "r", stdin);
restorestdin = TRUE;
}
.
.
if (restorestdin) {
fflush(stdin);
fclose(stdin);
stdin = fdopen(savestdin, "r");
restorestdin = FALSE;
}
.
.
}
Do this:
fclose(stdout);
stdout = fdopen(1, "w"); //reopen: 1 is file descriptor of std output
If you can use STDOUT_FILENO from <unistd.h>, instead of 1 as first argument to fdopen.

C/C++ add input to stdin from the program?

Is that even possible ?
Lets say that the code has a lot of scanf lines. Instead of manually running and adding values by hand when debugging, is it possible to "feed" stdin with data so that when the scanf starts reading, it will read the inputted data without any need to interact with the terminal.
Put the test lines into a file, and run the program like this:
myprogram < mytestlines.txt
Better than hacking your program to somehow do that itself.
When you're debugging the code, you can set up the debugger to run it with that command line.
To make your program a little more versatile, you might want to consider rewriting your program to use fscanf, fprintf, etc. so that it can already handle file IO as opposed to just console IO; then when you want to read from stdin or write to stdout, you would just do something along the lines of:
FILE *infile, *outfile;
if (use_console) {
infile = stdin;
outfile = stdout;
} else {
infile = fopen("intest.txt", "r");
outfile = fopen("output.txt", "w");
}
fscanf(infile, "%d", &x);
fprintf(outfile, "2*x is %d", 2*x);
Because how often do programs only handle stdin/stdout and not allow files? Especially if you end up using your program in shell scripts, it can be more explicit to specify input and outputs on the command line.
int fd[2];
pipe(fd);
close(0); // 0:stdin
dup(fd[0], 0); // make read pipe be stdin
close(fd[0]);
fd[0] = 0;
write(fd[1], "some text", 9); // write "some text" to stdin