So I have code like
int main(int argc, char* argv[])
{
string outputUrl ;
string outputContainer ;
string outputUserName ;
for(int i = 0 i>=argc; i+2){
switch(argv[i]){ //C2450
case "-server" : {outputUrl += (argv[i+1]);} break; //C2051
case "-container" : {outputContainer = (argv[i+1]);} break; //C2051
case "-nickname" : {outputUserName += (argv[i+1]);} break; //C2051
}
}
Why does it give me compiler error C2450 and on next line C2051?
How to fix such thing?
The switch statement can't use strings. You'll need to replace it with a string of if-else if statements instead.
C and C++ switch statements only operate on integral types. You can do some stuff like casting the pointer to an int (and in fact you are switching on pointers), but you're still not going to get 'switching on strings' behavior like you want here.
Why no switch on pointers?
You can switch on numbers, not on pointers to strings. I take it you're transitioning from another language?
Also, i+2 should be i+=2.
Also, i>=argc should be i < argc
You can't switch on strings, only integer types. You will have to explicitly if/else each one. Secondly, break occurs inside the case statement, not outside.
You can't switch on a string, or anything else that isn't an integer or can't be converted to one. Use three "if" statements instead.
Use something like getopt. There is a nice (but not complete) implementation: http://www.codeproject.com/KB/cpp/xgetopt.aspx?msg=614581. Or use boost.Program_options: http://www.boost.org/doc/libs/1_41_0/doc/html/index.html.
Related
A library we are using defines constants and we have:
const char field[] = "666"
and I would like to:
switch(an_int){
case field:
Is there a way to achieve this? I get a compiler error saying field is not usable in a constant expression (GCC 5.2).
I would really wish to avoid modifying the declaration of field if possible.
field is an array. It is not a single value you can switch on.
You're trying to switch on the contents of a character array, when it is interpreted as an integer value.
Use atoi(), or a helper std::istringstream's operator >>, to convert the array into an int variable, then switch on it.
No, It is not possible to have switch statement on char array/string. In case you are sure that the field will contain numeric value then convert char array to integer.
This question already has answers here:
C/C++: switch for non-integers
(17 answers)
Closed 9 years ago.
How can I compare an array of char in c++ using switch-case?
Here is a part of my code:
char[256] buff;
switch(buff){
case "Name": printf("%s",buff);
break;
case "Number": printf("Number "%s",buff);
break;
defaul : break
}
I receive the error :" error: switch quantity not an integer".How can I resolve it?
If you really need a switch statement, you will need to convert your buff variable to an integer. To do so, you could use a hash function or a std::map.
The easy approach would be to make a std::map<std::string,int> containing the keys you want to use in the switch associated with unique int values. You would get something like:
std::map<string,int> switchmap;
...
switch(switchmap.find(std::string(buff))->second){
...
}
The std::map approach is very readable and shouldn't cause much confusion.
You just can't use an array as the expression in a switch construct.
In C++ case statements require a constant integer value and cannot be used with values calculated at runtime. However if you are using C++11 you can use a constexpr function to generate case values simulate using strings with a case statement.
This uses a hash function that takes a pointer to a string and generates a value at compile time instead of runtime. If more than one string generates the same value (a hash collision) you get the familiar error message about multiple case statements using the same value.
constexpr unsigned int djb2Hash(const char* str, int index = 0)
{
return !str[index] ? 0x1505 : (djb2Hash(str, index + 1) * 0x21) ^ str[index];
}
The djb2Hash function can then be used directly in both the switch and case statements. There is one caveat however, the hash function can result in a collision at runtime. The probability of this happening is driven primarily by the quality of the hash function. The solution presented here does not attempt to address this problem (but may in the future).
void DoSomething(const char *str)
{
switch(djb2Hash(str))
{
case djb2Hash("Hello"): SayHello(); break;
case djb2Hash("World"): SayWorld(); break;
}
}
This works very well but might be considered ugly. You can simplify this further by declaring a user defined literal that handles invoking the hash function.
// Create a literal type for short-hand case strings
constexpr unsigned int operator"" _C ( const char str[], size_t size)
{
return djb2Hash(str);
}
void DoSomething(const char *str)
{
switch(djb2Hash(str))
{
case "Hello"_C: SayHello(); break;
case "World"_C: SayWorld(); break;
}
}
This provides a more intuitive usage of strings in a switch statements but may also be considered slightly confusing because of the user defined literal.
[Edit: Added note about runtime hash collisions. Much Kudos to R. Martinho Fernandes for bringing it to my attention!]
You cannot use a non-integral type in a switch statement. Your problem would require something like:
char buff[256];
if(!strcmp(buf, "Name") printf("%s",buff);
if(!strcmp(buf, "Number") printf("%s",buff);
To get the results you are looking for - basically a bunch of if statements to replace the switch.
You are trying to do something we all dearly wish we could, but not in C/C++ :) The case in a switch statement must be integral values. One easy alternative is to have an enumeration that matches the set of strings you want to act on.
In C++ you can use a switch-case only with integers (char, int, ...) but not with c-strings (char *)
In your case you have to use a if-then-else construct
if (strcmp(buff, "Name") == 0) {
...
} else if (...) {
...
}
As the error says, switch only works for integers. The simplest resolution is to use a chain of if...else if... tests.
However, using a char array rather than a string is awkward, since you need quirky C-style functions to compare them. I suggest you use std::string instead.
std::string buff;
if (buff == "Name") {
// deal with name
} else if (buff == "Number") {
// deal with number
} else {
// none of the above
}
More complex approaches, perhaps mapping strings to numbers for use in a switch or to functors to call, are possible and may be more efficient if you have a huge number of cases; but you should get the simple version working before worrying about such optimisations.
Unlike many other languages that allow string and other object comparisons to be used in a switch-case, c++ requires that the underlying value be an integer. If you want use more complex object types, you will have to use an if else-if construct.
You can't use a switch directly for this situation.
Typically, you'd want to use a std::map (or std::unordered_map) to store the action to associate with each input. You might (for example) use a std::map<std::string, std::function>, and then store the addresses of functions/function objects in the map, so your final construct would be something like:
std::map<std::string, std::function> funcs;
funcs["Name"] = [](std::string const &n) {std::cout << n;};
funcs["Number"] = [](std::string const &n) {std::cout << "Number: " << n;};
// ...
auto f = funcs[buff];
f(buff);
// or combine lookup and call: funcs[buff](buff);
Two notes: first, you probably really want to use map::find for the second part, so you can detect when/if the string you're looking for isn't present in the map.
Second, as it stands, your code doesn't seem to make much sense -- you're both switching on buff and printing out buff's value, so (for example) if you buff contains Number, your output will be "Number Number". I'd guess you intend to use buff and some other variable that holds the value you care about.
You can partially do a "string" compare.
The below does not specifically satisfy your query (as C won't ride that pony), nor is it elegant code, but a variation on it may get you through your need. I do not recommend you do this if you a learning C/C++, but this construct has worked well in limited programming environment.
(I use it in PIC programming where strlen(buff)==1 or 2 and sizeof(int)==2.)
Let's assume sizeof(int) == 4 and strlen(buff) >= 3.
char buff[256];
// buff assignment code is TBD.
// Form a switch 4-byte key from the string "buff".
// assuming a big endian CPU.
int key = (buff[0] << 3*8) | (buff[1] << 2*8) | (buff[2] << 1*8) | (buff[3] << 0*8);
// if on a little endian machine use:
// int key = (buff[0] << 0*8) | (buff[1] << 1*8) | (buff[2] << 2*8) | (buff[3] << 3*8);
switch (key) {
// Notice the single quote vs. double quote use of constructing case constants.
case 'Name': printf("%s",buff); break;
case 'Numb': printf("Number \"%s\"",buff); break;
default : ;
}
I have an error while I compile my code.
Error Output:
main.cpp: 35:16: error: switch quantity not an integer
I dont know why. The code is as follows:
int Values(string letter) {
switch( tolower(letter) ) {
case 'a' : a.setTotal();
break;
Regards
A string is not a char, it's an object representing an array of chars.
Instead of passing in a string to that function, you should pass in a char.
tolower(int) exists in C++ and it was meant to take characters, not strings.
Here's another way to fix this that needs less changes to your code:
Since I'm pretty sure that letter is going to be a string of length 1 judging by the name, you can change your switch statement to access letter[0], which will be the first character in the string. You would also have to pass letter[0] to tolower.
letter is string, so tolower(letter) produce a string. But your case is character ('a'). Additionally it is impossible in C/C++ to use switch for string.
user this line instead:
switch( tolower(letter.data[0]) )
The switch inscrutvion takes only enumerated types(enum), chars(char) or integers (int, unsigned, long)
It looks like you want to work with a single character.
Change your function's parameter:
int Values(string letter)
to this:
int Values(char letter)
And the switch statement will work.
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.
I have the following syntax:
enum home
{
no,
yes,
}homew;
home homes;
std::string s;
s="no";
homes=s; //is not working. Why?
Were am I wrong?
You are confusing strings with enumerated values.
An enum variable is simply an integer that you can use a literal for at compile time, nothing more than that.
It makes the code more understandable and self-documenting rather than merely using a number literal.
This
enum home { no, yes, } homew;
defines the type home plus a variable homew of that type.
Did you intent that? Why?
The values defined for an enum type are literals, to be used as such:
home homes = no;
In C++ there's no built-in way to convert between enum value literals and a string representation of them. If you need this, you'll have to cook up your own.
enums in C++ are implicitly an int data type. You can't assign string values to enum.
It doesn't compile because C++ provides no built-in mechanism for converting from std::string to an enum.
typeof(home) != typeof(std::string) // types are not equal
Thus, you cannot assign an enum to std::string or otherwise. Implicit conversion between enum and integral types like bool, int etc. is possible however.
Is there a way I can solve my problem as it is?
If possible use std::map.
std::map<std::string, home> myTypes;
myTypes["yes"] = yes;
myTypes["no"] = no;
Now you can do,
homes = myTypes["no"];
As others pointed out, enums values are of int type. You could instead write a small function that converts from enum to String like this:
std::string GetStringFromEnum(home iHome)
{
switch (home)
{
case yes: return "yes";
case no: return "no"; break;
default: return "here be dragons";
}
}
and vice-versa:
home GetEnumFromString(std::string iImput)
{
if (iImput == "yes") return yes;
return no; //if you extend the enum beyond 2 values, this function will get more complicated
}
and you could modify your code like so:
homes = GetStringFromEnum(no)
the downside for this approach is that if you modify the enum, you must also modify the convert function.
HTH,JP