C++primer 5th about func parameter - c++

Its question is" Give the second parameter of make_plural (ยง 6.3.2, p. 224) a default argument of 's'. Test your program by printing singular and plural versions of the words success and failure"
here is the make_plural.
string make_plural(size_t ctr, const string& word, const string& ending )
{
return (ctr > 1) ? word + ending : word;
}
Does it mean that change the 'ending', but ending is the third parameter, isn't it?
This question worries me a lot!
Regards!

That must be a typo.
Looking at the code:
string make_plural(size_t ctr, const string& word, const string& ending )
{
return (ctr > 1) ? word + ending : word;
}
the most reasonable thing would be to have "s" as default for ending, as this is how you make the plural by default (not always, but with "bee" -> "bees" e.g. it works).
A much stronger argument is that in C++ it is not possible (unless you find a magic workaround (*)) to have a default argument for the n-th parameter if the (n+1)-th has no default argument:
foo(int first = 0,int second) // not possible !!
With this example it is maybe not so clear why this isnt allowed, but consider having multiple default values. Lets say you would write:
foo(int first = 0,int second,int third = 0); // actually still not allowed
Then there would be no way to know if
foo(1,2);
is supposed to call
foo(0,1,2);
or
foo(1,2,0);
To resolve this ambiguity some rule had to be invented and for C++ the rule is that default arguments have to be provided from right to left.
(*) If you can change the function and are willing to write some extra code, the workaround is rather trivial. You just have to encapsulate all parameters in a struct that provides creation of parameters with whatever combination of defaults you like.

Related

Error in the example code of A Tour of C++

I'm going through Mr. Stroustrup's "A Tour of C++" book. In section 9.3 String Views, the author gives the following example:
string cat(string_view sv1, string_view sv2)
{
string res(sv1.length()+sv2.length());
char *p = &res[0];
for (char c : sv1) // one way to copy
*p++ = c;
copy(sv2.begin(),sv2.end(),p); // another way
return res;
}
When I try to compile this function, I get following error as std::string class doesn't provide any constructor which takes a single int parameter.
error: no matching function for call to 'std::__cxx11::basic_string<char>::basic_string(std::basic_string_view<char>::size_type)' 11 | string res(sv1.length()+sv2.length());
I checked the Errata for 2nd printing of A Tour of C++ but there is no mention of this issue.
Is this a bug in the example provide or else I'm missing something else?
Is this a bug in the example provide or else I'm missing something else?
Yes this is an erratum in the book as std::string doesn't have a constructor that has only one parameter of type int(or convertible to int).
Instead it has a constructor std::string::string(size_type, char) that can take a char as the second argument. In particular, from std::string:
fill (6) string (size_t n, char c);
(6) fill constructor:
Fills the string with n consecutive copies of character c.
Thus to resolve the erratum, we should pass a second argument as shown below:
string res(sv1.length()+sv2.length(), '\0');

Is there a way to check if value sent to variable is right type while it is already under that var?

I couldn't find a way to check if the value that was passed into variable is right type.
For example: I have passed char into int variable and I would like to check if it is int inside int(?). I thought about checking if argument that was sent is in ascii table, but i don't find this as optimal solution. Some code:
Martice m('q');
when
Martice (int _arg) : pass(_arg) { allocation(); };
I know that I could use this method to check input:
if (std::cin.fail() == true) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
but my point is to check it later, after passing it as argument.
If you want to distinguish between characters and integers, then you could use overloading of the Martice constructor. So you have one constructor taking an int, and one taking a char.
If you want to disallow passing of char, then you could mark the char overload as deleted:
explicit Martice(char) = delete;
If you want to allow it, but convert digit characters to numbers it's a little more complicated, as you must then use default-construction (if possible) and then convert the character and use assignment:
explicit Martice(char _arg) : Martice() // Delegating to default constructor
{
if (!std::isdigit(_arg))
{
// TODO: Not a digit, do something, perhaps throw an exception
}
else
{
pass = _arg - '0'; // Convert digit to number
allocation();
}
}
Note the use of explicit for the constructors. That will disallow implicit conversion from characters to Martice objects.

Why call basic_string::substr with no arguments?

