Zat42
Zat42

Reputation: 2911

Is it possible to use an std::string for read()?

Is it possible to use an std::string for read() ?

Example :

std::string data;

read(fd, data, 42);

Normaly, we have to use char* but is it possible to directly use a std::string ? (I prefer don't create a char* for store the result)

Thank's

Upvotes: 12

Views: 8835

Answers (6)

Gary Robinson
Gary Robinson

Reputation: 341

Using std::getline from the strings library - see cplusplus.com - can read from an stream and write directly into a string object. Example (again ripped from cplusplus.com - 1st hit on google for getline):

int main () {
  string str;
  cout << "Please enter full name: ";
  getline (cin,str);
  cout << "Thank you, " << str << ".\n";
}

So will work when reading from stdin (cin) and from a file (ifstream).

Upvotes: -1

stefaanv
stefaanv

Reputation: 14392

Because read() is intended for raw data input, std::string is actually a bad choice, because std::string handles text. std::vector seems like the right choice to handle raw data.

Upvotes: 0

James Kanze
James Kanze

Reputation: 153919

Well, you'll need to create a char* somehow, since that's what the function requires. (BTW: you are talking about the Posix function read, aren't you, and not std::istream::read?) The problem isn't the char*, it's what the char* points to (which I suspect is what you actually meant).

The simplest and usual solution here would be to use a local array:

char buffer[43];
int len = read(fd, buffer, 42);
if ( len < 0 ) {
    //  read error...
} else if ( len == 0 ) {
    //  eof...
} else {
    std::string data(buffer, len);
}

If you want to capture directly into an std::string, however, this is possible (although not necessarily a good idea):

std::string data;
data.resize( 42 );
int len = read( fd, &data[0], data.size() );
//  error handling as above...
data.resize( len );  //  If no error...

This avoids the copy, but quite frankly... The copy is insignificant compared to the time necessary for the actual read and for the allocation of the memory in the string. This also has the (probably negligible) disadvantage of the resulting string having an actual buffer of 42 bytes (rounded up to whatever), rather than just the minimum necessary for the characters actually read.

(And since people sometimes raise the issue, with regards to the contiguity of the memory in std:;string: this was an issue ten or more years ago. The original specifications for std::string were designed expressedly to allow non-contiguous implementations, along the lines of the then popular rope class. In practice, no implementor found this to be useful, and people did start assuming contiguity. At which point, the standards committee decided to align the standard with existing practice, and require contiguity. So... no implementation has ever not been contiguous, and no future implementation will forego contiguity, given the requirements in C++11.)

Upvotes: 14

DRVic
DRVic

Reputation: 2481

No, but

std::string data;
cin >> data;

works just fine. If you really want the behaviour of read(2), then you need to allocate and manage your own buffer of chars.

Upvotes: 0

user1202136
user1202136

Reputation: 11567

No, you cannot and you should not. Usually, std::string implementations internally store other information such as the size of the allocated memory and the length of the actual string. C++ documentation explicitly states that modifying values returned by c_str() or data() results in undefined behaviour.

Upvotes: 1

Anon Mail
Anon Mail

Reputation: 4770

If the read function requires a char *, then no. You could use the address of the first element of a std::vector of char as long as it's been resized first. I don't think old (pre C++11) strings are guarenteed to have contiguous memory otherwise you could do something similar with the string.

Upvotes: 0

Related Questions