I am reading Bjarne Stroustrup's "Programming Principles and Practice Using C " (second edition). On page 660-661, the writers define a function as follows:
istream& read_word(istream& is, char* buffer, int max)
// read at most max-1 characters from is into buffer
{
is.width(max); // read at most max-1 characters in the next >>
is >> buffer; // read whitespace-terminated word,
// add zero after the last character read into buffer
return is;
}
Later in int main()
, the function is called as read_word(cin,s,max);
where cin
is std::cin
, max
is an int
, and s
is a char
array of size max
.
I don't understand how is >> buffer;
works. In particular, that line gives an error when I tried to run the code:
C2679 binary '>>': no operator found which takes a right-hand operand of type 'char *' (or there is no acceptable conversion)
There is no user-defined operator>>
or further explanation on that line (except the comment) in the book.
I wonder if we can use things like is >> buffer;
in any meaningful way? If so, how does it work? Or is this an error in the book?
Update: I'm using Visual Studio 2022. I found that the code runs successfully with C 14/17, but not with C 20. The results are similar for clang and gcc.
CodePudding user response:
The std::basic_istream::operator >>
overload that takes a char*
argument (overload #2 in this cppreference page) was removed in C 20. This change will, no doubt, break huge amounts of existing code, including examples given by Bjarne Stroustrup himself!
The C 20 replacement, taking a char (&s)[N]
argument instead, seems (to me, at least) far less accessible. One way to adapt to this change is to rewrite the read_word
function as a template, when you would no longer require the explicit max
argument and the call to is.width()
:
template <size_t N>
std::istream& read_word(std::istream& is, char (&buffer)[N])
{
is >> buffer;
return is;
}
However, as mentioned in Alan Birtles' answer, you should really be moving away from raw char[]
arrays and start using std::string
, instead.
CodePudding user response:
The stream operator taking a raw char pointer has been replaced with one taking a fixed sized char array in c 20. The simplest solution is to use std::string
instead.
To use an array your code would be something like:
template <size_t N>
istream& read_word(istream& is, char (&buffer)[N], int max)
// read at most max-1 characters from is into buffer
{
is.width(max); // read at most max-1 characters in the next >>
is >> buffer; // read whitespace-terminated word,
// add zero after the last character read into buffer
return is;
}
Note that this will now read at most N-1
characters, if N
and max
are the same then you can omit max
and the width
call.