2

In my basic Linux Programming course at college, we use fcntl.h and unistd.h Using C++ strings, I get the following:

statusOfFunction = write(fileDescriptor, input.c_str(), input.length());

This line works. I get a file created, with the contents of input string. But, why doesn't any of these lines work:

statusOfFunction = read(fileDescriptor, reading.c_str(), 10);
Error: No matching function call to "read"

statusOfFunction = read(fileDescriptor, reading, 10);
Error: No matching function call to "read"

statusOfFunction = read(fileDescriptor, &reading, 10);
No error throws up, but does not get executed

statusOfFunction = read(fileDescriptor, &reading.c_str(), 10);
Error: No matching function call to "read"

https://www.dropbox.com/s/lnw208uo3xurqxf/Basic%20Unix%20Operations%20on%20Text%20Files.cpp?dl=0

Here is the program, for your reference. Thank you! :)

  • What's `reading`? You need to match the prototype to `read`, which according to `man 2 read` is `ssize_t read(int fd, void *buf, size_t count);` so you need reading to be a void pointer to a buffer large enough to hold 10 bytes (or whatever your `count` is). – Petr Skocik Sep 23 '14 at 08:51
  • In your basic Linux Programming course, have they not-yet-covered what `const` means? – WhozCraig Sep 23 '14 at 08:56

2 Answers2

0

The problem with the first

statusOfFunction = read(fileDescriptor, reading.c_str(), 10);

is that c_str is declared to return a const pointer. Otherwise this is the closes to the correct method.

First of all you need to create a string that contains at least 10 characters:

std::string temp_string(10, ' ');  // Creates a string contains 10 spaces

Then you need to pass a non-constant pointer, which you can get by using the address-of operator & and the strings array-indexing operator []:

statusOfFunction = read(fileDescriptor, &temp_string[0], temp_string.length());

And finally you assign it to the actual string:

reading = std::string(temp_string, 0, statusOfFunction);

Of course, you should check statusOfFunction so it's not an error (when it -1) or end of file (when its 0).


All the other methods you tried for reading are just very wrong.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • It still does not work :( https://www.dropbox.com/s/lnw208uo3xurqxf/Basic%20Unix%20Operations%20on%20Text%20Files.cpp?dl=0 Please check the code. Am I wrong anywhere? – Nadeem Ahmed Najeeb Sep 23 '14 at 10:44
  • @NadeemAhmedNajeeb For starters, you miss the bit where I tell you to create the string with memory allocated for it. What you do in the linked code is read into an empty string, leading to undefined behavior. – Some programmer dude Sep 23 '14 at 11:04
  • I did try, but I get an error then too: std:: string sample(10); No matching constructor for initialisation Also, I tried using sample[10], thinking [] might be overloaded. Turns out I am wrong there too – Nadeem Ahmed Najeeb Sep 23 '14 at 11:06
  • @NadeemAhmedNajeeb Sorry, I forgot that the constructor needs extra arguments, updated answer. The major problem here is that you are using `std::string` for something it's not really designed for. And `operator[]` *is* overloaded in the [`std::string`](http://en.cppreference.com/w/cpp/string/basic_string) class, please read the linked reference. – Some programmer dude Sep 23 '14 at 11:12
  • Joachim, thanks a ton! :) The two things I missed out of my code, both you rectified: 1 Missed out: lseek(fileDescriptor, 0, SEEK_SET); 2 The missing argument in the constructor – Nadeem Ahmed Najeeb Sep 23 '14 at 11:28
0

read expects a buffer to fill the data read.

What you're doing is dangerous.

You should allocate a char buffer and make sure you add the NULL char after the string length as read will not do it for you. the c_str function exposes the internal buffer used by the string class. It is read only.

Overwriting the string object itself will cause a crash for sure when later used.

char buff[11];
size_t bytes_read = read(fd, buff, 10);
buff[bytes_read] = 0; // terminate string
string myString(buff);
egur
  • 7,830
  • 2
  • 27
  • 47