Passing text file to standard input - c++

The following code is part of a larger translator program. The code below asks the user to type a line and than just writes it back. Is there a way that instead of writing a single line each time, I can just pass in a whole file etc 'translate.txt' in standard input and the program can write it back line by line and produces an error when the end of line is reached ?
#include <iostream>
#include <string.h>
#include<stdio.h>
#include<fstream>
using namespace std;
using namespace std;
void PL() {
char line[BUFSIZ];
while( cin.good() ) {
cout<<"Type line now"<<endl;
cout<<"\n";
cin.getline(line, sizeof(line));
cout<<"\n"<<endl;
string mystring = string(line);
// supposed to Parsing string into words and translate//
//but just reading back input for now//
cout<<"You typed:"<<mystring<<endl;
cout<<"\n"<<endl;
}
}
int main() {
PL();
}

Do you expect a way to pass a file to your program?
executable < file

This code works well for me:
void PL() {
string line;
while(cin) {
cout<<"Type line now";
if(std::getline(cin,line)) {
// supposed to Parsing string into words and translate//
//but just reading back input for now//
cout<<"You typed:"<<line<<endl;
}
}
}
Note that the stdin there is actually passed to the program from the shell as mentioned:
$ executable < file
If you want to pass arbitrary types of streams created from outside this function, you'll need something like
void PL(std::istream& is) {
string line;
while(is) {
cout<<"Type line now";
if(std::getline(is,line)) {
// supposed to Parsing string into words and translate//
//but just reading back input for now//
cout<<"You typed:"<<line<<endl;
}
}
}
int main() {
std::ifstream is("mytext.txt"); // hardcoded filename
PL(is);
return 0;
}
or alternatively
int main(int argc, char* argv[]) {
std::istream* input = &std::cin; // input is stdin by default
if(argc > 1) {
// A file name was give as argument,
// choose the file to read from
input = new std::ifstream(argv[1]);
}
PL(*input);
if(argc > 1) {
// Clean up the allocated input instance
delete input;
}
return 0;
}
There are certainly more elegant solutions
and calling from the command line:
$ executable mytext.txt

Your shell will have a way to pass a file in over stdin. So for example, if you are on a bourne-compatible shell you can run
translate < translate.txt
(assuming your program is compiled to a binary named translate). This is assuming you want to start the program interactively, i.e. from a shell.
If you want to automatically spawn this program from another program you wrote, it depends on your OS. On POSIX operating systems, for example, you will want to open the file and dup2 the resulting file descriptor into STDIN_FILENO after forking but before calling one of the exec family functions.

Related

Behaviour of static ifstream object inside a function

