Changing the ifstream >> operator behaviour in C++ - c++

I am trying to understand how reading from a file using ifstream in C++ can be modified to work as needed. Right now, from my understanding, a single string is read if I use an std::string, where the definition of a string is text delimited by whitespace.
So this would read the work "this" into my std::string.
#include <fstream>
#include <iostream>
#include <string>
int main() {
std::string fname("file.txt");
std::string data;
std::ifstream myfile(fname);
myfile >> data;
myfile.close();
std::cout << "read from file: " << data << std::endl;
exit(0);
}
If file.txt contained the line "this is a string".
What I am wondering, and cannot find, is if I can modify the behaviour of the >> operator, or possibly overload it in a custom class, to change the delimiter. For example, I could read an entire line until a \n is found. I could read delimiting by commas in a CSV file.
Etc.
Is this possible? I'm used to working in C and Python, and my C++ is rather weak.
Thanks.

Related

Reading from file without using string

I am doing a school project where we must not use std::string. How can I do this? In the txt file the data are separated with a ";", and we do not know the length of the words.
Example:
apple1;apple2;apple3
mango1;mango2;mango3
I tried a lot of things, but nothing worked, always got errors.
I tried using getline, but since it is for string it did not work.
I also tried to reload the operator<< but it did not help.
There are two entirely separate getline()'s. One is std::getline(), which takes a std::string as a parameter.
But there's also a member function in std::istream, which works with an array of chars instead of a std::string, eg:
#include <sstream>
#include <iostream>
int main() {
std::istringstream infile{"apple1;apple2;apple3"};
char buffer[256];
while (infile.getline(buffer, sizeof(buffer), ';'))
std::cout << buffer << "\n";
}
Result:
apple1
apple2
apple3
Note: while this fits the school prohibition against using std::string, there's almost no other situation where it makes sense.

How can I open a file based on a file name specified by user input?

I want to make a simple program that will allow the user to create/open files and add text to them. This is the code I have currently:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
cout << "Enter file name:" << endl;
char fileName;
cin >> fileName;
ofstream myFile;
myFile.open(fileName, ios::out);
myFile << "This is the file text.\n";
myFile.close();
return 0;
}
I receive the following error at myFile.open(fileName, ios::out):
error: no matching function for call to 'std::basic_ofstream<char>::open(std::__cxx11::string&, const openmode&)'
The simple problem you are having here is that the variable filename that stores the name of the file is of type char. Change it to string so that it works.
On another note, try to break down the error message you got:
no matching function for call to 'std::basic_ofstream::open(std::__cxx11::string&, const openmode&)'
In open(std::__cxx11::string& ... it clearly says that the data type of the file name should be string&. This indicated that you had a data type error, which is true because you have used char instead of string.
Another thing: use char only when you want to accept a single letter as input; when you want to take a word or a sentence, store it in a string variable, and get it from the user using the getline() function. This will make your life easier.
To modify your code, firstly change your variable declaration statement to:
string fileName; // std:: is not required as you have the line "using namespace std"
Secondly, change the input statement of the file name from cin >> filename; to:
getline(cin, fileName);
It should work after these changes.
EDIT: I found the peoblem to your question. You will nave to change the open command to:
myFile.open(fileName.c_str(), ios::out);
Like it says in the error, the function needs a string passed to ot, however, when we take the string as input and store it in the variable fileName, it simply converts the string into a const char *. This is invisible to you when you run the code, but every once in a while, it causes an error.
This should definitely work now.
If you take a look at the error message, the first half of what is in the open parentheses tells you the answer. The user is typing in a char, the file name is expected to be a string. Instead of:
char fileName;
Use:
string fileName;

no matching function to call for "getline"

I'm new to c++ programming. In a tutorial, the author mentioned "cin" will break if it reads a space in a string. If you want the program to read in an entire line of string with spaces, you should use the function "getline".
However, I couldn't make it work.
Here are my codes:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string my_name;
cout << "Please enter your name: ";
getline(cin, my_name, "\n");
cout << "My name is " << my_name << " .";
}
The IDE I am using is Xcode. The error message is "No matching function to call to 'getline'".
I have searched for similar issues but it seems to me none of the solutions apply to my problem. Maybe I am missing some knowledge? Thank you.
The complete error would tell you why your third parameter is of the wrong type.
It should be a character type, not a null-terminated string of characters.
getline(cin, my_name, '\n');
Edit: And, '\n' specifically is the assumed delimiter in another form of getline:
getline(cin, my_name);
What your teacher said is not true. cin will not "break". It's just that formatted extraction into an std::string is designed to read word by word. That's intentional. It's not broken.
As for your error, your call to std::getline is broken because the delimiter argument has the wrong type. '\n' is a char literal; "\n" is a char array literal, not at all what you wanted.
add this line work for me
#include <fstream>
If you change it to a char array you can use:
cin.getline(my_name, val_max);
Just make sure your buffer (val_max) is large enough

Difference between using ifstream and ofstream with cin and cout

I read about fstream, etc., a while ago. It says that ifstream is used to read data from a file, while ofstream is used to write data. I want to know that, what is the essence of using ifstream/ofstream if you can just use cin.getline() to fetch the data and cout << to print those?
ifstream: Stream class to read from files
ofstream: Stream class to write to files
Now what is a file?
Files are resources for storing information. For example, a text file.
Now, let's look at an example which explains ofstream.
Look at the following code:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();
return 0;
}
Here, we are writing something to a file. Writing information you can say.
Now, what is the difference between cin/cout and ifstream/ofstream?
cin is an object of class istream and cout is an object of class ostream. And in fact, we can use our file streams the same way we are already used to using cin and cout, with the only difference being that we have to associate these streams with physical files. Just think that cin/cout is a part of istream/ostream that is used for standard input/output.
Hope it helps a bit.
For more information, you can look at this link:
Input/output with files.
Ifstream()
ifstream() is used to input the file.
ifstream() is fstream() object it is used to input the single character or string or set of character to a file
it inherits the function get(), getline(), read(), etc...
Ofstream()
ofstream() is used to output the file
ofstream() is fstream() object it is used to output the single character or string or set of character from a file
it inherits the function put(), write(), etc...

How to read and write a STL C++ string?

#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.