How to get input from file piped to stdin - c++

So, I have a program that I am running through a command line on a raspberry pi on C++. I know how I can pass in the command line arguments already, but I need to pass it using cin, but I'm not able to get it to work.
Normally I would use args, and use a format on the command line such as ./program filename, but I have to use this format ./program < filename to redirect the filename to the program through stdin for this assignment. My instructor has told me to use cin, but no matter what I do, it will not open the file.
int main(int argc, char *argv[])
{
cout << "Matching Brackets: NAME" << endl;
string line;
string fname;
cin >> fname;
ifstream myfile;
myfile.open(fname);
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
int num = valid(line);
if(num >= 0)
cout << valid(line) << " ";
}
}
cout << endl;
myfile.close();
return 0;
}
I'm trying to get the cin to take the actual filename of a text file and use that in fstream to open the file and read through it to perform the operations, but I can't get it to open in that method, and I haven't been able to find anything about doing it that way.

When you use your program as
./program < filename
you only need to worry about reading content from stdin/std::cin.
main can be simplified to:
int main(int argc, char *argv[])
{
cout << "Matching Brackets: NAME" << endl;
string line;
while ( getline (std::cin, line) )
{
int num = valid(line);
if(num >= 0)
cout << num << " "; // No need to call valid(line) again;
}
cout << endl;
return 0;
}

Related

C++ : Error using argv[1] into a function to read a .txt file