I've made a static ifstream object inside a function and I'm associating it with the file given in the function argument.
In the main function, I'm calling this function twice, each time with a different file name.
Here's my code:
#include <iostream>
#include<fstream>
using namespace std;
void print_file(string path)
{
static ifstream ifs{path.c_str()};
if (ifs.is_open())
{
cout<<endl<<"Going to print the file: "<<endl;
char c = ifs.get();
while (ifs.good()) {
std::cout << c;
c = ifs.get();
}
}
else
cout<<endl<<"File couldn't be opened"<<endl;
}
int main(int argc, char**argv)
{
if(argc!=3)
{
cout<<endl<<argv[0]<<" file_name1 file_name2"<<endl;
return 0;
}
print_file(argv[1]);
print_file(argv[2]);
}
Given below is the output:
[vishal1#localhost temp]$ ./exe file1.txt file2.txt
Going to print the file:
File 1 contents
Going to print the file:
Due to some reasons file1 is not getting printed the second time. What's the reason?
The reason is that in the first call you read all the contents of the file, but you're not resetting the read file pointer to the beginning. So the next call the file status is still and the end of the file and ifs.good() returns false.
You need to "rewind" the file, and clear the status flags.
Also note that you should never use eof() in a loop condition, and using good() is just the same.
In your case, use e.g.
while (ifs.get(c))
{
std::cout << c;
}
instead.

Unable to have function properly populate array from text file, seems to skip first line/be one off

So I have two simple questions. One is my function okay for reading a text file composed of one number on each line and passing it an array inside main()? And is the text file opening/closing properly or do I not understand the code?
And secondly, I can't seem to fill my array correctly. There's 92 numbers/lines, but I can only seem to get 91 elements. It seems to skip the first number, but I'm not sure why. When I'm debugging I can see "number" reading the the first line, but I don't know where it goes.
The text file is 92 numbers with decimals, with a number in each line like this..and the first number is in the first line, no space above and no vertical space between the numbers.
31.11
25.22
...
int getTempData(double temperatures[]) {
ifstream input("pgm6.txt");
if (!input)
return 1; // closes input file
string number;
while (input >> number)
for (int i = 0; i < 91; i++)
{
input >> temperatures[i];
}
}
and inside main()
const int ARRAY_SIZE = 91;
double temperatures[ARRAY_SIZE];
getTempData(temperatures);
Edit: Thanks so much for the help everyone. I learned my lesson in not using code I don't quite understand from here: https://www.reddit.com/r/learnprogramming/comments/2wwv6i/c_creating_writing_to_and_displaying_text_files/
#include <fstream> // Instead of <iostream>
#include <string>
using namespace std; // Nothing too much wrong with this...
int main() {
ifstream input("input.txt"); // Open the file "input.txt" for reading
(if = input file)
if ( !input ) // Did the file open correctly?
return 1;
ifstream output("output.txt"); // Open the file "output.txt" for writing
(of = output file)
if ( !output ) // Did the file open correctly?
return 1; // C++ automatically closes the input file!
string word;
**while ( input >> word )** // Read a word while the file isn't at its
end
output << word << '\n'; // Write the word on its own line
// C++ automatically closes the output file
// C++ automatically closes the input file
}
What you are trying to achieve seems to boil down to this:
#include <fstream>
int getTempData(double temperatures[]) {
std::ifstream input("pgm6.txt");
int i;
for (i = 0; i < 92 && input >> temperatures[i]; i++) {
// deliberate empty line
}
// input will close file on exiting function
return i; // returns number of elements found
}
int main() {
const int ARRAY_SIZE = 92;
double temperatures[ARRAY_SIZE];
getTempData(temperatures);
}
while (input >> number)
This reads the first number and throws it away. Simply remove this line of code.
Also, you should probably add error checking to input >> temperatures[i];. And your function needs to return something if all is well -- currently there is no return statement at the end. Also, your loop only collects 91 elements.

Code to print out number of lines and integer values

I created a data file called program.txt. I need to create code that prints out number of lines and integer values from that program.txt
Heres the text I made
1
35
45
87
9
100
the program.text has these values in it
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string calc;
int test;
int cool;
int book;
ifstream myfile;
ifstream outof;
myfile.open ("program.txt");
outof.open("program.txt");
if (myfile.fail())
{
cerr<<"Error Opening file"<<endl;
}
if(outof.fail ())
{
cerr<<"Error Opening file"<<endl;
}
while (!myfile.eof ())
{
getline(myfile,calc);
++book;
}
cout <<book<<endl;
while (!outof.eof ())
{
outof<<test;//
cool++;
}
cout<<cool<<endl;
myfile.close();
outof.close();
}
Also after cerr I tried exit (1) and it said exit was not defined.
I am new to this any help would be greatly appreciated. Thanks This is C++ btw.
The problem is that you are using ifstream, which stands for INPUT file stream. You want to use ofstream, which is OUTPUT file stream. You cannot write to an input file stream, hence why the << operator is not defined.
Also, rather than using exit(1) after your errors, you can just return 1; as you are inside your main function. This will terminate the program, returning 1 as the exit code.
If you really want to use exit, you need to #include <cstdlib>.
Your defined input and expected output aren't clearly defined, so I'm not sure what you're trying to do. However, here's a general idea:
Putting the filename in a fstream's constructor will automatically try to open the file for read/write. You dont need to call .open() anymore. Also, you shouldnt be reading and writing to the same file simultaneously if you dont know what you're doing.
std::ifstream myInputFile("program.txt");
std::ofstream myOutputFile("programOut.txt");
Rather than checking myInputFile.fail(), just use the overloaded boolean operator. In depth explanation: ifstream::is_open vs ifstream::fail?
if (!myInputFile) {
//Something went wrong
std::cerr << "Failed to open input file" << std::endl;
return 1;
}
Define your std::string to hold lines as you read them, read all of your input file, and count the lines.
std::string line;
int lineCount = 0;
while (getline(myInputFile,line)) {
++lineCount;
//Do something with 'line'
}
Maybe you'll need to store the lines from your input file so that you can output the count of the lines at the beginning of your output file, you might want to #include <vector> and do something like this:
std::string line;
std::vector<std::string> linesFromFile;
//Read in all lines of the input file and store them in the vector
while (getline(myInputFile, line)) {
linesFromFile.emplace_back(line);
}
//All lines read, good time to close input file
myInputFile.close();
//Print number of lines read
myOutputFile << linesFromFile.size() << std::endl;
//Loop through lines and print them
for (auto &lineFromFile : linesFromFile) {
myOutputFile << lineFromFile << std::endl;
}
//Done outputting, close output file
myOutputFile.close();

