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.
Related
I'm try to compile a simple expression:
char_to_int(tolower(row[y]))
However I'm getting the following errors when trying to compile it:
error: implicit conversion loses integer precision: 'int' to 'char' [-Werror,-Wimplicit-int-conversion]
if (char_to_int(tolower(row[y])) > n
The signature of char_to_int is:
unsigned long char_to_int(char c)
and the type of row[y] is char.
Why am I getting this error and how can I fix it?
From your error information I assume you are using std::tolower from <cctype> (or equivalently, ::tolower from <ctype.h>), not std::tolower from <locale>.
Why you are getting the error is straightforward from your error information: your char_to_int expects a char, but tolower returns an int. This will cause loss of information.
Why does tolower return an int, not just a char? Because it can accept and return EOF, which may fall out of range of any char.
The fix can be straightforward: change your char_to_int to accept int, or do an intermediate step to discard the possible EOF.
std::tolower doesn't actually operate on chars: it operates on ints! Moreover, there is risk of undefined behaviour: if on your machine char is a signed type, then the "negative" characters will correspond to negative integers, which std::tolower is not equipped to deal with.
A way to fix this for your use is to manually cast the types before use:
char_to_int(static_cast<char>(
std::tolower(static_cast<unsigned char>(row[y]))));
... which unfortunately is a bit of a mess, but that's what you have to do.
Alternatively, you may use the locale version of std::tolower, which is templated and will correctly handle char types. You may use it like so:
// std::locale{} is an object representing the default locale
// you may specify a locale precisely if needed; see the above links
char_to_int(std::tolower(row[y], std::locale{}));
tolower returns an int. std::tolower is however a template, and will work correctly for char. In general, if there is a std:: version of any func you are calling, use it! :)
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 need to read input from user. The input value may be string type or int type.
If the value is int then the program insert the value into my object.
Else if the value is string then it should check the value of that string, if it's "end" then the program ends.
Halda h; //my object
string t;
int tint;
bool end=false;
while(end!=true)
{
if(scanf("%d",&tint)==1)
{
h.insert(tint);
}
else if(scanf("%s",t)==1)
{
if(t=="end")
end=true;
else if(t=="next")
if(h.empty()==false)
printf("%d\n",h.pop());
else
printf("-1\n");
}
}
The problem is that scanning string doesn't seem to work properly.
I've tried to change it to: if(cin>>t) and it worked well.
I need to get it work with scanf.
The specifier %s in the scanf() format expects a char*, not a std::string.
From C11 Standard (C++ Standard refers to it about the C standard library):
Except in the case of a % specifier, the input item (or, in the case of a %n directive, the
count of input characters) is converted to a type appropriate to the conversion specifier. If
the input item is not a matching sequence, the execution of the directive fails: this
condition is a matching failure. Unless assignment suppression was indicated by a *, the
result of the conversion is placed in the object pointed to by the first argument following
the format argument that has not already received a conversion result. If this object
does not have an appropriate type, or if the result of the conversion cannot be represented
in the object, the behavior is undefined.
Anyway, here there's is no real reason to prefer the C way, use C++ facilities. And when you use the C library, use safe functions that only reads characters up to a given limit (just like fgets, or scanf with a width specifier), otherwise you could have overflow, that leads again to undefined behavior, and some errors if you're luck.
That's a really bad way to check for end-of-input. Either use an integer or use a string.
If you choose string, make provisions to convert from string to int.
My logic would be to first check if it can be converted to integer. if it can be, then continue with the logic. If it can't be(such as if it's a float or double or some other string) then ignore and move on. If it can be, then insert it into Halda's object.
Sidenote: Do not use scanf() and printf() when you're working with C++.
Assuming string refers to std::sring this program doesn't have defined behavior. You can't really use std::string with sscanf() You could set up a buffer inside the std::string and read into that but the string wouldn't change its size. You are probably better off using streams with std::string (well, in my opinion you are always better off using streams).
So I am currently writing a part of a program that takes user text input. I want to ignore all input characters that are not alphabetic, and so I figured std::isalpha() would be a good way to do this. Unfortunately, as far as I know there are two std::isalpha() functions, and the general one needs to be disambiguated from the locale-specific one thusly:
(int(*)(int))std::isalpha()
If I don't disambiguate, std::isalpha seems to return true when reading uppercase but false when reading lowercase letters (if I directly print the returned value, though, it returns 0 for non-alpha chars, 1 for uppercase chars, and 2 for lowercase chars). So I need to do this.
I've done so in another program before, but for some reason, in this project, I sometimes get "ISO C++ forbids" errors. Note, only sometimes. Here is the problematic area of code (this appears together without anything in between):
std::cout << "Is alpha? " << (int(*)(int))std::isalpha((char)Event.text.unicode) << "\n";
if ( (int(*)(int))std::isalpha((char)Event.text.unicode) == true)
{
std::cout << "Is alpha!\n";
//...snip...
}
The first instance, where I send the returned value to std::cout, works fine - I get no errors for this, I get the expected values (0 for non-alpha, 1 for alpha), and if that's the only place I try to disambiguate, the program compiles and runs fine.
The second instance, however, throws up this:
error: ISO C++ forbids comparison between pointer and integer
and only compiles if I remove the (int(*)(int)) snippet, at which point bad behavior ensues. Could someone enlighten me here?
You are casting the return value of the std::alpha() call to int(*)(int), and then compare that pointer to true. Comparing pointers to boolean values doesn't make much sense and you get an error.
Now, without the cast, you compare the int returned by std::alpha() to true. bool is an integer type, and to compare the two different integer types the values are first converted to the same type. In this case they are both converted to int. true becomes 1, and if std::isalpha() returned 2 the comparison ends up with 2 != 1.
If you want to compare the result of std::alpha() against a bool, you should cast that returned in to bool, or simply leave out the comparison and use something like if (std::isalpha(c)) {...}
There is no need to disambiguate, because the there is no ambiguity in a normal call.
Also, there is no need to use the std:: prefix when you get the function declaration from <ctype.h>, which after C++11 is the header you should preferably use (i.e., not <cctype>) – and for that matter also before C++11, but C++11 clinched it.
Third, you should not compare the result to true.
However, you need to cast a char argument to unsigned char, lest you get Undefined Behavior for anything but 7-bit ASCII.
E.g. do like this:
bool isAlpha( char const c )
{
typedef unsigned char UChar;
return !!isalpha( UChar( c ) );
}
I'm working on a little console game with ncurses. In the main menu I want the user to be able to set the control keys. Now as far as I understood, in ncurses you can access e.a. the a-key by the int value of the char 'a'. Using the key ingame with 'a' works flawlessly, however I'm stuck with the menu:
For each key binding I have stored an int-value that is defaulted to e.a. 'a'. When the game starts, I read the 'a' binding correctly from the int-value and can use it ingame. However, it is not displayed correctly. I want it to be like this: "Left: a". I do it like this:
std::string key = "Left: " + static_cast<char>(_value);
_value being the int-value I stored and initialized as 'a'. I also tried it without the cast, btw.
Now what's being displayed is strange. Instead of "a" it says "~T^C". For the letters "s" and "d" it doesn't display anything at all. "w" becomes some very strange encoding question marks.
I suppose it's got something to do with the encoding of the characters in int-values or something. So what can I do to get it displayed the right way?
Thanks a lot!
You're adding together the adress of string literal and ASCII value of _value. String key is then constructed from whatever happens to be at that garbage adress.
Remember that string literals are of type array of N const char and that arrays decay to pointer to their first element when passed to functions and operators etc., which yields you const char*. The built in + operator for pointers doesn't do string concatenation. You need to construct a std::string from at least one of operands for overloaded operator to kick in:
std::string key = std::string("Left: ") + static_cast<char>(_value);