Concatenating an int to a string in Objective-c - objective-c

How do I concatenate the int length to the string I'm trying to slap into that array so it is "C10" given length == 10, of course. I see #"%d", intVarName way of doing it used else where. In Java I would of done "C" + length;. I am using the replaceObjectAtIndex method to replace the empty string, "", that I have previously populated the MSMutableArray "board" with. I am getting an error though when I add the #"C%d", length part at the end of that method (second to last line, above i++).
As part of my homework I have to randomly place "Chutes" (represented by a string of format, "C'length_of_chute'", in this first assignment they will always be of length 10 so it will simply be "C10") onto a game board represented by an array.
-(void)makeChutes: (int) length {// ??Change input to Negative number, Nvm.
//??Make argument number of Chutes ??randomly?? across the board.
for(int i = 0; i < length;){
int random = arc4random_uniform(101);
if ([[board objectAtIndex:random] isEqual:#""]) {
//[board insertObject:#"C%d",length atIndex:random];
[board replaceObjectAtIndex:random withObject:#"C%d",length];
i++;
}
}
}
Please ignore the extra and junk code in there, I left it in for context.

In Objective-C the stringWithFormat method is used for formatting strings:
NSString *formattedString = [NSString stringWithFormat:#"C%d", length];
[someArray insertObject:formattedString];
It's often easier to create your formatted string on a line of its own in Objective-C, since as you can see the call can be fairly verbose!

Related

Objective-C Displaying Numbers as Words Using Math

I have an exercise in my Objective-C book in which I must design a program using only the knowledge the book has given me so far to do so. It tells me to use math to do this not any methods from Objective-C.
What I must do is get any integer from the user and then convert each number to a word.
For example if the user enters: 956
The output must then be:
nine
five
six
I am not the best math student and definitely need help here. I can of course use loops of any kind as well as if statements and basic math operators as well as arrays but no built in methods.
I assume that I need to get each digit separated into its own integer variable and then use switch of if statements to then create the strings and display them but cannot successfully do this.
Please help, thanks!
Here's an example I quickly came up with. See the comments in the code below for an explanation.
//Create an array of number strings. They must be in order starting from 0 so the indexes line up
NSArray *numbers = #[#"zero", #"one", #"two", #"three", #"four", #"five", #"six", #"seven", #"eight", #"nine"];
//Create whatever string you're processing
NSString *numString = #"956";
//Loop through the substrings of the number string
while (numString.length > 0) {
//Get the first character in the string
int currentNum = [[numString substringToIndex:1] intValue];
//Print the number. The number string should be at the index of this value in the array
NSLog(#"%#", numbers[currentNum]);
//Remove everything before the first character
numString = [numString substringFromIndex:1];
}
Output:
nine
five
six
Here is a working example using C (one of your tags):
This one makes use of a char *[] (array of C strings) and ascii values of each char...
char *number[]={"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
int main(void)
{
char dig[20];
int len, i;
printf("enter integer: "); //instruction to user
scanf("%s", dig); //read from user
len = strlen(dig);
for(i=0;i<len;i++)
{
if(isdigit(dig[i]))//test to verify good user input (accept only digits)
{
printf("%s\n", number[dig[i]-48]); // 48-57 is range of ASCII values for 0-9
}
}
return 0;
}
Example session:

Count number of arbitrary repeating decimal numbers in NSString

In my code, I'm dealing with an NSString that contains an NSNumber value. This NSNumber value could possibly be a repeating decimal number (e.x. 2.333333333e+06) that shortens to "2.333333" in a string format. It could also be a terminating number (e.x. 2.5), negative, or irrational number (2.398571892858...) (only dealing with decimals here)
I need to have a way to figure out if there are the repeating numbers in the string (or the NSNumber, if necessary). In my code, I would have no way to know what the repeating number would be, as it's a result of computations started by the user. I have tried this for loop (see below) that doesn't work the way I want it to, due to my inexperience with string indexing/ranges/lengths.
BOOL repeat = NO; //bool to check if repeating #
double repNum, tempNum; //run in for loop
NSString *repeating = [numVal stringValue]; //string that holds possible repeating #
for (int i = 3; i <= [repeating length]-3; i++) { //not sure about index/length here
if (i == 3) {
repNum = [repeating characterAtIndex:i];
}
tempNum = [repeating characterAtIndex:i];
if (tempNum == repNum) {
repeat = YES;
} else {
repeat = NO;
}
}
This code doesn't work as I'd like it to, mainly because I also have to account for negative dashes in the string and different amounts of numbers (13 1/3 vs. 1 1/3). I've used the modffunction to separate the integers from the decimals, but that hasn't worked well for me either.
Thank you in advance. Please let me know if I can clarify anything.
EDIT:
This code works with the finding of different solutions for polynomials (quadratic formula). Hope this helps put it into context. See here. (Example input)
NSNumber *firstPlusSolution, *secondMinusSolution;
NSString *pValueStr, *mValueStr;
firstPlusSolution = -(b) + sqrt(square(b) - (4)*(a)*(c)); //a, b, c: "user" provided
firstPlusSolution /= 2*(a);
secondMinusSolution = -(b) - sqrt(square(b) - 4*(a)*(c));
secondMinusSolution /= 2*(a);
pValueStr = [firstPlusSolution stringValue];
mValueStr = [secondMinusSolution stringValue];
if ([NSString doesString:pValueStr containCharacter:'.']) { //category method I implemented
double fractionPart, integerPart;
fractionPart = modf(firstPlusSolution, &integerPart);
NSString *repeating = [NSString stringWithFormat:#"%g", fractionPart];
int repNum, tempNum;
BOOL repeat = NO;
//do for loop and check for negatives, integers, etc.
}
if ([NSString doesString:mValueStr containCharacter'.']) {
//do above code
//do for loop and check again
}
Use C. Take the fractional part. Convert to a string with a known accuracy. If length of string indicates that last digits are missing, then it does not repeat. Use NSString-UTF8String to convert a string. Get rid of the last digit (may be rounding or actual floating point arithmetic error). Use function int strncmp ( const char * str1, const char * str2, size_t num ) to perform comparison within the string itself. If the result is 8 characters long and the last 2 characters match the first 2 characters, then shall the first 6 characters be considered repeating?
Assuming that fraction knowledge your desire:
• Possibility 1: Use fractions. Input fractions. Compute with fractions. Output fractions. Expand upon one of the many examples of a c++ fraction class if necessary and use it.
• Possibility 2: Choose an accuracy which is much less than double. Make a fraction from the result. Reduce the fraction allowing rounding based upon accuracy.
I suggest use not optimal but easy to write solution
Create NSMutableDictionary that will contain number as key and count of occurrence as value.
You can use componentsSeparatedByString: if numbers in string delimited by known symbol
In loop check valueForKey in dictionary and if need increase value
Last step is analyzing our dictionary and do anything you need with numbers

Replacing character within cstring - getting bad access

Is it possible to replace a character from a c string after converting it from NSString via the UTF8string method?
For example take the code below. It is to format a string with particular rule.
- (NSString *)formatString:(NSString *)input {
if (input.length==0) {
return #"";
}
//code to determine rule
....
....
// substitute output format with input characters
if (rule) {
input = [input substringFromIndex:prefix.length];
char *string = (char *)[rule UTF8String];
int repCount = 0;
for (int i=0; i<rule.length; i++) {
if (string[i] == '#') {
if (repCount < input.length)
string[i] = [input characterAtIndex:repCount++];//bad access
else
string[i] = ' ';
}
}
NSMutableString *output = [NSMutableString stringWithCString:string encoding:NSUTF8StringEncoding];
...
... //do something with the output
return output;
} else {
return input;
}
}
Initially string[0] has '#' and it should get replaced with the character in the input. This is not happening.
In a word, NO. That buffer doesn't belong to you so leave it alone.
A couple of issues:
You are casting UTF8String, which returns a const char *, to char *. UTF8String is, by definition, returning a read-only string and you should use it as such. (You really should use casts sparingly, if at all. Certainly never use casts to override const qualifiers for variables.)
If you want to perform this C-string manipulation, you have to copy the string to your own buffer. For example, use getCString or getCharacters methods (but only after you've created a buffer to receive them, and remember to add a character for the NULL terminator).
By the way, you're also returning characterAtIndex, which is a unichar (which can be larger than 8-bits), and using it in your char * buffer (8-bits per character). I'd be wary about mixing and matching those without being very careful. It is best to pick one and stick with it (and unichar offers a little more tolerance for those non-8-bit characters).
Perhaps you check for this earlier, but you're setting string to be those characters after the prefix, and then proceed to check the next rule.length number of characters. But, as far as I can tell, you have no assurances that string actually has that many characters left in it. You should test for that, or else that will also cause problems.
Personally, I'd retire this whole C-string algorithm and employ the appropriate NSString and/or NSMutableString methods to do whatever replacement you wanted, e.g. stringByReplacingCharactersInRange, stringByReplacingOccurrencesOfString, or the equivalent NSMutableString methods, replaceCharactersInRange or replaceOccurrencesOfString.

Optimise searching in an array, search by comparison of 2 strings in Objective C

I have a list of contacts retrieved from Address book stored inside a MutableArray contactList. Each contact is an object which has properties like "contactName, contactImage.... etc".
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{
//getAllContacts is a method which returns a Mutable array of Objects
self.contactList = [NSMutableArray arrayWithArray:[instance getAllContacts]];
//groupLetterToLoad could be "DEF"
for(int j=0; j<self.groupLetterToLoad.length;j++) {
//1st iteration D, 2nd iteration E and 3rd iteration F
NSString *testChar = [NSString stringWithFormat:#"%c",[self.groupLetterToLoad characterAtIndex:j]];
//check D,E,F with contact name property's first letter of the contact list array
for(int i=0;i<self.contactList.count;i++) {
NSString *firstChar =[[[self.contactList objectAtIndex:i] contactName] substringToIndex:1];
if([testChar isEqualToString: firstChar]) {
pos=i; //retrieve the index of the matched position
break;
}
}
if(pos!=-1) break;
}
});
Now this has two for loops (Time O(n^2)).. The disadvantage here is, if the groupLetterToLoad is "WXYZ", then comparison will start from W with A to W with Z.. How can I optimise it?
Ordering your array by contactName and performing a half interval search will reduce your complexity greatly if can avoid sorting every time you search (hint: keep [instance getAllContacts] sorted).
http://rosettacode.org/wiki/Binary_search#Objective-C - that's a starting point. you could replace the compare: with your first character comparison.
This isn't an algorithmic improvement, but the way you're handling characters is about the slowest way possible. If your group letters are really ASCII letters as you indicate, try this (I include the "if" in my answer because doing correct comparison of non-ASCII is really best left up to NSString):
1) Instead of using -substringToIndex to get the first character, use -characterAtIndex:0 and store a unichar
2) Instead of using +stringWithFormat:#"%c" to make a single character string, just use -characterAtIndex: and store it in a unichar
3) Instead of using -isEqualToString:, use == on the unichars
Unrelated, I'm pretty suspicious of the thread-safety of this. Are all those properties on self and instance you're accessing really not accessed on any other queue or thread?

NSString intValue not working for retrieving phone number

I have a phone number formatted as an easy to read phone number, i.e., (123) 123-4567
However, when I want to use that phone number in code, I need to parse that string into a number variable (such as an int)
However, [string intValue]; doesn't work - I've used intValue about a million times in previous projects, all with no problem, however here, every string I pass in, I get the same, random int back out:
- (int)processPhoneNumber:(NSString *)phoneNumber {
NSMutableString *strippedString = [NSMutableString stringWithCapacity:10];
for (int i=0; i<[phoneNumber length]; i++) {
if (isdigit([phoneNumber characterAtIndex:i])) {
[strippedString appendFormat:#"%c",[phoneNumber characterAtIndex:i]];
}
}
NSLog(#"clean string-- %#", strippedString);
int phoneNumberInt = [strippedString intValue];
NSLog(#"**** %d\n &i", phoneNumberInt, phoneNumberInt);
return phoneNumberInt;
}
Then when I call this method:
NSLog(#"%i", [self processPhoneNumber:self.phoneNumberTextField.text]);
I get: 2147483647. Every input I give this method returns: 2147483647
As CRD has already explained, you're trying to convert that string to a type that's too small to hold the value, and you're getting back the maximum possible value for that type.
Your real problem is deeper, however. A phone "number" isn't really a number. It doesn't represent a quantity. You would never perform arithmetic on one. It's actually a string of digits, and you should handle it that way. Don't convert it; just operate on the string.
See also What's the right way to represent phone numbers?
2147483647 is INT_MAX which is returned on overflow. How large is your phone number, will it fit into an int? Maybe you should use longLongValue?