How to compare strings instead of integers in switch case? - objective-c

I have this code who try to compare strings in Switch Case:
char input[50+1];
fgets( input, 50, stdin );
switch (input) {
case "register": NSLog(#"Voce escolheu a opcao de cadastro");
break;
case "enter": NSLog(#"Voce escolheu a opcao de entrada");
break;
case "exit": NSLog(#"Voce escolheu a opcao de saida");
break;
}
This command returns me an error, because I believe that we can not write a text after the 'case' command. I would have someone could help me solve this problem, I believe there are other ways to make a Switch Case using strings, but how?

The lookup option works pretty well. Consider:
NSArray *strings = #{#"string1", #"string2"};
NSUInteger index = [strings indexOfObject:input];
switch(index) {
case 0:
//stuff for string 1;
case 1:
// stuff for string 2:
case NSNotFound:
// not found;
}

You can't. Switch only works with integers. The best options are a chain of if-else statements or a lookup table (e.g. an NSDictionary).

Related

How to reduce a string to ASCII 7 characters for indexing purposes?

I am working on an application which must index certain sentences. Currently using Java and PostgreSQL. The sentences may be in several languages like French and Spanish using accents and other non-ASCII symbols.
For each word I want to create an index-able equivalent so that a user can perform a search insensitive to accents (transliteration). For example, when the user searches "nacion" it must find it even if the original word stored by the application was "Nación".
What could be the best strategy for this? I am not necessarily restricted only to PostgreSQL, nor the internal indexed value needs to have any similarity with the original word. Ideally, it should be a generic solution for converting any Unicode string into an ASCII string insensitive to case and accents.
So far I am using a custom function shown below which naively just replaces some letters with ASCII equivalents before storing the indexed value and does the same on query strings.
public String toIndexableASCII (String sStrIn) {
if (sStrIn==null) return null;
int iLen = sStrIn.length();
if (iLen==0) return sStrIn;
StringBuilder sStrBuff = new StringBuilder(iLen);
String sStr = sStrIn.toUpperCase();
for (int c=0; c<iLen; c++) {
switch (sStr.charAt(c)) {
case 'Á':
case 'À':
case 'Ä':
case 'Â':
case 'Å':
case 'Ã':
sStrBuff.append('A');
break;
case 'É':
case 'È':
case 'Ë':
case 'Ê':
sStrBuff.append('E');
break;
case 'Í':
case 'Ì':
case 'Ï':
case 'Î':
sStrBuff.append('I');
break;
case 'Ó':
case 'Ò':
case 'Ö':
case 'Ô':
case 'Ø':
sStrBuff.append('O');
break;
case 'Ú':
case 'Ù':
case 'Ü':
case 'Û':
sStrBuff.append('U');
break;
case 'Æ':
sStrBuff.append('E');
break;
case 'Ñ':
sStrBuff.append('N');
break;
case 'Ç':
sStrBuff.append('C');
break;
case 'ß':
sStrBuff.append('B');
break;
case (char)255:
sStrBuff.append('_');
break;
default:
sStrBuff.append(sStr.charAt(c));
}
}
return sStrBuff.toString();
}
String s = "Nación";
String x = Normalizer.normalize(s, Normalizer.Form.NFD);
StringBuilder sb=new StringBuilder(s.length());
for (char c : x.toCharArray()) {
if (Character.getType(c) != Character.NON_SPACING_MARK) {
sb.append(c);
}
}
System.out.println(s); // Nación
System.out.println(sb.toString()); // Nacion
How this works:
It splits up international characters to NFD decomposition (ó becomes o◌́), then strips the combining diacritical marks.
Character.NON_SPACING_MARK contains combining diacritical marks (Unicode calls it Bidi Class NSM [Non-Spacing Mark]).
The one obvious improvement for your current code: use a Map<Character, Character> that you prefill with your mappings.
And then simply check if that Map has a mapping; of so; use that; otherwise use the original character.
And as Androbin explains, there are special maps that do not rely on objects, but work with primitive types, like this trove. So, depending on your solution and requirements; you could look into that.

Ternary operator error - "Expected expression"

I haven't used the ternary operator much and I'm getting an error on this:
(isInitializing) ? (return YES) : (isInitializing = 1);
Error is: "Expected Expression" and it's pointing to return YES.
Don't use the Ternary Operator to "do stuff" but to return one of two values.
So this is a valid case:
NSString *something = (isInitializing ? #"value a" : #"value b");
In your case, you might want to do this instead:
if (isInitializing) {
return YES;
} else {
isInitializing = 1;
}
The ternary operator is used to return one of two values depending on a condition. It is not so much used to execute statements, hence the return is a bit of a problem. I would rather use an if when you do not want to distinguish values, but rather have two different execution paths.

error with switch case and exptected expression

Sorry to ask this (I rarely use switch statements) but I am getting an error with this but it seems valid to me (but obviously isn't):
NSInteger section=indexPath.section;
switch(section){
case 0:
Item *mi = self.miArray[indexPath.row]; // <- expected expression
...
return cell;
break;
case 1:
Item *mi = self.miArray[indexPath.row];
break;
}
What am I doing wrong?
You can either put the case in braces (case 0: { Item *mi ... }) or add a ; after the case statement (case 0:;).
Either of that should help but I actually forgot why this is necessary.
Found an explanation here: Weird Switch error in Obj-C
Declaration is not allowed within switch.
Declare Item before entering to switch and do the initialization within the switch.

"used struct type value where scalar is required" at .layer.position

I want to make a selection before apply one of two animations,
what I thought is: make a Point one, if my myImageView is at the Point one, then apply animationNo1, else apply animationNo2, but I got this:"used struct type value where scalar is required", at line if (myImageView.layer.position = one)
What I do? how can I fix this?
Does anyone know exactly what makes the problem happen?
CGPoint one = CGPointMake(myImageView.layer.position.x, 100);
if (myImageView.layer.position = one)
{
animationNo1
}
else
{
animationNo2
}
First of all, your if-statement will not do what you think. If you want to compare something you have to use == (ie 2 =)
and you can't compare CGPoints like this.
use
if (CGPointEqualToPoint(one, self.view.layer.position))
if (myImageView.layer.position = one) { animationNo1 }
should be
if (CGPointIsEqualToPoint(myImageView.layer.position, one)) { animationNo1 }
You used a single = meaning assignment, rather than a == for comparison. But the == wouldn't do what you wanted here anyway.
You are passing a struct (int this case position) instead of a scalar. To do what you want you need to use CGPointIsEqualToPoint:
if (CGPointEqualToPoint(one, self.view.layer.position))
Full code with corrections:
CGPoint one = CGPointMake(myImageView.layer.position.x, 100);
if (CGPointEqualToPoint(one, self.view.layer.position))
{
animationNo1
}
else
{
animationNo2
}
Also, as others have pointed out: Be careful about = vs ==. They are different. In this case you don't use == for comparison fortunately, but if you use = for other stuff it will make it true instead of checking to see if it is true.

How do I use a boolean operator in a case statement?

I just Don't understand how to use a boolean operator inside a switch statement
switch (expression) {
case > 20:
statements
break;
case < -20:
statements
break;
}
Edit:
I don't want an If () statement.
You can't. Use if() ... else ....
The nearest thing available to what you want uses a GCC extension and is thus non-standard. You can define ranges in case statements instead of just a value:
switch(foo)
{
case 0 ... 20: // matches when foo is inclusively comprised within 0 and 20
// do cool stuff
break;
}
However, you can't use that to match anything under a certain value. It has to be in a precise range. Switches can only be used to replace the comparison operator against a constant, and can't be used for anything more than that.
switch ((expression) > 20) {
case true:
statements
break;
case false:
default:
statements
break;
}
What.. you want more than 1 boolean in a case? You could do this
int ii = ((expression) > 20) + 2 * ((expression) < -20);
switch (ii) {
case 1:
statements
break;
case 2:
statements
break;
}
This, IMO is pretty bad code, but it is what you asked for...
Just use the if statement, you'll be better off in the long run.