I'm currently beginning on C++ and trying to make a function that can open a .txt file, read it, and save its words in an array (each word being a protein sequence).
Unfortunately I don't succeed at calling the argument containing the name of the file (argv[1]) in the function.
Can anyone spot errors in my code or in the way I implemented this ?
Thanks in advance, you will find the code and the error messages below :
Libraries
So here are my librairies and 'shortcuts'.
// Librairies
#include <iostream>
#include <string>
#include <fstream>
// Alias
using std::cout;
using std::endl;
using std::string;
The function
Now this is the function, note that filename is supposed to be a string containing argv[1] (the name of a .txt file specified at execution) :
string SequenceChoice(int n, string filename); // Function returning a string
std::ifstream sequenceFile (filename); //Opens the file specified on execution
if ( sequenceFile.is_open() )
{
cout<<"File opened"<<endl;
string tmp;
int i = 0;
while( sequenceFile >> tmp ) // Counts the number of sequences (words)
{
i++;
}
string allchains[i]; // Creates an array of strings, to save all the words
sequenceFile.clear();
sequenceFile.seekg(0, sequenceFile.beg); // Replaces the cursor at the beginning of the file
i=0;
while( sequenceFile >> allchains[i]) // Saves each word as a string in an array
{
cout << allchains[i] << tmp;
i++;
}
sequenceFile.close();
cout<< "File closed"<<endl;
}
else
{
cout << "Error: Cannot open file" << endl;
}
return allchains[n]; // returns the 'n'th word (n being specified when calling the function
// end of the function
Main
Now the main function, I'm not sure if doing string filename = argv[1] works, but I get less errors when I keep this step instead of putting argv[1] as an argument of my SequenceChoice() function.
int main(int argc, char *argv[]) {
if(argc >= 2)
{
string filename = argv[1];
cout << SequenceChoice( 2, filename ) << endl; // I expect it to give me the 3rd word of a .txt file for example.
}
else
{
cout << "Error : No file" << endl;
}
return 0;
}
The error message I get
Error message
The link above is a picture of the error message I get when I compile, I've been searching for hours on the internet how to resolve this, unfortunately I could'nt manage to have the code working. There's probably an error of type with the way I deal with argv[], but I failed at solving it so any help and comments would be greatly appreciated.
Please try changing following line
string SequenceChoice(int n, string filename); // Function returning a string
to
string SequenceChoice(int n, string filename) { // Function returning a string
You are trying to write a function but the ; is terminating your function and body is not starting. It should work. Also please read a book carefully.
This page lists very good books for all experience levels.
Try this :
string SequenceChoice(int n, string filename)
{
std::ifstream sequenceFile (filename); //Opens the file specified on execution
if ( sequenceFile.is_open() )
{
cout<<"File opened"<<endl;
string tmp;
int i = 0;
while( sequenceFile >> tmp ) // Counts the number of sequences (words)
{
i++;
}
string allchains[i]; // Creates an array of strings, to save all the words
sequenceFile.clear();
sequenceFile.seekg(0, sequenceFile.beg); // Replaces the cursor at the beginning of the file
i=0;
while( sequenceFile >> allchains[i]) // Saves each word as a string in an array
{
cout << allchains[i] << tmp;
i++;
}
ifs.close();
cout<< "File closed"<<endl;
}
else
{
cout << "Error: Cannot open file" << endl;
}
return allchains[n];
}
Here is fully functioning code:
You can compare it with yours.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string SequenceChoice(int n, string filename){ // Function returning a string
std::ifstream sequenceFile (filename); //Opens the file specified on execution
if ( sequenceFile.is_open() )
{
cout<<"File opened"<<endl;
string tmp;
int i = 0;
while( sequenceFile >> tmp ) // Counts the number of sequences (words)
{
i++;
}
string allchains[i]; // Creates an array of strings, to save all the words
sequenceFile.clear();
sequenceFile.seekg(0, sequenceFile.beg); // Replaces the cursor at the beginning of the file
i=0;
while( sequenceFile >> allchains[i]) // Saves each word as a string in an array
{
cout << allchains[i] << tmp;
i++;
}
sequenceFile.close();
cout<< "File closed"<<endl;
return allchains[n]; // returns the 'n'th word (n being specified when calling the function
}
else
{
cout << "Error: Cannot open file" << endl;
}
return NULL;
// end of the function
}
int main(int argc, char *argv[])
{
if(argc >= 2)
{
string filename = argv[1];
cout << SequenceChoice( 2, filename ) << endl; // I expect it to give me the 3rd word of a .txt file for example.
}
else
{
cout << "Error : No file" << endl;
}
}
Thanks to your answers I managed to solve my problem, apart from some syntax errors in the code the argument filename in the function was a string, and as argv[] is an array of pointers. So it just couldn't work to consider them as the same type.
Here is a working version of the function, for those it could help :
string SequenceChoice(int n, char* argv[])
{
std::ifstream sequenceFile (argv[1]); //Opens the file specified on execution
if ( sequenceFile.is_open() )
{
cout<< " .File opened. \n" <<endl;
string tmp;
int i = 0;
while( sequenceFile >> tmp ) // Counts the number of sequences (words)
{
i++;
}
cout << " " << i << " chains in the .txt file : \n" << endl;
string allchains[i]; // Creates an array of strings, to save all the words
sequenceFile.clear();
sequenceFile.seekg(0, sequenceFile.beg); // Replaces the cursor at the beginning of the file
i=0;
while( sequenceFile >> allchains[i]) // Saves each word as a string in an array
{
cout << " --- Chain "<< i + 1 << " --- : " << allchains[i] << endl;
i++;
}
sequenceFile.close();
cout << "\n .File closed. \n" << endl;
return allchains[n];
}
else
{
cout << "Error: Cannot open file" << endl;
return NULL;
}
}
And finally the new main function :
int main(int argc, char *argv[]) {
if(argc >= 2)
{
string filename = argv[1];
cout << SequenceChoice( 2, argv ) << endl; // Shows the 3rd word of the file, as an example.
}
else
{
cout << "Error : No file" << endl;
}
return 0;
}
Thanks for your help and have a great day !

ifstream does not return the correct int value

I want to make a factory class which creates and loads objects in from a file;
however when I try to read in a int from the file it appears to return a incorrect number.
std::ifstream input;
input.open("input.txt");
if (!input.is_open()){
exit(-1);
}
int number;
input >> number;
cout << number;
input.close();
When I enter a number in the input.txt file it shows: -858993460.
Changing the number doesn’t make a difference and when I use cin instead of ifstream it works like it should. I'm probably just missing something really stupid, but I can't figure it out.
Edit: Using getLine() works like it should. I guess there is a problem using >>.
Here is another solution to open a file a read it line by line:
string line;
ifstream myfile("input.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n'; // Use this to verify that the number is outputed
// Here you can transform your line into an int:
// number = std::stoi(line);
}
// myfile.close(); Use this if you want to handle the errors
}
else cout << "Unable to open file";
If you don't want to read line by line, just remove the while
...
getline(myfile,line);
number = std::stoi(line);
...
Read multiple numbers in one line
Image that your input file is like this:
1, 2.3, 123, 11
1, 2
0.9, 90
Then, you can use this piece of code to read all the numbers:
string line;
ifstream myfile("input.txt");
string delimiter = ", ";
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << "Reading a new line: " << endl;
size_t pos = 0;
string token;
while ((pos = line.find(delimiter)) != string::npos) {
token = line.substr(0, pos);
cout << token << endl; // Instead of cout, you can transform it into an int
line.erase(0, pos + delimiter.length());
}
}
}
else cout << "Unable to open file";
The output will be:
Reading a new line:
1
2.3
123
11
Reading a new line:
1
2
Reading a new line:
0.9
90
New solution that may work =)
I didn't test this, but it works apparently:
std::ifstream input;
double val1, val2, val3;
input.open ("input.txt", std::ifstream::in);
if (input >> val1 >> val2 >> val3) {
cout << val1 << ", " << val2 << ", " << val3 << endl;
}
else
{
std::cerr << "Failed to read values from the file!\n";
throw std::runtime_error("Invalid input file");
}
To check the IO, see http://kayari.org/cxx/yunocheckio.html