Using input redirection, how to read file and get character string in C?

I have a file that I want my program to read from using input redirection from the command line. For example,a.out < file.dat . Then I was going to use cin.get() and put characters in an array.
I don't want to hard code any input file names, which I have been seeing in some of the existing posts. If I treat this input redirection as stdin, do I have to explicitly open my file?
int main (int argc, char *argv[])
{
string filename;
ifstream infile;
cin >> filename;
do {
int c = 0;
c = infile.get(); //need to get one character at a time
//further process
} while ( ! infile.eof());
}
You can just use cin, which is a stream buffer associated with stdin
#include <iostream>
int main()
{
char c;
while (std::cin.get(c))
{
std::cout << c << std::endl; // will print out each character on a new line
}
exit(0);
}

why its jumping out of program?

I just start learning C++.
When I execute my code it's jumping out of the program without any error. Why?
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char s1[20],s2[10];
cout<<" enter a number : ";
cin.get(s1,19);
cout<<" enter a number : ";
cin.get(s2,9);
cout<<s1<<"/n"<<s2;
getch();
}
The method get() reads upto the '\n' character but does not extract it.
So if you type: 122345<enter>
This line:
cin.get(s1,19);
Will read 12345, but the '\n' (created by hitting <enter>) is left on the input stream. Thus the next line to read:
cin.get(s2,9);
Will read nothing as it sees the '\n' and stops. But it does not extract the '\n' either. So the input stream still has the '\n' there. So this line:
getch();
Just reads the '\n' character from the input stream. Which then allows it to finish processing and exit the program normally.
OK. That is what is happening. But there is more to this. You should not be using get() to read formatted input. Use the operator >> to read formatted data into the correct type.
int main()
{
int x;
std::cin >> x; // Reads a number into x
// error if the input stream does not contain a number.
}
Because the std::cin is a buffered stream the data is not sent to the program until you push <enter> and the stream is flushed. Thus it is often useful to read the text (from user input) a line at a time then parse that line independently. This allows you to check the last user input for errors (on a line by line bases and reject it if there are errors).
int main()
{
bool inputGood = false;
do
{
std::string line;
std::getline(std::cin, line); // Read a user line (throws away the '\n')
std::stringstream data(line);
int x;
data >> x; // Reads an integer from your line.
// If the input is not a number then data is set
// into error mode (note the std::cin as in example
// one above).
inputGood = data.good();
}
while(!inputGood); // Force user to do input again if there was an error.
}
If you want to get advanced then you can also look at the boost libs. They provide some nice code in general and as a C++ program you should know the contents of boost. But we can re-write the above as:
int main()
{
bool inputGood = false;
do
{
try
{
std::string line;
std::getline(std::cin, line); // Read a user line (throws away the '\n')
int x = boost::lexical_cast<int>(line);
inputGood = true; // If we get here then lexical_cast worked.
}
catch(...) { /* Throw away the lexical_cast exception. Thus forcing a loop */ }
}
while(!inputGood); // Force user to do input again if there was an error.
}
You need to use cin.ignore(); to ignore the newline character from stream before getting next input.