I have a program that basically reads a text file and counts the number of occurrences of each word on each line. Everything works properly when reading from a text file using an ifstream, however, if a file name is not entered on the command line, I need to read from stdin instead.
I use the following to open and read in the file currently:
map<string, map<int,int>,compare> tokens;
ifstream text;
string line;
int count = 1;
if (argc > 1){
try{
text.open(argv[1]);
}
catch (runtime_error& x){
cerr << x.what() << '\n';
}
// Read file one line at a time, replacing non-desired char's with spaces
while (getline(text, line)){
replace_if(line.begin(), line.end(), my_predicate, ' ');
istringstream iss(line);
// Parse line on white space, storing values into tokens map
while (iss >> line){
++tokens[line][count];
}
++count;
}
}
else{
while (cin) {
getline(cin, line);
replace_if(line.begin(), line.end(), my_predicate, ' ');
istringstream iss(line);
// Parse line on white space, storing values into tokens map
while (iss >> line){
++tokens[line][count];
}
++count;
}
Is there a way to assign cin to an ifstream and simply add an else statement if argc > 1 fails, using the same code afterwards instead of duplicating like this? I haven't been able to find a way to do this.
Make the reading part a function of its own. Pass either an ifstream or cin to it.
void readData(std::istream& in)
{
// Do the necessary work to read the data.
}
int main(int argc, char** argv)
{
if ( argc > 1 )
{
// The input file has been passed in the command line.
// Read the data from it.
std::ifstream ifile(argv[1]);
if ( ifile )
{
readData(ifile);
}
else
{
// Deal with error condition
}
}
else
{
// No input file has been passed in the command line.
// Read the data from stdin (std::cin).
readData(std::cin);
}
// Do the needful to process the data.
}
You cannot assign cin to an ifstream.
But you could reopen cin to some file.
Anyway, the better method would be modularising your code and just using a std::istream&.
I just put a easy way to let the program read file if given else use stdin, and close it properly.
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
int main(int argc, char* argv[]) {
auto fp_deletor = [](std::istream* is_ptr) {
if (is_ptr && is_ptr != &std::cin) {
static_cast<std::ifstream*>(is_ptr)->close();
delete is_ptr;
std::cerr << "destroy fp.\n";
}
};
std::unique_ptr<std::istream, decltype(fp_deletor)> is_ptr{nullptr, fp_deletor};
if (argc > 2) {
std::cerr << "usage: " << argv[0] << "[input-file]";
return -1;
} else if (argc == 1) {
std::cerr << "using stdin as input.\n";
is_ptr.reset(&std::cin);
} else {
is_ptr.reset(new std::ifstream(argv[1]));
}
std::string line;
while (std::getline(*is_ptr, line)) {
// your logic....
}
// just return, unique_ptr manage the istream
return 0;
}
Related
My task is to make a C++ program that will read, write, save, load and append a text file. I have two issues that I've been stuck on so far. The first being, how do you store the first argument entered by a user in a string using argv? Secondly, how do I create the program such that when the user enters in the command the program doesn't exit immediately after, so technically be in a while loop the whole time until prompted by a quit message? I've tried doing this already but my code also goes into a loop.
int main(int argc, char* argv[]) {
while (!inFile.eof()) {
inFile.open("userinput.txt");
getline(cin, line);
if (argc > 1) {
int result = strcmp(argv[1], "load");
if (result == 0) {
cout << "CORRECT" << endl;
}
else{
exit(1);
}
}
}
return 0;
}
Something like this, read program argument, read user input, read/write/append on a file.
#include <iostream>
#include <ios> // new
#include <fstream> // new
using namespace std;
int main(int argc, char* argv[])
{
fstream inFile("userinput.txt", std::ios_base::app | std::ios_base::out); //new, allows to append lines to 'userinput.txt'
while (!inFile.eof()) {
string line;
getline(cin, line);
inFile << line; // new: write the user input on inFile
if (argc > 1) {
int result = strcmp(argv[1], "load");
if (result == 0) {
cout << "CORRECT" << endl;
}
else {
exit(1);
}
}
}
return 0;
}
I don't really know the usage of this though so you should adapt it to your ends.
i can detect the empty line in text but not getting how to delete it
please can you give me some tips how to delete that detected lines
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
// open input file
std::ifstream ifs( "in_f1.txt" );
std::fstream ofs( "out_f1.txt" );
char c;
char previous_c;
// squeeze whitespace
std::string word;
ifs >> word;
ofs << word;
while (ifs)
{
if (c==' ')
{
ofs.put(c);
while (c==' '&&ifs)
{
ifs.get (c);
;}
}
if (c=='\v')
{
previous_c=c;
while (c=='\v'&&ifs)
{
ifs.get (c);
;}
ofs.put(previous_c);
};
// read line
std::string line;
std::getline( ofs, line );
// append flag and remove 'empty lines'
int flag = 2;
while( getline( ofs, line ) )
{
if( line == " " )
{
flag = 2;
continue;
}
cout << line << " " << flag << endl;
flag = 0;
}
ifs.close();
ofs.close();
}}
you are looking in the output stream for an empty line, after you copy the characters to it.. A stream is not intended to be something we edit like a string, so stop thinking on it that way..
instead you need to add the logic before you put the characters into the stream.
the easiest approach is to have a temporary stream, that you copy from input to.
then for each line, copy the temporary stream to output stream, if and only if, it contains characters different from whitespace.
void remove_empty_lines(std::istream& in, std::ostream& out)
{
std::string line;
while (std::getline(in, line))
if (!line.empty())
out << line << '\n';
}
N.B. This will add a newline to the end of the file even if there isn't one in the original.
#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());
}
Wherever, there is a new line or ("\n") and a space (" ") immediately after the the new line, I want to disregard the "\n" and just print the space in my output, how could I do this?
This is an example:
newegg
bizrate
want to change it to :
newegg bizrate
I am confused since I guess I cannot do it by reading line by line! below is my rough code, which I don't know how to continue ...
Thanks a lot in advance.
ifstream file ("input.txt");
ofstream output("output.txt");
string line;
if(file.is_open())
{
while (!file.eof())
{
getline (file, line);
if (line.find("\n"+' ') != string::npos)
{
??
}
Do it like this. The function getline() will read till \n character
getline(file, line);
cout<<line;
while (!file.eof())
{
getline(file, line);
if (line[0]==' ')
{
cout <<" "<<line;
}
else
{
cout <<"\n"<<line;
}
}
The function getline() (documentation here) will read and throw away the \n character, so there's no need to search for it in the string.
Just do something like this:
bool first = true;
while (!file.eof())
{
getline(file, line);
// you may want to check that you haven't read the EOF here
if (!first)
{
cout << " ";
}
else
{
first = false;
}
cout << line;
}
You might want this:
#include <cctype>
#include <iostream>
#include <sstream>
int main() {
std::istringstream input(""
"newegg\n"
" bizrate\n"
"End");
std::string line;
while(std::getline(input, line)) {
while(std::isspace(input.peek())) {
std::string next_line;
std::getline(input, next_line);
line += next_line;
}
std::cout << line << '\n';
}
}
Please note: A test for EOF is likely wrong.
I have a file with many numbers. The file looks like "192 158 100 0 20 200" basically like that. How can I load the files number values 1 at a time and display them on the screen in C++?
try something like this:
int val;
std::ifstream file("file");
while (file >> val)
std::cout << val;
The following program should print each number, one per line:
#include <iostream>
#include <fstream>
int main (int argc, char *argv[]) {
std::ifstream ifs(argv[1]);
int number;
while (ifs >> number) {
std::cout << number << std::endl;
}
}
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
int main() {
std::ifstream fs("yourfile.txt");
if (!fs.is_open()) {
return -1;
}
// collect values
// std::vector<int> values;
// while (!fs.eof()) {
// int v;
// fs >> v;
// values.push_back(v);
// }
int v;
std::vector<int> values;
while (fs >> v) {
values.push_back(v);
}
fs.close();
// print it
std::copy(values.begin(), values.end(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Please consider the following code:
ifstream myReadFile;
myReadFile.open("text.txt");
int output;
if (myReadFile.is_open())
{
while (fs >> output) {
cout<<output;
}
}
//Of course closing the file at the end.
myReadFile.close();
As well, please include the iostream and fstream inside your code when using the example above.
Note that you need to start open a filestream to read and you can try to read it char by char and detect is there any white space in between it.
Good luck.
Another way of doing it:
std::string filename = "yourfilename";
//If I remember well, in C++11 you don't need the
//conversion to C-style (char[]) string.
std::ifstream ifs( filename.c_str() );
//Can be replaced by ifs.good(). See below.
if( ifs ) {
int value;
//Read first before the loop so the value isn't processed
//without being initialized if the file is empty.
ifs >> value;
//Can be replaced by while( ifs) but it's not obvious to everyone
//that an std::istream is implicitly cast to a boolean.
while( ifs.good() ) {
std::cout << value << std::endl;
ifs >> value;
}
ifs.close();
} else {
//The file couldn't be opened.
}
The error-handling can be done in many ways through.