How can you ask for user input when also using a text file in unix shell in c++?

I run my code using a.out < file.txt and I read all of the file when I try to use cin >> variable to ask the user for input it does nothing.
When you invoke your program with a.out < file.txt, you're asking the shell to pipe the file.txt content in as the standard input for a.out instead of letting the keyboard provide standard input. If that doesn't suit you, then add a command line argument to specify the filename, use an ifstream to open it and read from that instead of cin, the use cin for the keyboard input.
For example:
int main(int argc, const char* argv[])
{
if (argc != 2)
{
std::cerr << "usage: " << argv[0] << " <filename>\n";
exit(1);
}
const char* filename = argv[1];
if (std::ifstream in(filename))
{
// process the file content, e.g.
std::string line;
while (getline(in, line))
std::cout << "read '" << line << "'\n";
}
else
{
std::cerr << "unable to open \"" << filename << "\"\n";
exit(1);
}
// can still read from std::cin down here...
}
If you need additional user input after your stdin, you have to open your controlling terminal which is convinently named "/dev/tty". Example:
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
ifstream tin("/dev/tty");
ofstream tout("/dev/tty");
tin.tie(&tout);
while (true) {
string input;
tout << "> ";
getline(tin, input);
if (input == "quit")
break;
}
return 0;
}
To convince yourself that above will not read redirected file, a simple test:
$ echo "quit" | ./a.out
>

Issue with getline from file

I am trying to read lines from a .txt file and print them out using std::cout. My code is posted below, but currently is not passing any lines to the vector during the while loop. Where did I go wrong?
int main(int argc, const char * argv[]) {
std::ifstream input("input1.txt");//(argv[1]);
if (!input.good()) {
cerr << "Can not open the grades file "; //<< argv[1] << "\n";
return 1;
}
std::vector<string> art;
string x; // Input variable
// Read the scores, appending each to the end of the vector
cout << "Start While:"; //For Debugging Purposes
while (getline(input, x)) {
art.push_back(x);
}
for (int i=0; i<art.size(); i++) {
cout << art[i] << "\n";
}
return 0;
}
Turns out Xcode was just being difficult. After moving a few files around and running it in the compiler it worked.

Writing to a file with fstream and cstring

#include <fstream>
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char filename[20] = "filename";
char userInput;
ofstream myFile;
cout << "Enter filename: ";
cin.getline(filename, sizeof(filename));
myFile.open(filename);
if(myFile.fail())
{
cout << "Error opening file: "
<< filename << "\n";
return 1;
}
cout << "Add text to the file: ";
cin.get(userInput);
while(cin.good() && userInput)
{
myFile.put(userInput);
cin.get(userInput);
}
myFile.close();
return 0;
}
Im having trouble terminating the input without force quiting it(It still writes to the file).
This is what I am supposed to do
Receives a line of input from the user, then outputs that
line to the given file. This will continue until the line input
by the user is “-1” which indicates, the end of input.
however I cannot work out the -1 part. Any help would be greatly appreciated everything else seems to work.
You're making things a bit more complicated than they need to be. Why C strings instead of std::string, for example? Using the right (standard-provided) classes generally leads to shorter, simpler and easier-to-understand code. Try something like this for starters:
int main()
{
std::string filename;
std::cout << "Enter filename" << std::endl;
std::cin >> filename;
std::ofstream file{filename};
std::string line;
while (std::cin >> line) {
if (line == "-1") {
break;
}
file << line;
}
}
First of all, the assignment asks to read a line from the user, character-wise input by get() shouldn't be the function to use. Use the member function getline() as you did to recieve the file name and use a comparison function to check against -1:
for (char line[20]; std::cin.getline(line, sizeof line) && std::cin.gcount(); )
{
if (strncmp(line, "-1", std::cin.gcount()) == 0)
break;
myFile.write(line, std::cin.gcount());
}