• Advertisement
Sign in to follow this  

Spaces in string

This topic is 4798 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

say I have the source:
#include <iostream>
#include <string>
using namespace std;
int main() {
    string inventory[9];
    string item;
    cout<<"What would you like to add to the inventory?"<<endl;
    cin>>item;
    inventory[0] = item;
    cout<<inventory[0]<<endl;
    return 0;
}

I typed in "Long Sword" as what I want to add to the inventory, but when it throws it back, it only says long. So this tells me you cant have spaces in string. How can I get it so I can have spaces?

Share this post


Link to post
Share on other sites
Advertisement
I think cin.getline() is used like..

cin.getline(VarToStoreEnteredStringIn, HowManyChars);
soo..

cout << "Enter whatever you want:";
cin.getline(inventory, 255);


i'm pretty sure thats how it works, keep checking back though, if I'm wrong i'm sure someone will correct me..

Share this post


Link to post
Share on other sites
what getline does is pulls all the characters until you get to the line break character (hence getline) and places it into a buffer you create. (there's a few other details and options, but I won't go into them for simplicity ;) example:


char buffer[255];
cin.getline(buffer, 255);



would grab everything before a line break (up to 255 characters max, hence the 255)

Share this post


Link to post
Share on other sites
I get an error.
Compiler: Default compiler
Executing g++.exe...
g++.exe "C:\Documents and Settings\HP_Owner\Desktop\Test.cpp" -o "C:\Documents and Settings\HP_Owner\Desktop\Test.exe" -I"C:\Dev-Cpp\include\c++\3.3.1" -I"C:\Dev-Cpp\include\c++\3.3.1\mingw32" -I"C:\Dev-Cpp\include\c++\3.3.1\backward" -I"C:\Dev-Cpp\lib\gcc-lib\mingw32\3.3.1\include" -I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib"
C:/Documents and Settings/HP_Owner/Desktop/Test.cpp: In function `int main()':

C:/Documents and Settings/HP_Owner/Desktop/Test.cpp:8: error: no matching
function for call to `std::basic_istream<char, std::char_traits<char> >::
getline(std::string&, int)'
C:/Dev-Cpp/include/c++/3.3.1/bits/istream.tcc:664: error: candidates are:
std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT,
_Traits>::getline(_CharT*, int, _CharT) [with _CharT = char, _Traits =
std::char_traits<char>]
C:/Dev-Cpp/include/c++/3.3.1/istream:401: error:
std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT,
_Traits>::getline(_CharT*, int) [with _CharT = char, _Traits =
std::char_traits<char>]
C:/Documents and Settings/HP_Owner/Desktop/Test.cpp:9: error: syntax error
before `[' token

Execution terminated
correction errors. hehe

Share this post


Link to post
Share on other sites
Now its different, ive changed a little, but still have errors.
[source lang = "cpp]
#include <iostream>
#include <string>
using namespace std;
int main() {
string inventory[9];
for(int i=0; i<=9; i++)
{
cout<<"What would you like to add to the inventory?"<<endl;
cin.getline(inventory, 20);
}
for(int x=0; x<9; x++)
{
cout<<inventory[x]<<endl;
}
return 0;
}


and then the errors are

Executing g++.exe...
g++.exe "C:\Documents and Settings\HP_Owner\Desktop\Test.cpp" -o "C:\Documents and Settings\HP_Owner\Desktop\Test.exe" -I"C:\Dev-Cpp\include\c++\3.3.1" -I"C:\Dev-Cpp\include\c++\3.3.1\mingw32" -I"C:\Dev-Cpp\include\c++\3.3.1\backward" -I"C:\Dev-Cpp\lib\gcc-lib\mingw32\3.3.1\include" -I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib"
C:/Documents and Settings/HP_Owner/Desktop/Test.cpp: In function `int main()':

