What does stringWithFormat:#"%1$#%2$d" do? - objective-c

stack = [NSString stringWithFormat:#"%1$#%2$d", stack, number];
I'm following a Xcode calculator tutorial, and I'm not too sure what does the %1$#%2$d represents. Please guide me.

%# says the argument is an Objective-C object and it sends one of the description selectors to get the string that will be inserted into the final string.
%1$# says the same thing, but specifies the first argument.
%d is a signed, 32-bit integer.
%2$d specifies the second argument is a signed, 32-bit integer.

This format is used to explicitly select which argument should be replaced in the string so 1$ is for the first argument, 2$ for the 2nd etc...
The '#' is for ObjC objects (which in general displayes an object's description), and 'd' is for integers
In this case it could also be written simply as :
stack = [NSString stringWithFormat:#"%#%d", stack, number];

I assume you know what %# and %d mean. By default, the first specifier(such as %#) will be replaced by the value of the first argument in argument list, and so on. However, n$ gives you the power to specify the argument at which position you want to use its value to replace the specifier containing n$.
In fact, a simple example is much clearer:
NSString *aString = #"ultimate answer";
int anInteger = 42;
NSLog(#"The %# is %d.", aString, anInteger); // The ultimate answer is 42.
NSLog(#"The %1$# is %2$d.", aString, anInteger); // The ultimate answer is 42.
NSLog(#"%2$d is the %1$#.", aString, anInteger); // 42 is the ultimate answer.

[NSString stringWithFormat:#"%1$#%2$d", stack, number];
breaks down logically to mean you want a string (you get that from string with format), displaying two items (you can see that from the items after the string, and the number of % symbols in the format.
%1$#%2$d is for two items, you can break them by the %, %1 and %2 mean first and second.
%1$# - # represents an object that wil be translated to a string
%2$d - d represents a decimal.

Related

How to do NSLog with variable

What should be the correct format of the below to print *newString ?
NSString *newString = #"Hello this is a string!";
NSLog(#newString);
NSLog works pretty much as a C printf, with the addition of the %# string format specifier, which is meant for objects. Being NSString an object, %# is the right format to use:
NSString *newString = #"Hello this is a string!";
NSLog(#"%#", newString);
For as tempting as it can look, NEVER do
NSLog(newString); //NONONONONO!
since it's a terrible practice that may lead to unexpected crashes (not to mention security issues).
More info on the subject: Warning: "format not a string literal and no format arguments"
The # symbol is just a shorthand for specifying some common Objective-C objects. #"..." represents a string (NSString to be specific, which is different from regular C strings), #[...] represents an array (NSArray), #{...} represents a dictionary (NSDictionary).
On the first line, you've already specified a NSString object using the # sign. newString is now an NSString instance. On the second line, you can just give it's variable name:
NSLog(newString);
You could theoretically just give the variable name, but it is a dangerous approach. If newString has any format specifiers, your app may crash/mess up (or access something that it shouldn't be accesing) because NSLog would try to read the arguments corresponding to the format specifiers, but the arguments don't exist. The safe solution would be NSLog(#"%#", newString);. The first argument to NSLog is now hard-coded and can't be changed. We now know that it will expect a single argument, that we are providing that argument, newString, so we are safe.
Because you've already specified a string and just passing that instance to NSLog, you don't need the # sign again.

Seems like null NSString has length 6?

I have a person object of class Person with property is address, age. When I check properties, I print address on screen with:
NSLog(#"Add: %#, length: %i", person.address, [person.address length]);
The result is: Add: nil, length: 6
Can you explain for me why the string is null but its length shows as 6?
Thanks.
You are probably getting the string value of "(null)" in the field somehow, which is 6 characters long.
What type is address? NSString I assume? use %d or %lu for length (and cast to unsigned long if using %lu) instead of %i - that should give correct result.
Length gives a NSUInteger as a result, correct string format specifier would hence be %lu although %d should also work (thinking of it, I always use %d). I never as %i...
NSLog(#"%lu", (unsigned long)string.length)
Look at the format specifies:
https://developer.apple.com/library/mac/ipad/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
The answer you're probably looking for is: you're using the wrong string format specifier. I'm not sure what %i is; %d is for integers and %u for unsigned, so you need:
NSLog(#"Add: %#, lenght: %u", person.address, [person.address length]);
But... the length is possibly not returning what you think it is.
If person.address is nil, then sending the message length to it won't return the length (what is the length of "nothing"?). As it happens, the Objective C runtime will return zero so your example "works" but is arguably not correct.

Working with big numbers in Objective-C?

I need to convert values like 1393443048683555715 to HEX. But, first of all, i cann't display it as decimal using NSLog(), for example.
Ok, it works:
NSLog(#"%qu", 1393443048683555706);
But what about converting to HEX. What type i have to use to store this big value?
NSLog([NSString stringWithFormat: #"%x", 1393443048683555706]);
// result eb854b7a. It's incorrect result!
but i forgot to say that this big number represented as string #"1393443048683555706" (not int)
You can use %qi and %qu format specifiers with NSLog to display 64-bit integers. Your constant appears to fit in 64-bit signed number, with the limits of:
[−9223372036854775808 to 9223372036854775807]
The "x" format specifier is for 32-bit numbers; you need to use either "qx" or "qX" (depending on whether you want the letter values to be uppercase or not). These are the formatters for unsigned long long values, see:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265-SW1
Next, you should not pass a string as you have done above directly to NSLog - this can cause a crash.
NSLog(string); // bad!!
NSLog(#"%#", string); // good
So if your value comes as a string, you'll want to do this:
NSString *longNumber = #"1393443048683555706";
NSLog(#"%qx", [longNumber longLongValue]);
If the string value can't be coerced to a number, longLongValue will return 0. I'll leave it to you do handle the error (and bounds) checking - see NSString for details.
If you want to save the hex value as a string, do this:
NSString *hexRepresentation = [NSString stringWithFormat:#"%qx", [longNumber longLongValue]];
Again, best to take care for error handling.

#"%# in Objective C?

I was following a tut and found a line of code like #"%# button pressed.". I'm pretty sure the relevant part is the %#, but is the first # an escape sequence or what?
Anyways, searching symbols doesn't go well in any search engine so I thought I'd ask. I think the %# is like {0} in C#?
%# is a format specifier. Functions such as NSLog and methods such as +stringWithFormat: will replace %# with the description of the provided Objective-C or Core Foundation object argument.
For example:
NSString *myName = #"dreamlax";
NSLog (#"My name is: %#", myName);
This will log the output "My name is: dreamlax". See here for more information format specifiers.
The initial # symbol at the beginning of the string tells the compiler to create a static instance of an NSString object. Without that initial # symbol, the compiler will create a simpler C-style string. Since C-style strings are not Objective-C objects you cannot add them to NSArray or NSDictionary objects, etc.
#"some string" means this is an NSString literal.
The string as show in #"CupOverflowException", is a constant
NSString object. The # sign is used
often in Objective-C to denote
extentions to the language. A C string
is just like C and C++, "String
constant", and is of type char *
I found this page which might help - http://www.yetanotherchris.me/home/2009/6/22/objective-c-by-example-for-a-c-developer.html
It seems that you are on the right track.
I'm still fairly new to the language, but it looks like the # specifies that the variable being passed/created is an NSObject, or a compiler directive.
As mentioned above, if you use it like this:
#"someText"
you're instantiating an NSString object, and setting the text of that object to someText. If you look at a good ol' C-style format specifier such as:
..."This is some text, and this is a float: %f", myFloat);
You're creating some text and telling the compiler to put the floating point string representation of myFloat into the string. %# is a format specifier, just like %f, %d, %c, %s and any other format specifier you're used to. However, if you use %# as follows:
... "This is some text, and this is an object:%#", myObject];
What you're doing is (I believe) telling the compiler that myObject is an object, and that you want it to include the output of the description method (ie. [myObject description]) in the string that you're creating.

How to find out if there is an "." in an NSString?

Have got an
NSString *str = #"12345.6789"
and want to find out if there is that "." character inside of it. I'm afraid that there are ugly char-encoding issues when I would just try to match an #"." against this? How would you do it to make sure it always finds a match if there is one?
I just need to know that there is a dot in there. Everything else doesn't matter.
You can use rangeOfString: message to get the range where your "." is.
The prototype is:
- (NSRange)rangeOfString:(NSString *)aString
You can find more info about this message in: Mac Dev Center
There would be something like this:
NSRange range;
range = [yourstring rangeOfString:#"."];
NSLog(#"Position:%d", range.location);
If you need to, there is another message ( rangeOfString:options: ) where you can add some options like "Case sensitive" and so on.
If [str rangeOfString:#"."] returns anything else than {NSNotFound, 0}, the search string was found in the receiver. There are no encoding issues as NSString takes care of encoding. However, there might be issues if your str is user-provided and could contain a different decimal separator (e.g., a comma). But then, if str really comes from the user, many other things could go wrong with that comparison anyway.
To check . symbol, it will be useful.
if ([[str componentsSeparatedByString:#"."] count]>1) {
NSLog(#"dot is there");
}else{
NSLog(#"dot is not there");
}
If what you really want to do is determine whether the string represents a number with a fractional part, a better solution is to feed the string to a number formatter, then examine the number's doubleValue to see whether it has a fractional part.
For the latter step, one way would be to use the modf function, which returns both the fractional part (directly) and the integral part (by reference). If the fractional part is greater than zero (or some appropriately small fraction below which you're willing to tolerate), then the number has a fractional part.
The reason why this is better is because not everybody writes decimal fractions in the “12345.6789” format. Some countries use a comma instead, and I'm sure that's not the only variation. Let the number formatter handle such cases for you.
I wrote a little method to make things a little more natural if you use this sort of thing a whole bunch in your project:
+(BOOL)seeIfString:(NSString*)thisString ContainsThis:(NSString*)containsThis
{
NSRange textRange = [[thisString lowercaseString] rangeOfString:[containsThis lowercaseString]];
if(textRange.location != NSNotFound)
return YES;
return NO;
}
Enjoy!