If s1 and s2 are strings, then (as far as I can tell)
s1 = s2.substr();
means exactly the same as
s1 = s2;
Why would somebody want to call substr() without any arguments?
Edit: Another way to phrase the same question:
Why does the standard define substr thus:
basic_string substr( size_type pos = 0,
size_type count = npos ) const;
rather than thus:
basic_string substr( size_type pos,
size_type count = npos ) const;
The answer is, just for the heck of it.
As you rightly noticed, it has no advantage (and sometimes a speed disadvantage) to just creating a copy.
Speculating why the first argument is defaulted at all, I guess that it was meant as a way to force un-sharing of ancient COW strings (not allowed by current standards). Or someone was over-zealous when adding default arguments. It happens to the best of us.
In some cases, the logic might flow better with substr().
Imagine a case where you have a buffer as a string pointer and a pointer to some string metrics object.
if (metrics) {
substring = buffer->substr(metrics->pos(), metrics->len());
} else {
substring = buffer->substr();
}
reads better than
if (metrics) {
substring = buffer->substr(metrics->pos(), metrics->len());
} else {
substring = *buffer;
}

Prefix(polish) notation - evaluation c++

I am looking for code wchich parses prefix expressions using recursion. Primarily in C++, but it can bee in other language, i will translate. Thanks.
It's really easy to do yourself (you just need a stack for the operators (and sometimes/optionally its first term)).
But if you really don't want to do much work, here's a link:
prefix notation string to int conversion
If you need to use recursion, you basically use local variables in the function as individual elements in your stack.
Eg. pseudo-C++ code follows:
int naughtyglobalendindex = 0;
int parse(string str) {
if (/* str starts off with an integer */) return the integer;
char operator;
operator = ?? // you will need to get the first op here. Maybe sscanf(str,"%c",&operator) or similar
// get first argument
int first = parse(/* str with 1st operator removed */);
// get 2nd integer argument
int second = parse(/* str - get substring from naughtyglobalendindex to end*/)
// return first operator second <- this is pseudocode
// in effect you want a switch clause
switch (operator) {
case '+': return first + second;
case '-': return first - second; // and so on
}
}
You can convert the pseudocode to actual C++, and if you want, fix the global naughtyglobalendindex variable if you want.

structure initialization

static struct Args {
char* arg1;
unsigned arg2;
unsigned arg3;
char* arg4;
} arg;
My program saves command line args to a structure. Sometime all of the members are set... sometimes only a couple of them.
In the case where only arg1 is set, what would the best practice be to do with the rest of the members?
Thanks.
I'd use a flagged optional type, e.g. Boost.Optional. While you can use NULL for pointers, you may as well use an optional<char *> as well as an optional<int>.
If you insist on using NULL, you may decide that some int values aren't legal inputs (e.g. (unsigned)-1); you could reject them if the user supplies them, and use them to represent "no option supplied".
The essence of an optional wrapper is: boolean flag for whether option is present, and wrapped data type, e.g.:
template <class T>
struct optional<T> {
T val;
bool none;
bool have() { return !none; }
optional() : none(true)
optional(T const& val) : val(val),none(false) {}
void operator=(T const& t) { none=false; val=t; }
// etc; make none and val private if you wish
};
Usually when an argument is omitted, some default value is used by the program instead. If it makes sense, just put such defaults into the structure as if they were supplied as arguments.
Alternatively, it's common to set (char *)s to NULL in cases like this. (Note, it's possible to distinguish an empty string "" from NULL, and this may be useful as well.)
Integers are often set to some "invalid" value like 0 or -1 (this depends on which values are valid). For an unsigned you could use 0xFFFFFFFF.
I would just memset the whole thing. Any 0 value or null pointer are assumed not set.
For example,
memset(&arg, 0, sizeof(arg));
...
if (arg.arg2 == 0) // Not set
If you are working in plain c consider using GNU gengetopt, or emulating the approach used therein (which is to have flag variable that tell if optional arguments have been set). The c standards provide you with no support (soon to be released c++ standard).
As Artelius pointed out, you could set them to the default values. It is common to set pointers to NULL in such cases. With integers, you would want them to have a value other which will not confuse the rest of the code, like -1.