C:/Documents and Settings/HP_Owner/Desktop/Test.cpp:9: error: no matching
function for call to `std::basic_istream<char, std::char_traits<char> >::
getline(std::string&, int)'
C:/Dev-Cpp/include/c++/3.3.1/bits/istream.tcc:664: error: candidates are:
std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT,
_Traits>::getline(_CharT*, int, _CharT) [with _CharT = char, _Traits =
std::char_traits<char>]
C:/Dev-Cpp/include/c++/3.3.1/istream:401: error:
std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT,
_Traits>::getline(_CharT*, int) [with _CharT = char, _Traits =
std::char_traits<char>]

Execution terminated

Share this post


Link to post
Share on other sites
heres how I made it..i'm sure its not the most effective..but it works


#include <iostream>
using namespace std;
int main()
{
string inventory[9];


for (int a=0; a<=9; a++ )
{
//make a buffer
char buffer[255];
//ask for the item
cout << "enter inventory item " << a <<": ";
//collect whatever the user entered..up to 255 chars
cin.getline(buffer, 255);
//set the buffer equal to the string
inventory[a] = buffer;
//display the new inventory item
cout << inventory[a].c_str();
}



return 0;
}

Share this post


Link to post
Share on other sites
as above, its probably a problem putting them into a string, put it into an array if chars first, and then put that into the string.

Share this post


Link to post
Share on other sites
Try
getline(cin, item);

OT: don't suggest to read into char array and then convert from char to string, please. a:you already have function that reads line into string and does it well, b:it is inelegant to read into char and then copy&convert, c: and inefficient, d: length of buffer is limited, e: you can get buffer overflow errors, i think.

Share this post


Link to post
Share on other sites
@Dmytry: You aren't going to get buffer overflow errors as long as you pass a correct size parameter - not due to the getline call itself, anyway. But your points are otherwise well taken, enough so that I am going to go into more detail on the whole topic ;)

cin.getline() - the getline member function of the istream object named cin - expects a character array as a buffer to hold its input. That's why it bothers asking for a length - you supply the length of the buffer, because it's Bad News (TM) if the data you're trying to read is longer than that and there isn't a safeguard. With this form, the code will stop reading if the buffer is full, even if the line isn't done yet. If you don't know how long lines can be (just that they could potentially be very long), then you are left with distasteful options:

1) just using a really big buffer and praying it's enough, while wasting that space most of the time.
2) Reading in a buffer-full at a time, doing some checking to see if the line is done, and appending the buffer to somewhere else - meanwhile, that somewhere else is either another 'really big buffer' (in which case you haven't really solved anything), or you have to keep reallocating it (i.e. do a bunch of tricky low-level memory allocation work).

Since using raw character arrays and pointers to represent text is already a very messy business (even without worrying about Unicode), we would like to be able to get a line into a std::string. This is also done using getline - this is a free function named getline, though. It takes the stream to read from as a parameter, as well as the string to read into. The stream has to be specified because it's no longer implicit (since this isn't a member function). The size is no longer needed, because std::string will resize itself as needed (just one of its many advantages over working with plain char *'s).

Thus:

#include <iostream>
#include <string>
using namespace std;
int main() {
string inventory[9];
string item;
cout<<"What would you like to add to the inventory?"<<endl;
getline(cin,item); // Ahhh... much better.
inventory[0] = item;
cout<<inventory[0]<<endl;
// BTW, you don't need a temporary string 'item'; you can getline directly
// to inventory. It won't likely make any difference in the compiled code,
// so it boils down to what you find more readable. I usually find more
// compact things to be more readable - when they aren't, I start to wonder
// about the quality of my variable names ;)
return 0;
}



Of course, this raises a few questions...

Q. Why do we need to have a free function like this? Can't the member function getline() be overloaded to take a std::string?

A. Apparently there were some kind of technical difficulties with this? I would appreciate if someone could fill in technical details, although it'd almost certainly be way over the OP's head and quite possibly over mine too ;)

Q. Given that only one of the two could be implemented as a member function, why not do it the other way around?

A. Your guess is as good as mine... There may have been motivation to emphasize the first version in the early days of C++, since people were used to everything being as close to the metal as feasible and distrusted the new-fangled std::string. Actually, I suppose iostream.h-for-C++ - and even the first version of 'iostream' - predate std::string. Or perhaps the answer to question 1 renders this all moot...

Share this post


Link to post
Share on other sites
offtopic:
in C++ you can not add methods to existing class without changing this class. I had been stuck with this problem several times. When i have some class hierarchy i shouldn't change, but want to add some method to common parent, the only possibility is to change that parent, but in some cases you can't change existing code.(e.g. if it is standard) so you have to do things in non-OOP way. It especially sucks if you need to add virtual member. In this case, you need to code inheritance manually. I had to do it at least 2 times for converting from one tree-like structure to other tree-like structure.

buffer overflow: even if it doesn't overwrite anything in ram, if it behaves in unexpected way for long strings, there's still a problem. For example, it is implementation of some stream/protocol/something. If , for example, SQL queries will be passed through it, it may become possible to make exploit using this string trimming. to do evil job

Let you pass string like
`store "user-provided data here", a+b+c+d'
If user-provided data is long, a+b+c+d might be truncated out of string.
Or you pass 2 strings that is concatenated, truncation can be used to trim out quotes and make code injection be possible.

Or you might get no terminating zero if line is longer than buffer length.

Share this post


Link to post
Share on other sites
Okay, I got it, and then had a problem with which space the "item" goes into, so I'm converting it to vector. I have it all good, but how do I output a vector?

Share this post


Link to post
Share on other sites
Quote:
Original post by Meta Adam
...how do I output a vector?
You don't output a vector, you output the elements of a vector. You can either select the element to output manually (via indexing, or a loop), or you can use std::copy and a std::ostream_iterator.

using namespace std;

vector<string> inventory;
...
// fill inventory
...
ostream_iterator<string> out(cout, "\n");
copy(inventory.begin(), inventory.end(), out);

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement