I would like to << stream to save all inputs from console into a file
Here is how I tried
ofstream of("file.txt");
while(1)
{
string str;
cin>>str;
of<<str;
}
I don't see the non-English characters in the file (Edit: I mean they are Japanese, Chinese or Korean etc)
You could stream char by char. Then it would be a true binary copy.
ofstream of("file.txt");
while(1)
{
char c;
cin>>c;
of<<c;
}
Streaming using the formatted extraction operator is a poor choice. Specifically, it will consume all of the white space.
If it were me, I would copy using std::getline or istream::rdbuf:
std::getline:
// Copy standard input to named file, one line at a time.
#include <iostream>
#include <fstream>
int main (int argc, char **argv) {
std::string s;
std::ofstream of(argv[1]);
while(std::getline(std::cin, s)) {
of << s << "\n";
}
}
istream::rdbuf:
// Copy entire standard input stream to named file in one go
#include <iostream>
#include <fstream>
int main (int argc, char **argv) {
std::ofstream(argv[1]) << std::cin.rdbuf();
}
Just a couple of points as a starter:
ofstream of("file.txt");
If you want to see Japanese, Chinese or Korean character you should not be using an ofstream here. You want a stream that writes wide characters: a std::wofstream. You will also haveendow that stream with a locale. See Why does wide file-stream in C++ narrow written data by default? for details.
Another point: You apparently are have a using namespace std;. You can find many questions here at Stack Overflow that indicate that this is a bad idea. Typing those extra five characters isn't very hard, it avoids problems with names from the standard library polluting your namespace, and it makes the code clearer.
while(1)
Your loop doesn't have any break statements to escape the loop, so this plus the while (1) means your program will never stop. It is just going to keep on going and going and going and going. You want it to stop (or should want it to stop) on encountering an error or end of file in the input stream.
A better approach is to use a construct such as
while (std::getline (std::cin, s))
to control the loop (except you need to use something special to get wide characters).
Related
So I've been doing algorithms in C++ for about 3 months now as a hobby. I've never had a problem I couldn't solve by googleing up until now. I'm trying to read from a text file that will be converted into a hash table, but when i try and capture the data from a file it ends at a space. here's the code
#include <iostream>
#include <fstream>
int main()
{
using namespace std;
ifstream file("this.hash");
file >> noskipws;
string thing;
file >> thing;
cout << thing << endl;
return 0;
}
I'm aware of the noskipws flag i just don't know how to properly implement it
When using the formatted input operator for std::string it always stops at what the stream considers to be whitespace. Using the std::locale's character classification facet std::ctype<char> you can redefine what space means. It's a bit involved, though.
If you want to read up to a specific separator, you can use std::getline(), possibly specifying the separator you are interested in, e.g.:
std::string value;
if (std::getline(in, value, ',')) { ... }
reads character until it finds a comma or the end of the file is reached and stores the characters up to the separator in value.
If you just want to read the entire file, one way to do is to use
std::ifstream in(file.c_str());
std::string all((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
I think the best tool for what you're trying to do is get, getline or read. Now those all use char buffers rather than std::strings, so need a bit more thought, but they're quite straightforward really. (edit: std::getline( file, string ), as pointed out by Dietmar Kühl, uses c++ strings rather than character buffers, so I would actually recommend that. Then you won't need to worry about maximum line lengths)
Here's an example which will loop through the entire file:
#include <iostream>
int main () {
char buffer[1024]; // line length is limited to 1023 bytes
std::ifstream file( "this.hash" );
while( file.good( ) ) {
file.getline( buffer, sizeof( buffer ) );
std::string line( buffer ); // convert to c++ string for convenience
// do something with the line
}
return 0;
}
(note that line length is limited to 1023 bytes, and if a line is longer it will be broken into 2 reads. When it's a true newline, you'll see a \n character at the end of the string)
Of course, if you a maximum length for your file in advance, you can just set the buffer accordingly and do away with the loop. If the buffer needs to be very big (more than a couple of kilobytes), you should probably use new char[size] and delete[] instead of the static array, to avoid stack overflows.
and here's a reference page: http://www.cplusplus.com/reference/fstream/ifstream/
I am new to C++ . I am writing following simple code. I wanted to pass the character[40] into a function and then get the same as output.
If i put a debug at following point.
strcpy_s(x,100,tester);
But it only takes "This" if i write "This is sent at the output". Can anyone please point out what am i missing and whats the reason for only accepting few characters.
// BUSTesting.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "resource.h"
int testFunction(char* tester);
int _tmain()
{
char m[40];
std::cin>>m;
testFunction(m);
}
int testFunction(char* tester)
{
char x[100] ;
memset(x,100,sizeof(x));
strcpy_s(x,100,tester);
std::cout<<x;
return 0;
}
operator>> will stop consuming input at first whitespace character. An alternative would be to use cin.getline() to prevent processing of input due to whitespace.
Note to initialize an array and avoid memset():
char x[100] = "";
Recommend std::string and std::getline() which avoids specifying a maximum number of characters to read from the input stream (avoiding potential buffer overrun problems with fixed sized arrays).
Change this: std::cin >> m; to this cin.getline(m, 39);
cin >> x doesn't get all line characters until end-line when there is a white-space (space, tab, ...) in the input.
Since you are using C++, it is better to use std::string class instead of old C-style strings.
std::cin>>m probably breaks the string on a space for some reason. Break with a debugger and check m's content. If it's only this, you've found the problem.
This is so stupid. I've been stuck literally for an hour trying to read in a .txt file of numbers that are separated by a single whitespace. The while loops only gets executed once for some reason!
#include <iostream>
#include <string>
#include <fstream>
#include <stack>
using namespace std;
int main(int argc, char* argv[])
{
string line;
string str(argv[1]);
ifstream myfile((str).c_str());
int num;
stack<int> x;
while (myfile >> num);
{
x.push(num);
}
return(0);
}
Hmm, look at this line more closely:
while (myfile >> num);
Eventually, you'll notice the semi-colon. The compiler thinks this means you want a loop that does nothing (the semi-colon here indicates a single, empty statement). So, the loop reads in all the numbers, but does nothing with them.
The next section is interpreted separately as a statement in its own scope (denoted by the braces), to be executed after the loop:
{
x.push(num);
}
All that does is push the last number read onto the stack, leading you to think the loop only executes once.
Remove the ; and you're OK! Once bitten by this, you'll never forget ;-)
On an unrelated note, it's a bit silly to take argv[1] (a C-style string), put it into a string object, then use c_str() to turn that back into a C-string for the ifstream constructor. Just use argv[1] directly, since you're not doing anything else with it. Also, it would be a good idea to check argc first and make sure that a filename was passed in. Finally, you should check that the file was successfully opened instead of assuming it -- at the very least make your assumption explicit with an assert(myfile.is_open());. Oh, and you don't use the line variable at all.
#include<string>
...
string in;
//How do I store a string from stdin to in?
//
//gets(in) - 16 cannot convert `std::string' to `char*' for argument `1' to
//char* gets (char*)'
//
//scanf("%s",in) also gives some weird error
Similarly, how do I write out in to stdout or to a file??
You are trying to mix C style I/O with C++ types. When using C++ you should use the std::cin and std::cout streams for console input and output.
#include <string>
#include <iostream>
...
std::string in;
std::string out("hello world");
std::cin >> in;
std::cout << out;
But when reading a string std::cin stops reading as soon as it encounters a space or new line. You may want to use std::getline to get a entire line of input from the console.
std::getline(std::cin, in);
You use the same methods with a file (when dealing with non binary data).
std::ofstream ofs("myfile.txt");
ofs << myString;
There are many way to read text from stdin into a std::string. The thing about std::strings though is that they grow as needed, which in turn means they reallocate. Internally a std::string has a pointer to a fixed-length buffer. When the buffer is full and you request to add one or more character onto it, the std::string object will create a new, larger buffer instead of the old one and move all the text to the new buffer.
All this to say that if you know the length of text you are about to read beforehand then you can improve performance by avoiding these reallocations.
#include <iostream>
#include <string>
#include <streambuf>
using namespace std;
// ...
// if you don't know the length of string ahead of time:
string in(istreambuf_iterator<char>(cin), istreambuf_iterator<char>());
// if you do know the length of string:
in.reserve(TEXT_LENGTH);
in.assign(istreambuf_iterator<char>(cin), istreambuf_iterator<char>());
// alternatively (include <algorithm> for this):
copy(istreambuf_iterator<char>(cin), istreambuf_iterator<char>(),
back_inserter(in));
All of the above will copy all text found in stdin, untill end-of-file. If you only want a single line, use std::getline():
#include <string>
#include <iostream>
// ...
string in;
while( getline(cin, in) ) {
// ...
}
If you want a single character, use std::istream::get():
#include <iostream>
// ...
char ch;
while( cin.get(ch) ) {
// ...
}
C++ strings must be read and written using >> and << operators and other C++ equivalents. However, if you want to use scanf as in C, you can always read a string the C++ way and use sscanf with it:
std::string s;
std::getline(cin, s);
sscanf(s.c_str(), "%i%i%c", ...);
The easiest way to output a string is with:
s = "string...";
cout << s;
But printf will work too:
[fixed printf]
printf("%s", s.c_str());
The method c_str() returns a pointer to a null-terminated ASCII string, which can be used by all standard C functions.
I'd like to read whole content of a text file to a std::string object with c++.
With Python, I can write:
text = open("text.txt", "rt").read()
It is very simple and elegant. I hate ugly stuff, so I'd like to know - what is the most elegant way to read a text file with C++?
Thanks.
There are many ways, you pick which is the most elegant for you.
Reading into char*:
ifstream file ("file.txt", ios::in|ios::binary|ios::ate);
if (file.is_open())
{
file.seekg(0, ios::end);
size = file.tellg();
char *contents = new char [size];
file.seekg (0, ios::beg);
file.read (contents, size);
file.close();
//... do something with it
delete [] contents;
}
Into std::string:
std::ifstream in("file.txt");
std::string contents((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
Into vector<char>:
std::ifstream in("file.txt");
std::vector<char> contents((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
Into string, using stringstream:
std::ifstream in("file.txt");
std::stringstream buffer;
buffer << in.rdbuf();
std::string contents(buffer.str());
file.txt is just an example, everything works fine for binary files as well, just make sure you use ios::binary in ifstream constructor.
There's another thread on this subject.
My solutions from this thread (both one-liners):
The nice (see Milan's second solution):
string str((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>());
and the fast:
string str(static_cast<stringstream const&>(stringstream() << ifs.rdbuf()).str());
You seem to speak of elegance as a definite property of "little code". This is ofcourse subjective in some extent. Some would say that omitting all error handling isn't very elegant. Some would say that clear and compact code you understand right away is elegant.
Write your own one-liner function/method which reads the file contents, but make it rigorous and safe underneath the surface and you will have covered both aspects of elegance.
All the best
/Robert
But beware that a c++-string (or more concrete: An STL-string) is as little as a C-String capable of holding a string of arbitraty length - of course not!
Take a look at the member max_size() which gives you the maximum number of characters a string might contain. This is an implementation definied number and may not be portable among different platforms. Visual Studio gives a value of about 4gigs for strings, others might give you only 64k and on 64Bit-platforms it might give you something really huge! It depends and of course normally you will run into a bad_alloc-exception due to memory exhaustion a long time before reaching the 4gig limit...
BTW: max_size() is a member of other STL-containers as well! It will give you the maximum number of elements of a certain type (for which you instanciated the container) which this container will (theoretically) be able to hold.
So, if you're reading from a file of unknow origin you should:
- Check its size and make sure it's smaller than max_size()
- Catch and process bad_alloc-exceptions
And another point:
Why are you keen on reading the file into a string? I would expect to further process it by incrementally parsing it or something, right? So instead of reading it into a string you might as well read it into a stringstream (which basically is just some syntactic sugar for a string) and do the processing. But then you could do the processing directly from the file as well. Because if properly programmed the stringstream could seamlessly be replaced by a filestream, i. e. by the file itself. Or by any other input stream as well, they all share the same members and operators and can thus be seamlessly interchanged!
And for the processing itself: There's also a lot you can have automated by the compiler! E. g. let's say you want to tokenize the string. When defining a proper template the following actions:
- Reading from a file (or a string or any other input stream)
- Tokenizing the content
- pushing all found tokens into an STL-container
- sort the tokens alphabetically
- eleminating any double values
can all(!!) be achived in one single(!) line of C++-code (let aside the template itself and the error handling)! It's just a single call of the function std::copy()! Just google for "token iterator" and you'll get an idea of what I mean. So this appears to me to be even more "elegant" than just reading from a file...
I like Milan's char* way, but with std::string.
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
string& getfile(const string& filename, string& buffer) {
ifstream in(filename.c_str(), ios_base::binary | ios_base::ate);
in.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit);
buffer.resize(in.tellg());
in.seekg(0, ios_base::beg);
in.read(&buffer[0], buffer.size());
return buffer;
}
int main(int argc, char* argv[]) {
if (argc != 2) {
cerr << "Usage: this_executable file_to_read\n";
return EXIT_FAILURE;
}
string buffer;
cout << getfile(argv[1], buffer).size() << "\n";
}
(with or without the ios_base::binary, depending on whether you want newlines tranlated or not. You could also change getfile to just return a string so that you don't have to pass a buffer string in. Then, test to see if the compiler optimizes the copy out when returning.)
However, this might look a little better (and be a lot slower):
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
string getfile(const string& filename) {
ifstream in(filename.c_str(), ios_base::binary);
in.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit);
return string(istreambuf_iterator<char>(in), istreambuf_iterator<char>());
}
int main(int argc, char* argv[]) {
if (argc != 2) {
cerr << "Usage: this_executable file_to_read\n";
return EXIT_FAILURE;
}
cout << getfile(argv[1]).size() << "\n";
}