I seems std::cout does not work consistently in printing multiple things, as shown in the following two examples. I thought it might related to buffer flush but it made no difference even if I add a number of std::flush in the test example.
#include <cstdlib>
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
void test(const std::string& f1);
int main(void) {
std::string a = "a";
std::cout << a << a << a << std::endl;
// Then I got aaa on the screen, which is as expected.
test("inputfile");
// The input file contains one character: "a"
// after running the test I got only one "a" on the screen
// even though the string is repeated three times in the cout statement, as in the previous case
return 0;
}
void test(const std::string& f1){
std::ifstream ifile;
ifile.open(f1);
for(std::string line; std::getline(ifile, line); ) {
std::cout << line << line << line << std::endl;
}
ifile.close();
}
I expected to see
aaa
aaa
on the screen, but the actual output was
aaa
a
I use this to compile
g++ -g -std=c++11 -o test test.cpp
The version of g++ is 5.2.0.
I have a feeling the comment by Mark Ransom points out the problem. You can verify that hypothesis by opening your file in binary mode and printing the integer values that encode the characters.
void test(const std::string& f1){
std::ifstream ifile;
ifile.open(f1, std::ifstream::binary);
int ch;
while ( (ch = ifile.get()) != EOF )
{
// Print the integer value that encodes the character
std::cout << std::setw(2) << std::setfill('0') << std::hex << ch << std::endl;
}
ifile.close();
}
If the output is
61
0d
0a
and your platform is not Windows, then the output your are getting would make sense.
The line read from the file contains the characters 'a' (0x61) and '\r' (0x0d).
The carriage return character ('\r') causes the line to be written on top of the previous output.
Related
I came across the following observation while working with input and output file streams and I am confused. Can anyone tell me why this happens:
I saved a txt file on my desktop by the name hello which contains the following text:
Hello my name is xyz
Next, I ran the following code:
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::fstream strm;
strm.open("C:\\Users\\SWARAJ SONAVANE\\Desktop\\hello.txt");
if (strm.fail())
{
std::cout << "failed.... :(\n";
}
//std::string p;
//strm >> p;
//std::cout << p;
strm << "random text";
}
The content of the hello.txt file after running this code was:
random textme is xyz
Now i ran the following code on the original hello.txt file
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::fstream strm;
strm.open("C:\\Users\\SWARAJ SONAVANE\\Desktop\\hello.txt");
if (strm.fail())
{
std::cout << "failed.... :(\n";
}
std::string p;
strm >> p;
std::cout << p;
strm << "random text";
}
The console printed hello but the contents of the hello.txt file remained unaltered.
Can anybody explain, what difference did reading stream into the string make?
If you want to know how streams work in C++ then you need a reference work (and maybe a tutorial as well), obviously its much more complicated than can be explained here.
The reason for what you found is the rule that if you switch from reading to writing (or vice versa) you must execute a positioning or flushing operation before you make the switch. Try the following code instead
int main()
{
std::fstream strm;
strm.open("C:\\Users\\SWARAJ SONAVANE\\Desktop\\hello.txt");
if (strm.fail())
{
std::cout << "failed.... :(\n";
}
std::string p;
strm >> p;
std::cout << p;
strm.seekp(0); // position the stream at the beginning
strm << "random text";
}
I (a student whose professor encourages online research to complete projects) have an assignment where I have to analyze the contents of a file (frequency of certain words, total word cout, largest and smallest word) and I'm getting stuck on even opening the file so the program can get words out. I've tried to just count the words that it reads and i get nothing. As I understand it, the program should be opening the selected .txt file, going through its contents word by word and outputing it right now.
Here's code:
#include <iostream>
#include <string>
#include <cctype>
#include <fstream>
#include <sstream>
string selected[100];
//open selected file.
ifstream file;
file.open(story.c_str());
string line;
if (!file.good())
{
cout << "Problem with file!" << endl;
return 1;
}
while (!file.eof())
{
getline(file, line);
if (line.empty())
continue;
istringstream iss(line);
for (string word; iss >> word;)
cout << word << endl;
```
Because of the simplicity of the attached code, I will not give detailed explanations here. With the usage of std::algorithm every task can be performed in a one-liner.
We will read the complete source file into one std::string. Then, we define a std::vector and fill it with all words. The words are defined by an ultra simple regex.
The frequency is counted with a standard approach using std::map.
#include <fstream>
#include <string>
#include <iterator>
#include <vector>
#include <regex>
#include <iostream>
#include <algorithm>
#include <map>
// A word is something consiting of 1 or more letters
std::regex patternForWord{R"((\w+))"};
int main() {
// Open file and check, if it could be opened
if (std::ifstream sampleFile{ "r:\\sample.txt" }; sampleFile) {
// Read the complete File into a std::string
std::string wholeFile(std::istreambuf_iterator<char>(sampleFile), {});
// Put all words from the whole file into a vector
std::vector<std::string> words(std::sregex_token_iterator(wholeFile.begin(), wholeFile.end(), patternForWord, 1), {});
// Get the longest and shortest word
const auto [min, max] = std::minmax_element(words.begin(), words.end(),
[](const std::string & s1, const std::string & s2) { return s1.size() < s2.size(); });
// Count the frequency of words
std::map<std::string, size_t> wordFrequency{};
for (const std::string& word : words) wordFrequency[word]++;
// Show the result to the user
std::cout << "\nNumber of words: " << words.size()
<< "\nLongest word: " << *max << " (" << max->size() << ")"
<< "\nShortest word: " << *min << " (" << min->size() << ")"
<< "\nWord frequencies:\n";
for (const auto& [word, count] : wordFrequency) std::cout << word << " --> " << count << "\n";
}
else {
std::cerr << "*** Error: Problem with input file\n\n";
}
return 0;
}
i am writing this very simple program that ouputes hello world using files. keep in mind i want the hello and world to be on separate lines.
here is the following code:
int main()
{
std::ofstream someFile("file.dat");
someFile << "" << std::endl;
std::fstream someOtherFile("file.dat",ios::in | ios::out);
std::string content;
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
someOtherFile.seekg(0, ios::beg);
std::getline(someOtherFile, content);
std::cout << content << std::endl;
return 0;
}
however, whenever i run the following program, it only prints "hello".
any help will be greatly appreciated, and PLEASE give an example using fstream, not ofstream or ifstream (I am trying to learn how fstream works, however am finding a little trouble).
my compiler is the latest VS.
getine function only read one line per one time, so you should call getline until the end of file. The code be below can help you.
#include <iostream>
#include <fstream>`
#include <string>
using namespace std;
int main()
{
std::ofstream someFile("file.dat");
someFile << "" << std::endl;
std::fstream someOtherFile("file.dat",ios::in | ios::out);
std::string content;
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
someOtherFile.seekg(0, ios::beg);
while(std::getline(someOtherFile, content))
{
std::cout << content << std::endl;
}
return 0;
}
You have 2 lines of code:
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
They put 2 lines of strings into file.dat:
// file.dat
hello
world
The function "getline()" gets only 1 line from the file. And the "seekg" function sets the read position to the first line of the file: which contains "hello".
If you want to read to the end of the file: then replace:
std::getline(someOtherFile, content);
std::cout << content << std::endl;
with:
while (!someOtherFile.eof())
{
std::getline(someOtherFile, content);
std::cout << content << std::endl;
}
Or use a counter variable if you just want specific lines.
By the way, I am just assuming that you meant to put the variable "content" where "name" is.
std::getline only get one line of text from the specific file. As http://www.cplusplus.com/reference/string/string/getline/?kw=getline says:
istream& getline (istream& is, string& str);
Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for (2)).
Add another getline(..) and cout statement after the first set of getline and cout. you will get the world as output.
someOtherFile << "hello" << std::endl;
someOtherFile << "world" << std::endl;
someOtherFile.seekg(0, ios::beg);
std::getline(someOtherFile, content);
std::cout << content << std::endl;
std::getline(someOtherFile, content);
std::cout << content << std::endl;
getline gets only one line in a file. To get next line, you need to call again.
#include<fstream>
#include<iostream>
using namespace std;
int main()
{
std::ofstream someFile("file.dat");
someFile << "" << std::endl;
someFile.close();
std::fstream someOtherFile("file.dat",ios::in | ios::out);
std::string content;
someOtherFile << "hello ";
someOtherFile << "world" << std::endl;
someOtherFile.close();
someOtherFile.seekg(0, ios::beg);
std::getline(someFile1, content);
std::cout << content << std::endl;
someFile1.close();
return 0;
}
This will print your desired answer
Using the following code to extract a string from a std::istream :
#include <sstream>
#include <iostream>
void parse(std::istream & is, std::string & out)
{
is >> out;
}
int main(int argc, char** argv)
{
if (argc>1)
{
std::istringstream is(argv[1]);
std::string out("__INIT__");
std::cout << "good:" << is.good() << " fail:"<< is.fail() << " eof:"<< is.eof() << " in_avail:"<< is.rdbuf()->in_avail() << " value:" << out << std::endl;
parse(is, out);
std::cout << "good:" << is.good() << " fail:"<< is.fail() << " eof:"<< is.eof() << " in_avail:"<< is.rdbuf()->in_avail() << " value:" << out << std::endl;
}
}
With a non-empty string the output looks like :
$./a.out "TEST"
good:1 fail:0 eof:0 in_avail:4 value:__INIT__
good:0 fail:0 eof:1 in_avail:0 value:TEST
With an empty string the output looks like :
$./a.out ""
good:1 fail:0 eof:0 in_avail:0 value:__INIT__
good:0 fail:1 eof:1 in_avail:0 value:__INIT__
Instead of this, I would expect :
good:1 fail:0 eof:0 in_avail:0 value:__INIT__
good:0 fail:0 eof:1 in_avail:0 value:
The operator>> does not extract an empty string. The result is the same with an empty string or and no data.
Any suggestion to handle this situation will be appreciated.
If you're using your parse function exclusively for extraction, you can simply make it out to be a check for an empty buffer. If there is, simply clear the string:
void parse(std::istream& is, std::string& out)
{
if (is.eof() || is.peek() == std::char_traits<char>::eof())
{
out.clear();
return;
}
is >> out;
}
There is no difference between an empty value and no value.
That's just your assumption, and it's not really true.
If you attempt to extract a string, it is expected that there are characters to extract. Before characters are available, it is impossible to perform any extraction, let alone one that results in extraction to a particular object.
This is entirely expected behaviour.
I guess your confusion stems from your prior check for argc > 1, but although the shell pretended ./myProgram "" had some argument, as far as your stream is concerned there is nothing in that argument.
If you wish to make your own handling for it, simply stick an if condition on is.fail() after the read.
#include <sstream>
#include <iostream>
int main(int argc, char** argv)
{
if (argc>1)
{
std::istringstream is(argv[1]);
std::string out;
is >> out;
if (is.fail()) {
std::cout << "Well, you gave me an argument, but it was empty, biatch!\n";
}
}
}
Don't bother checking is.eof(); it'll be set when you reached the end of input whether it contained any characters or not.
I get confused with the "istream& getline (istream& is, string& str)"function, and according to http://www.cplusplus.com/reference/string/string/getline/, the following program:
#include <iostream>
#include <sstream>
int main()
{
std::istringstream s("this is a test");
std::string line = "line ";
getline( s, line );
std::cout << line << std::endl;
s.str("test again");
getline( s, line );
std::cout << s.str() << std::endl;
std::cout << line << std::endl;
return 0;
}
I expect the output to be:
line this is a test
test again
test again
but when I test it on Visual Studio, the output is :
this is a test
test again
this is a test
Could anyone explain the frustrating function for me ?
Clear the error flags between the calls to getline:
int main()
{
std::istringstream s("this is a test");
std::string line = "line ";
getline( s, line );
std::cout << line << std::endl;
s.str("test again");
s.clear() // <<<--------------- to clear error flags
getline( s, line );
std::cout << s.str() << std::endl;
std::cout << line << std::endl;
return 0;
}
The first getline sets eofbit on the stream. The second one then fails and line stays intact.
With the fix, you'll get:
this is a test
test again
test again
because getline doesn't add to the string, it replaces the content.
Whatever value line has prior to the call will not matter, as from the documentation for std::getline:
Calls str.erase()
Your second logical error is due to reusing a stream once you've reached its end.