If statement inside a switch case in Objective-c - ios

I know there are a couple of questions like this on stack overflow but the problem is that it does not solve my answer.
I want to show an if-statement inside a switch case.
Here is my code
NSMutableArray *stdMarks = [[NSMutableArray alloc]initWithObjects:#"100", #"70", #"97", #"11", #"59", nil];
int marksObtained;
for (int i= 0; i < [stdMarks count]; i++) {
marksObtained += [[stdMarks objectAtIndex:i] integerValue];
}
int totalMarks = 500;
int percentage = (marksObtained * 100)/totalMarks;
NSLog(#"The total marks are: %d", marksObtained);
NSLog(#"The percentage is: %d", percentage);
NSLog(#"The total numbers of subjects are: %d", [stdMarks count]);
switch (percentage) {
case 1:
if (percentage >= 70) {
NSLog(#"You get 50 percent fee concession");
}
break;
case 2:
if (percentage >= 60) {
NSLog(#"You get 45 percent fee concession");
}
break;
default:
NSLog(#"you do not qualify");
break;
}
No matter what the percentage is I always get the default answer "You do not qualify".
What am I doing wrong
Please help me out here

that is because the switch is being fed the percentage which only caters for 1 and 2 percent, so those if statements will never fire because to get into those cases, they have to be lower then the values in the if statements
my suggestion is to drop the switch statement, because it seems unnecessary, just have if/else statements that encompass the ranges you want

In your code, if your percentage is not equal to run 1 or 2, it will go to default.
switch (percentage) { <---- this percentage, you only provide the case of 1 and 2.
case 1:
if (percentage >= 70) {
NSLog(#"You get 50 percent fee concession");
}
break;
case 2:
if (percentage >= 60) {
NSLog(#"You get 45 percent fee concession");
}
break;
default:
NSLog(#"you do not qualify");
break;
}
guessing you need to change the percentage in switch(percentage).
Updated:
if (percentage >= 70) {
NSLog(#"You get 50 percent fee concession");
}
else if (percentage >= 60) {
NSLog(#"You get 45 percent fee concession");
}
else{
NSLog(#"you do not qualify");
}
update:
if you want to do it using switch case:
for percentage >= 70
switch (percentage)
case 70:
case 71:
case 72:
case 73:
.
.
.
case 100:
NSLog(#"You get 50 percent fee concession");
break;
case 60:
.
.
.
and so on which is very stupid , so a if else case is more suitable

Related

remove decimal when value is equal 10 else not

How to remove decimal if value is equal to 10 else decimal value should not removed.
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:YES];
if (_ratingValue >= 100) {
_ratingValue = 10;
_formatValue = #"%0.0f";
}
else{
_formatValue = #"%.01f";
}
}
_ratingValue == 0.0f ? [cellProductInfo.view_ProductRating setInnerText:#"review"] :
[cellProductInfo.view_ProductRating setInnerText:[NSString stringWithFormat:#" %.01f / 10",_ratingValue]];
If ratingValue is equal 10, I do not want to show the decimal value else if below 10 want to show decimal value.
For 1 decimal place your format needs to be %.1f. For no decimals you want %.0f.
If you want values less than 10 to show 1 decimal and values greater or equal to 10 to show none, you want:
if (_ratingValue >= 10.0) {
_formatValue = #"%.0f";
} else {
_formatValue = #"%.1f";
}
_ratingValue == 0.0f ? [cellProductInfo.view_ProductRating setInnerText:#"review"] :
[cellProductInfo.view_ProductRating setInnerText:[NSString stringWithFormat:_formatValue,_ratingValue]];
Its works for me!

How to determine Zodiac Sign in Objective-C

I have the following code:
NSDate *myDate = [datePickerControl date];
NSDateFormatter *format = [[NSDateFormatter alloc]init];
[format setDateFormat:#"dd-MM"];
NSString *getDate = [format stringFromDate:myDate];
NSArray *array = [NSArray arrayWithObjects:#"15-06",#"15-07",#"15-08",nil];
for (int i = 0; i < ([array count]); i++) {
NSLog(#"i = %i", i);
NSString *stringToCheck = (NSString *)[array objectAtIndex:i];
if ([getDate isEqualToString:stringToCheck]) {
[signWow setText:[NSString stringWithFormat:#"Your sign is Scorpion"]];
}}
It uses Date Picker to determine date of birth and then to compare the date with a date from NSArray. But it's too difficult to type in all the dates related to specific Zodiac sign.
So, is it possible to make an array which contains all dates between for example 02/12 (dd/MM) and 03/15?
Take a look at screenshot here.
Please, give some code, because I'm new to Objective-C... :)
How about using tuple... (Swift)
func getZodiacSign(_ date:Date) -> String{
let calendar = Calendar.current
let d = calendar.component(.day, from: date)
let m = calendar.component(.month, from: date)
switch (d,m) {
case (21...31,1),(1...19,2):
return "aquarius"
case (20...29,2),(1...20,3):
return "pisces"
case (21...31,3),(1...20,4):
return "aries"
case (21...30,4),(1...21,5):
return "taurus"
case (22...31,5),(1...21,6):
return "gemini"
case (22...30,6),(1...22,7):
return "cancer"
case (23...31,7),(1...22,8):
return "leo"
case (23...31,8),(1...23,9):
return "virgo"
case (24...30,9),(1...23,10):
return "libra"
case (24...31,10),(1...22,11):
return "scorpio"
case (23...30,11),(1...21,12):
return "sagittarius"
default:
return "capricorn"
}
}
You should not need to enter every date for each sign. Instead, enter a table of the starting and ending month and day for each sign.
You would then take the user's selected date, use a Gregorian NSCalendar to extract the month and day units from the date, and then compare the user-entered date to the ranges for each sign.
BTW, it's "Scorpio", not "Scorpion".
Here's the most straightforward way to do it. Yes it's long, and yes it's not the most efficient, but it is definitely the easiest to understand, and it's already written for you. Cheers :)
P.S. This is going off of the Tropical zodiac (the standard, as opposed to the Sidereal zodiac based off of the Hindu system), and in response to Zev, Ophiuchus only affected each sign's corresponding constellation, but the sign's and their dates remained unaffected.
Here's the code:
-(void)getZodiacFromBirthday {
NSString *UserBirthday = #"09/09/99";
NSArray *birthArray = [UserBirthday componentsSeparatedByString:#"/"];
NSString *month = birthArray[0];
NSString *day = birthArray[1];
if ([month isEqualToString:#"01"]) {
if ([day intValue] >= 21) {
sign = #"Aquarius";
} else {
sign = #"Capricorn";
}
} else if ([month isEqualToString:#"02"]) {
if ([day intValue] >= 20) {
sign = #"Pisces";
} else {
sign = #"Aquarius";
}
} else if ([month isEqualToString:#"03"]) {
if ([day intValue] >= 21) {
sign = #"Aries";
} else {
sign = #"Pisces";
}
} else if ([month isEqualToString:#"04"]) {
if ([day intValue] >= 21) {
sign = #"Taurus";
} else {
sign = #"Aries";
}
} else if ([month isEqualToString:#"05"]) {
if ([day intValue] >= 22) {
sign = #"Gemini";
} else {
sign = #"Taurus";
}
} else if ([month isEqualToString:#"06"]) {
if ([day intValue] >= 22) {
sign = #"Cancer";
} else {
sign = #"Gemini";
}
} else if ([month isEqualToString:#"07"]) {
if ([day intValue] >= 23) {
sign = #"Leo";
} else {
sign = #"Cancer";
}
} else if ([month isEqualToString:#"08"]) {
if ([day intValue] >= 23) {
sign = #"Virgo";
} else {
sign = #"Leo";
}
} else if ([month isEqualToString:#"09"]) {
if ([day intValue] >= 24) {
sign = #"Libra";
} else {
sign = #"Virgo";
}
} else if ([month isEqualToString:#"10"]) {
if ([day intValue] >= 24) {
sign = #"Scorpio";
} else {
sign = #"Libra";
}
} else if ([month isEqualToString:#"11"]) {
if ([day intValue] >= 23) {
sign = #"Sagittarius";
} else {
sign = #"Scorpio";
}
} else if ([month isEqualToString:#"12"]) {
if ([day intValue] >= 22) {
sign = #"Capricorn";
} else {
sign = #"Sagittarius";
}
}
NSLog(#"Sign: %#", sign);
}
For those using swift, i must thanks Duncan C. his solution helped me a lot:
in case that date is "dd/MM/yyyy"
func getZodiacalSign(date:String) -> String {
let f = date.components(separatedBy: "/")
let day = Int(f[0])
let month = Int(f[1])
switch month {
case 1: return (day! >= 21) ? "Aquarius" : "Capricorn";
case 2: return (day! >= 20) ? "Picis" : "Aquarius";
case 3: return (day! >= 21) ? "Aries" : "Pisces";
case 4: return (day! >= 21) ? "Taurus" : "Aries";
case 5: return (day! >= 22) ? "Gemini" : "Taurus"
case 6: return (day! >= 22) ? "Cancer" : "Gemini";
case 7: return (day! >= 23) ? "Leo" : "Cancer";
case 8: return (day! >= 23) ? "Virgo" : "Leo";
case 9: return (day! >= 24) ? "Libra" : "Virgo";
case 10: return (day! >= 24) ? "Scorpio" : "Libra";
case 11: return (day! >= 23) ? "Sagittarius" : "Scorpio";
case 12: return (day! >= 22) ? "Capricorn" : "Sagittarius";
default: return ""
}
Duncan is right, I was writing you a sample code when he answered the question.....
//get date from your picker
NSDate *myDate = [datePickerControl date];
NSCalendar *gregorianCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComps = [gregorianCal components: (NSDayCalendarUnit | NSMonthCalendarUnit)
fromDate: myDate];
// Then use it
int month=[dateComps month];
int days=[dateComps day];
//I guess there is only two zodiac signs possilble for each month right?
switch (month)
{
case 1:
//compare the dates
if (days<=20)
{
//user is Capricorn
}
else
{
//user is Picses
}
break;
case 2:
break;
//you will have 12 cases and each case will have an if else with corect dates.....
default;
break;
}
Here is an answer for those using Swift. It is based upon Hendra Kusumah's tuple solution, but uses extensions and enums for a neater and more Swift-like answer.
Usage
let date = Date()
date.zodiacSign // Enum value e.g. .aquarius
date.zodiacSign.rawValue // String value e.g. "aquarius"
Note - If you wanted the string value to be capitalised or to appear different in another way, either manipulate the string using date.zodiacSign.rawValue.capitalized or edit the ZodiacSign enum cases e.g. case aquarius = "Aquarius"
Extension
extension Date {
var zodiacSign: ZodiacSign {
get {
let calendar = Calendar.current
let day = calendar.component(.day, from: self)
let month = calendar.component(.month, from: self)
switch (day, month) {
case (21...31, 1), (1...19, 2):
return .aquarius
case (20...29, 2), (1...20, 3):
return .pisces
case (21...31, 3), (1...20, 4):
return .aries
case (21...30, 4), (1...21, 5):
return .taurus
case (22...31, 5), (1...21, 6):
return .gemini
case (22...30, 6), (1...22, 7):
return .cancer
case (23...31, 7), (1...22, 8):
return .leo
case (23...31, 8), (1...23, 9):
return .virgo
case (24...30, 9), (1...23, 10):
return .libra
case (24...31, 10), (1...22, 11):
return .scorpio
case (23...30, 11), (1...21, 12):
return .sagittarius
default:
return .capricorn
}
}
}
}
Enum
enum ZodiacSign: String {
case aries
case taurus
case gemini
case cancer
case leo
case virgo
case libra
case scorpio
case sagittarius
case capricorn
case aquarius
case pisces
}

Finding the nearest, lower number in a sorted NSArray

I have a sorted array of times like so
[0.0, 1.2, 4.3, 5.9, 7.2, 8.0]
While an audio file plays, I want to be able to take the current time and find what the nearest, lower number is in the array.
My approach would be to traverse the array, possible in reverse order as it feels like it should be faster. Is there a better way?
The playback SHOULD be linear, but might be fast-forwarded/rewound, so I would like to come up with a solution that takes that into account, but I'm not really sure how else to approach the problem.
The method you are looking for is -[NSArray indexOfObject:inSortedRange:options:usingComparator:]. It performs a binary search. With the options:NSBinarySearchingInsertionIndex option, if the value isn't found exactly, it returns the index where the object would be inserted, which is the index of the least larger element, or the count of items in the array.
NSTimeInterval currentTime = ...;
NSUInteger index = [times indexOfObject:#(currentTime)
inSortedRange:NSMakeRange(0, times.count)
options:NSBinarySearchingInsertionIndex
usingComparator:^(id object0, id object1) {
NSTimeInterval time0 = [object0 doubleValue];
NSTimeInterval time1 = [object1 doubleValue];
if (time0 < time1) return NSOrderedAscending;
else if (time0 > time1) return NSOrderedDescending;
else return NSOrderedSame;
}];
// If currentTime was not found exactly, then index is the next larger element
// or array count..
if (index == times.count || [times[index] doubleValue] > currentTime) {
--index;
}
The fastest* way to find something in a sorted array is binary search: if there are n items, check the element at index n/2. If that element is greater than what you're looking for, check the element at index n/4; otherwise, if it's less than what you're looking for, check the element at index 3n/4. Continue subdividing in this fashion until you've found what you want, i.e. the position where the current time should be. Then you can pick the preceding element, as that's the closest element that's less than the current time.
However, once you've done that once, you can keep track of where you are in the list. As the user plays through the file, keep checking to see if the time has passed the next element and so on. In other words, remember where you were, and use that when you check again. If the user rewinds, check the preceding elements.
*Arguably, this isn't strictly true -- there are surely faster ways if you can make a good guess as to the probable location of the element in question. But if you don't know anything other than that the element appears somewhere in the array, it's usually the right approach.
I'm not sure if it's the best approach, but I think it'll get the job done (assuming your array is always ascending order).
- (NSNumber *) incrementalClosestLowestNumberForNumber:(NSNumber *)aNumber inArray:(NSArray *)array {
for (int i = 0; i < array.count; i++) {
if ([array[i] floatValue] == [aNumber floatValue]) {
return aNumber;
}
else if ([array[i] floatValue] > [aNumber floatValue]) {
int index = (i > 0) ? i - 1 : 0;
return array[index];
}
}
return #0;
}
Then call it like this:
NSArray * numbArray = #[#0.0, #1.2, #4.3, #5.9, #7.2, #8.0];
NSNumber * closestNumber = [self closestLowestNumberForNumber:#2.4 inArray:numbArray];
NSLog(#"closest number: %#", closestNumber);
I'm not sure if someone else knows a special way that is much faster.
Based on some of the other answers / comments, I came up with this, perhaps one of them can point out if a whole is somewhere.
- (NSNumber *) quartalClosestLowestNumberForNumber:(NSNumber *)compareNumber inArray:(NSArray *)array {
int low = 0;
int high = array.count - 1;
NSNumber * lastNumber;
int currentIndex = 0;
for (currentIndex = low + (high - low) / 2; low <= high; currentIndex = low + (high - low) / 2) {
NSNumber * numb = array[currentIndex];
if (numb.floatValue < compareNumber.floatValue) {
low = currentIndex + 1;
}
else if (numb.floatValue > compareNumber.floatValue) {
high = currentIndex - 1;
}
else if (numb.floatValue == compareNumber.floatValue) {
return numb;
}
lastNumber = numb;
}
if (lastNumber.floatValue > compareNumber.floatValue && currentIndex != 0) {
lastNumber = array[currentIndex - 1];
}
return lastNumber;
}
I'm really bored right now, so I'm trying to test the fastest method. Here's how I did it.
NSMutableArray * numbersArray = [NSMutableArray new];
for (int i = 0; i < 100000; i++) {
float floater = i / 100.0;
[numbersArray addObject: #(floater)];
}
// courtesy #RobMayoff
NSDate * binaryDate = [NSDate date];
NSNumber * closestNumberBinary = [self binaryClosestLowestNumberForNumber:#4.4 inArray:numbersArray];
NSLog(#"Found closest number binary: %# in: %f seconds", closestNumberBinary, -[binaryDate timeIntervalSinceNow]);
// The Quartal Version
NSDate * quartalDate = [NSDate date];
NSNumber * closestNumberQuartal = [self quartalClosestLowestNumberForNumber:#4.4 inArray:numbersArray];
NSLog(#"Found closest number quartal: %# in: %f seconds", closestNumberQuartal, -[quartalDate timeIntervalSinceNow]);
// The incremental version
NSDate * incrementalDate = [NSDate date];
NSNumber * closestNumberIncremental = [self incrementalClosestLowestNumberForNumber:#4.4 inArray:numbersArray];
NSLog(#"Found closest number incremental: %# in: %f seconds", closestNumberIncremental, -[incrementalDate timeIntervalSinceNow]);
And here's the output:
Found closest number binary: 4.4 in: 0.000030 seconds
Found closest number quartal: 4.4 in: 0.000015 seconds
Found closest number incremental: 4.4 in: 0.000092 seconds
And another test case:
Found closest number binary: 751.48 in: 0.000030 seconds
Found closest number quartal: 751.48 in: 0.000016 seconds
Found closest number incremental: 751.48 in: 0.013042 seconds

if x > 0 but less than y

Sorry for kind of stupid question.
I use an UITextField, where I can enter some numbers.
No i use this code to detect if the entered number is 0, greater than 0, and less than 15.
if (myNr <= 15){
NSLog (#"the number is OK");
}
else if (myNr > 15)
{
NSLog(#"this number doesn't existing");
}
else if (myNr == 0)
{
NSLog(#"number should be between 1 and 15");
}
I got some errors when the number is 0.
i Need to be able to insert numbers only between 1 and 15, if the number is 0 or greater then 15, NSLog should say.
thanks
you should put if(myNr == 0) at first
if (myNr == 0)
{
NSLog(#"number should be between 1 and 15");
} else if (myNr <= 15)
{
NSLog (#"the number is OK");
}
else if (myNr > 15)
{
NSLog(#"this number doesn't existing");
}
What error do you get?
Offhand, remember: Capitalization matters. NSLog is different than nslog.
Your code reduces to:
if (myNr <= 15)
{
NSLog(#"the number is OK");
}
else
{
NSLog(#"this number doesn't existing");
}
The case for 0 is never reached.
Remember the tests are considered sequentially.

Create a non-repeating random number [duplicate]

This question already has answers here:
Non repeating random numbers in Objective-C
(6 answers)
Closed 8 years ago.
I would like to know how to make it so that the same picture is not chosen twice in a row. Lets say pictures are given a number 1-3. If picture 1 is chosen, then picture 1 will not be chosen next. If picture 3 is chosen, then picture 1 can be chosen again, and so on.
I know that I would have to use a while statement, except I don't know how. Heres what I have as of now:
- (void)chooseBackgroundImage{
if(thisNumber % 10 == 0){
int chooseBackgroundImage = arc4random() % 7;
switch (chooseBackgroundImage) {
case 0:
backgroundImage.image = [UIImage imageNamed:#"CyanToYellowBackground.png"];
break;
case 1:
backgroundImage.image = [UIImage imageNamed:#"GreenToBlueBackground.png"];
break;
case 2:
backgroundImage.image = [UIImage imageNamed:#"OrangeToGreenBackground.png"];
break;
case 3:
backgroundImage.image = [UIImage imageNamed:#"OrangeToPurpleBackground.png"];
break;
case 4:
backgroundImage.image = [UIImage imageNamed:#"PurpleToCyanBackground.png"];
break;
case 5:
backgroundImage.image = [UIImage imageNamed:#"RedToBlueBackground.png"];
break;
case 6:
backgroundImage.image = [UIImage imageNamed:#"YellowToRedBackground.png"];
break;
}
}
}
I've also tried using:
- (void)chooseBackgroundImage{
if(slogansGenerated % 10 == 0){
int chooseBackgroundImage = arc4random() % 7;
while(chooseBackgroundImage == oldChooseBackgroundImage){
switch (chooseBackgroundImage) {
case 0:
backgroundImage.image = [UIImage imageNamed:#"CyanToYellowBackground.png"];
break;
case 1:
backgroundImage.image = [UIImage imageNamed:#"GreenToBlueBackground.png"];
break;
case 2:
backgroundImage.image = [UIImage imageNamed:#"OrangeToGreenBackground.png"];
break;
case 3:
backgroundImage.image = [UIImage imageNamed:#"OrangeToPurpleBackground.png"];
break;
case 4:
backgroundImage.image = [UIImage imageNamed:#"PurpleToCyanBackground.png"];
break;
case 5:
backgroundImage.image = [UIImage imageNamed:#"RedToBlueBackground.png"];
break;
case 6:
backgroundImage.image = [UIImage imageNamed:#"YellowToRedBackground.png"];
break;
}
int oldChooseBackgroundImage = chooseBackroundImage
}
}
But nothing seems to work. Is there any way to create a non-repeating random number?
The following is probably random enough for you needs:
First add an instance variable, say, lastChosenBackgroundImage.
After:
int chooseBackgroundImage = arc4random() % 7;
add:
if(chooseBackgroundImage == lastChosenBackgroundImage)
chooseBackgroundImage = (chooseBackgroundImage + 1) % 7; // same as last time, move to next choice
lastChosenBackgroundImage = chooseBackgroundImage; // remember for next time
This does mean that picking the next image is twice as probable as picking any of the other ones, but I suspect that will not be a significant issue for your use case.
I recon you're looking for something like this.
-(int)getNonRepeatedRandom{
int randomNumber = -1;
do{
randomNumber = arc4random_uniform(7);
} while (randomNumber == oldRandomNumber);
oldRandomNumber = randomNumber; //set the random number to old random so you can check it on the next run.
return randomNumber;
}
oldRandomNumber will have to be an iVar for this to work though.
You should use arc4random_uniform instead of arc4random modulus to get rid of modulous bias.
Use this utility function to give you random integers between a range (in your case 0 and 6) -
#define MAX_ATTEMPTCOUNT 10
// Provides a random number between the range (both inclusive).
+ (int)randomIntegerInRange:(int)fromInt toInteger:(int)toInt excluding:(NSArray *)excludeNumbers {
NSAssert((toInt - fromInt) > 0 && (!excludeNumbers ? YES : (toInt - (fromInt - 1)) >= [excludeNumbers count]), #"Invalid range");
static int randomAttempts = 0;
srandom(time(NULL));
int randomInteger = fromInt + random() % (toInt - (fromInt - 1));
if (excludeNumbers != nil) {
for (NSNumber *number in excludeNumbers) {
if ([number intValue] == randomInteger) {
if (randomAttempts == MAX_ATTEMPTCOUNT) {
// Reached the maximum attempt count to get the random number but failed to find one.
break;
}
else {
// Recursive call to get obtain the next number.
++randomAttempts;
randomInteger = [self randomIntegerInRange:fromInt toInteger:toInt excluding:excludeNumbers];
}
break;
}
}
if (randomAttempts >= MAX_ATTEMPTCOUNT) {
// Pick up the first number that's not there in visited words.
randomAttempts = 0; // Reset the counter for next attempt.
randomInteger = fromInt;
for (; randomInteger <= toInt; ++randomInteger) {
bool found = NO;
for (NSNumber *number in excludeNumbers) {
if ([number intValue] == randomInteger) {
// Found the number.
found = YES;
break;
}
}
if (!found) break;
else continue;
}
}
}
return randomInteger;
}
Add the returned integer in an array (array of excluded numbers) which is actually passed as parameter (excludeNumbers).
Let me know if any issue (I made it for one of my project so may not completely suit your need so feel free to modify it or ask me)

Resources