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
Related
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.
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;
How this program should work:
Enter 4 words:
this is bad
Bad input.
and
Enter 4 words:
hello you love it
Good input.
How I tried it:
#include <iostream>
#include <string>
using namespace std;
int main(void) {
cout << "Enter 4 words:" << endl;
string a, b, c, d;
cin >> a >> b >> c >> d;
}
It reads input after end of the line and I can't figure out how to limit it only to one line. Can you please point me what function I should use? I'll be very grateful for every answer.
Thank you all!
std::getline() should be used when the program's expected input comes from an interactive terminal.
That's what std::getline() does: it reads text until the newline character. operator>> doesn't do that, that's what std::getline() does, and that's what should be used to process a line of typed-in text. Use the right tool, for the right job.
Sadly, many C++ books and tutorials introduce >> too early, before introducing std::getline(), and use it in their examples, simply because it's easier and more convenient to have >> handle the required data type conversion. Unfortunately, this results in a wrong mindset settling in, where >> is thought to be the automatic choice for processing interactive input. It is not.
The correct approach is to use std::getline(). Then, if necessary, construct a std::istringstream, and use that to handle any type conversions from the entered input. Not only does that solve the immediate problem, it also solves the problem of unparsable input putting std::cin into a failed state, with all subsequent attempted input conversions failing as well -- that's another common pitfall.
So, use std::getline(), first:
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
int main(void) {
std::cout << "Enter 4 words:" << endl;
std::string line;
std::getline(std::cin, line);
And now, once the line of text is entered, it can be converted to a std::istringstream:
std::istringstream i(line);
Followed by a loop to repeatedly invoke >> in order to count the words in this line. This part you can finish yourself.
P.S. Another common pitfall is using namespace std;. You should not do that, as well. The earlier good programming practices are acquired, the easier the subsequent road on the path towards C++ guru-ism will be.
You should use following command:
std::getline()
This ignore the eventual space as a quote terminating string and you can store the value inside a variable, then see how much words are inside that.
Example:
std::getline (std::cin,name);
Ok thanks for the answer Wug! I changed my code but now it's complaining about:
no matching function for call to
std::basic_ofstream::basic_ofstream(std::basic_string)
I'm not sure it makes any difference but i'll just post all of my code it's not that much so far.
I'll try to keep it cleaner from now on.
#include <iostream>
#include <windows.h>
#include <direct.h>
#include <fstream>
using namespace std;
int main()
{ /*Introduction*/
SetConsoleTitle("Journal");
string action, prom0, filename, filepath;
filepath = "C:\\Users\\-\\Desktop\\Projects\\Journal Project\\Logs\\";
cout << "Hi and welcome to Journal! \nHere you can write down your day.\nWrite help for";
cout << "more \nType command to start: ";
/*Choose Action*/
cin >> action;
if (action == "new")
{system("cls");
/*Make new Journal file*/
cout << "Filename: ";
getline(cin, filename);
mkdir("C:\\Users\\-\\Desktop\\Projects\\Journal Project\\Logs");
ofstream journallogs(filepath + filename);
journallogs.close();
}
else {
cout << "Wrong command\n";
};
return 0;}
There are 2 things wrong. The first is what the compiler's complaining about:
ofstream journallogs("C:\\Users\\-\\Desktop\\Projects\\Journal Project\\Logs\\" + getline(cin, filename), ios::out);
std::getline(istream&, string&) returns istream&, and you can't add char * to istream. I recommend taking a look at the documentation for getline(), which might help you understand better how you're supposed to use it. Here's an example anyway:
string filepath = "C:\\Users\\-\\Desktop\\Projects\\Journal Project\\Logs\\";
string filename;
getline(cin, filename);
ofstream journallogs(filepath + filename);
The second problem is that you're reading from cin into filename before calling getline(). When you call getline(), any contents of filename are dropped, so you'll effectively trim the first word off of your filename, which probably isn't what you want. To fix that, remove the extraneous cin >> filename;
Note: indentation is important and helps you read your own code. Put forth the effort to keep your code looking nice.
First, learn this:
Start small and simple.
Add complexity a little at a time.
Test at every step.
develop new functionality in isolation.
Never add to code that doesn't work.
For the rest, I don't use Windows, so I can't be certain my code will work there, but the approach will.
You are trying to 1) get a filename from the user, 2) modify it and then 3) use it to open a file; we will develop these three things in isolation.
Getting a filename from the user. Civilized filenames do not contain whitespace, so they can be read with cin, but if you want to allow whitespace you can use getline instead. Either way, test it.
Modifying the filename. Write code that assigns a value to the filename, just as it does to the path-- do not get the filename from the user, it slows down your testing and is not proper isolation. Now try to append them. If you try filepath + filename, you may get a compiler error. Here's where you must understand the difference between std::string and char[]. A char[] is an array of char, and it (usually) contains a null-terminated sequence of characters; you must read up on arrays and pointers. It is a primitive type, and you cannot simply concatenate two of them with '+', you must use something like strcat, which is dangerous if you haven't done your homework on arrays. On the other hand, std::string is more sophisticated, and can handle '+' and many other operations. If you have a std::string x and you decide you want a char[] after all, you can get one like so: x.c_str().
Opening the file. If I remember right, the ofstream constructor can take a char[], but not a std::string. Test this with a hard-coded string (isolation!).
Once you have these three components working independently, you can hook them together.
Here is the code:
// pointers to structures
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct movies_t {
string title;
int year;
};
int main ()
{
string mystr;
movies_t amovie;
movies_t * pmovie;
pmovie = &amovie;
cout << "Enter title: ";
getline (cin, pmovie->title);
cout << "Enter year: ";
getline (cin, mystr);
(stringstream) mystr >> pmovie->year;
cout << "\nYou have entered:\n";
cout << pmovie->title;
cout << " (" << pmovie->year << ")\n";
return 0;
}
Taken from http://www.cplusplus.com/doc/tutorial/structures/. I was hoping I could get clarification on a few things.
What is getline and how does it work? I tried looking up the documentation, but I'm still having trouble understanding. Also, what exactly is cin and how is it being used with getline?
If I understand correctly, pmovie->title essentially says that pmovie points to the member title of the object amovie? If so, and it's not already clear from the explanation to #1, how does getline (cin, pmovie->title) work?
Now this (stringstream) mystr >> pmovie->year is giving me the most trouble. What is a stringstream, and are we using it like we would cast a double as a int, for example?
Thank you all!
What is getline and how does it work? I tried looking up the documentation, but I'm still having trouble understanding. Also, what exactly is cin and how is it being used with getline?
The getline function reads a line from a istream. The cin stream refers to your standard input stream, the one you would normally get input from. It is being passed to getline to tell it which input stream to get a line from.
If I understand correctly, pmovie->title essentially says that pmovie points to the member title of the object amovie? If so, and it's not already clear from the explanation to #1, how does getline (cin, pmovie->title) work?
The getline functions reads a line from cin and stores it in pmovie->title which is passed by reference.
Now this (stringstream) mystr >> pmovie->year is giving me the most trouble. What is a stringstream, and are we using it like we would cast a double as a int, for example?
A stringstream is a class that makes a string act like a stream. This is kind of confusing syntax (C-style cast) that makes it a bit harder to understand what it is happening. Basically, a temporary stringstream is created and initialized with the contents of mystr. A stringstream, when initialized with a string, gives you a stream from which you can read those contents. The >> operator reads from an output stream, in this case, into pmovie->year, which is again passed by reference.
By the way, it seems to me like you're trying to understand unusually complex and confusing uses without yet understanding the more basic uses of these objects. That's a very hard way to learn.
Most of the questions don't seem to be about structures at all. So, I'm addressing the issue which is related to the title rather than those about streams:
If I understand correctly, pmovie->title essentially says that pmovie points to the member title of the object amovie? If so, and it's not already clear from the explanation to #1, how does getline (cin, pmovie->title) work?
You misunderstand. I would guess, that this is the root of your confusion: pmovie points to a movies_t object. As it happens, in the sample code it is initialized to point to the movies_t object named amovie.
Now, each movies_t object has two members, i.e., subobjects: a title and a year. To access the title component of a movies_t pointed to by a pointer you use pmovie->title. To access the year component instead you'd use pmovie->year.
The one thing I say about streams, though, is this: You should always check that your input was successful before assuming the read was successful. For example, you would check that reading a line was successful using
if (std::getline(std::cin, pmovie->title)) {
// deal with a successfully read title
}
cin is a special stream defined by C++ to work with standard output (usually the keyboard, but can be almost anything). getline is a function that allows you to read text from a stream into a buffer until the platform's line ending is encountered (Line Feed on UNIX, Carriage Return Line Feed of Windows and DOS).
pmovie->title says that pmove is a pointer to a structure that has a member called title. This refers to that member. Because getline takes a string& (String reference), it happily accepts the string referenced by pmovie->title.
stringstream defines an implicit constructor that converts strings to stringstreams. the >> operator gets input from a string and converts it to the target type (the type of the operand to the right of the >>) and puts it there. This is just a way of converting a string to an integer.