Help With Inputting Strings
I know this is probably a very stupid question, but I can't make the user input a string.I thought I could use cin...here is my code:
#include<iostream>
//#include<cstdlib>
//#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int x=0;
string thing[10];
cin>>thing;
//x=atoi(thing.c_str());
//cout<<x;
system("pause");
return 0;
}
I then get an error message saying: error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'std::string [10]' (or there is no acceptable conversion)
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
You are confounding c-style strings and stl strings.
An old c-style string:
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
char name[ 100 ]; // this is an array of characters
cout << "Please enter your name> ";
cin.getline( name, 100 );
cout << "Hello " << name << "!\n";
return 0;
}
An STL string:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name; // this is a string object. It has no maximum size
cout << "Please enter your name> ";
getline( cin, name );
cout << "Hello " << name << "!\n";
return 0;
}
When you say string foo[ 10 ]; you are saying that 'foo' is an array of ten string objects... probably not what you meant.
Hope this helps.
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
I had thought that I didn't need to allocate the size. Are you sure that there is no way to do that with gets() or cin. I always thought that that was proper code for inputting strings...But I tried your way and it does work.
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
I was testing it out and I saw that it stops at the first whitespace. There has to be a different way.
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
Now you have confused me.
You don't need to allocate the size of a std::string --that's the whole point. But you do need to specify the size of a c-style character array.
Both my methods are correct.
Both use cin.
Never use gets(). (It is pure evil, and should be shot.)
If you want to use the old stdio functions to input c-strings, use fgets()
#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
char name[ 100 ]; // this is an array of characters
char *p;
cout.sync_with_stdio();
cout << "Please enter your name> ";
fgets( name, 100, stdin );
if (p = strchr( name, '\n' )) *p = '\0';
cout << "Hello " << name << "!\n";
return 0;
}
Notice how on line 12 I had to manually remove the newline (from the ENTER key) from the input string.
[edit]
Neither incarnation ofgetline() stops at the first whitespace unless you tell it to. They stop at the end of the line.
However, cin >> foo; does stop at the first whitespace.
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
its the atoi function that stopped at the first whitespace. I thought it was the getline.
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
Ah, yes, the venerable old atoi(). ;)
You know you can use a stringstream instead?
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
string s;
cout << "Enter a number> ";
getline( cin, s );
long n;
if (!(stringstream( s ) >> n))
cout << "That wasn't a very good number\n";
else
cout << n << " * 2 = " << (n * 2) << endl;
return 0;
}
:)
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
Thanks-in another thread someone also suggested stringstreams when i was having trouble with atoi(). One last stupid question, when i use the header the cin>>str; works but not when I use but in this book I'm reading-"C++ From the Ground Up" by Herbert Schildt-he always uses for char strings. So what's the difference between and
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
is the old C library: strlen(), strchr(), memcpy(), etc.
is the C++ STL strings library: std::basic_string<> and descendants (string, wstring).
The latest version of that book is five years old... but I have no clue why he is dinking around with stuff in anyway... Perhaps he just wants you to understand what is going on behind the scenes.
STL containers exist to do a lot of the dirty work for you. A "string" in C and C++ is always just an array of characters. However, in C++, you can use the std::string class to manage that array dynamically and transparently.
That is why in the examples above I noted that the string object has no maximum size (well, it does, but you'll never have a string that large), because it will make sure its char array is always big enough to hold the entire string.
cin >> str; works by using a trick calledoperator overloading. What actually happens is a special function gets called depending on what type of thing str is.
char s[ 100 ];
cin >> s;
// same as
operator >> ( (istream)cin, (char*)s );
string s;
cin >> s;
// same as
operator >> ( (istream)cin, (string&)s );
In each case there is a function named " operator >> ". It is indeed an odd name for a function --normally functions are named " read_string " or something like that. But the next thing to notice is that there aretwo functions with the same name: one that takes a char* as argument and another that takes a std::string. The compiler is smart enough to figure out which one to call so all you (the programmer) ever have to think is
cin >> s; // input my 's' (i don't care about the details)
This makes it so that you only have to care about how a specific kind of thing is extracted from an input stream in one place: where you define the overloaded function. Everywhere else you have a simple, uncluttered, easy-to-read expression that looks the same no matter what type of object you are reading fromcin.
Hope that made sense.
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
Wow you know a lot strings-thanks. After reading it over a few times I understood it. Do you think that the book is too old (is it now outdated)?
Here is an example of when he uses #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
char str[80];
cout<<"enter a string";
gets(str);
cout<<"The Length is: " <<strlen(str);
system("pause");
return 0;
}
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
Ya he didn't even put a system pause or anything to let the user see the length before the program ended-i had to add that in.
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
Actually, putting that system pause in there contributed to my low opinion. You said that was an example of when he uses .
gets() is pure evil and should be lynched at every opportunity.
Using c-strings in a C++ program, outside of any need to interface with legacy code, is considered anachronistic and silly. It is kind of like building your own car to drive to the grocery --when a premade vehicle would cost less and be more convenient.
system( "anything" ) is resource heavy and a big security hole. It should not be taught as a convenience to do stupid or trivial stuff. I've nothing against using it in your own code, temporarily, to subdue your IDE, but it shouldn't ever find its way into production code. In the case of "pause", "cls", "title", etc, it also puts surprise restrictions on your program. Stream applications shouldn't demand human attention to operate.
Alas. C++ is a big world. And a lot of it is still stuck in C on MSDOS.
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
It is his program, but if anyone ran it it would just close down immidiately. What do you suggest instead of system("pause")?
Wait, so you hate the gets() because it builds a new string-right?
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
Why gets() is black, unpropitious, immoral, and wrong. (click me)
Well, since you asked ;) , I personally suggest
#include <iostream>
#include <limits>
...
std::cout << "Press ENTER to continue...";
std::cin.ignore( std::numeric_limits <std::streamsize> ::max(), '\n' );
But that's not the only good solution. I didn't say "never use system()". I just said "know what you are doing".
The reason the console window closes immediately has nothing to do with the program. Your IDE is too stupid to keep it open until you explicitly close it. A common affliction, alas.
:sad: :)
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
Ohh. Why don't you put using namespace std; ?
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0
No good reason. Either works.
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
CPPRULZ
Junior Poster in Training
91 posts since Aug 2008
Reputation Points: 10
Solved Threads: 0