About the formation in NSLog in Objective-C - objective-c

const char *string ="Hi there,this is a C string";
NSData *data=[NSData dataWithBytes:string
length:strlen(string)+1];
NSLog(#"data is %#",data);
NSLog(#"%lu byte string is '%s'",[data length],[data bytes]);
This can be implied successfully. If the last sentence is:
NSLog(#"%d byte string is '%s'",[data length],[data bytes]);
it will warn that conversion specifies type 'int' but argument has typed 'NSUInteger' (aka'usigned long')
Why %d can't?

NSUInteger is basically an unsigned long, so use %lu instead.

%d means 'int'. NSUInteger is not an 'int', so %d won't work. You have to match format specifiers with the type. If you specify the wrong type, your program can crash or more likely, it'll print garbage.

Related

NSUInteger should not be used in format strings?

Here's my code in all it's glory:
[NSString stringWithFormat:#"Total Properties: %d", (int)[inArray count]];
Which gets me an Xcode 5.1 warning:
Values of type 'NSUInteger' should not be used as format arguments; add an explicit cast to 'unsigned long' instead
Ok so I'm confused. The value really is a 32-bit int, and I cast it to a 32-bit int. So what is this NSUInteger it's complaining about (the count I assume) and why doesn't this cast fix it?
NSUInteger and NSInteger are different lengths on 32-bit (int) and 64-bit (long). In order for one format specifier to work for both architectures, you must use a long specifier and cast the value to long:
Type Format Specifier Cast
---- ---------------- ----
NSInteger %ld long
NSUInteger %lu unsigned long
So, for example, your code becomes:
[NSString stringWithFormat:#"Total Properties: %lu", (unsigned long)[inArray count]];
There is very little work to do, really, because Xcode's Fix-It feature will do this for you automatically.
It is also possible to use the "z" and "t" modifiers for CPU-independent format strings, e.g.
NSInteger x = -1;
NSUInteger y = 99;
NSString *foo = [NSString stringWithFormat:#"NSInteger: %zd, NSUInteger: %tu", x, y];
The underlying type of NSUInteger changes based on the platform: it is a 32-bit unsigned integer on 32-bit platforms, and a 64-bit unsigned integer on 64-bit platforms.
In the Platform Dependencies section on of the String Programming Guide Apple suggests that you do the following:
To avoid the need to use different printf-style type specifiers depending on the platform, you can use the specifiers shown in Table 3. Note that in some cases you may have to cast the value.
For NSUInteger use format %lu or %lx, and cast the value to unsigned long.
Hence your code needs to be changed as follows to avoid the warning:
[NSString stringWithFormat:#"Total Properties: %lu", (unsigned long)[inArray count]];
You could also try using NSNumber methods:
[NSString stringWithFormat:#"Total Properties: %#", [[NSNumber numberWithUnsignedInteger:[inArray count]] stringValue]];

How do I do the equivalent of println in Objective-C?

In Java, I would do this:
String temp = ".";
System.out.println(temp);
How might I do that in Objective-C?
Objective-C doesn't really have its own dedicated printing function. NSLog will print what you give it along with a bunch of debugging information. For straight-up printing, the C printf() is still basically the standard. As the equivalent to your code, I'd write:
NSString *temp = #".";
printf("%s\n", [temp UTF8String]);
NSString *temp = #".";
NSLog(#"%#", temp);
NSLog format specifiers:
%# Object, calls the Object's description method
%d, %i signed int
%u unsigned int
%f float/double
%p for pointers to show the memory address
%zu value of type size_t (for sizeof(variable function)
%s C strings
\u can used for arbitrary unicode chars example:NSLog(#"\u03c0");//π

Cannot implicitly convert type 'integer' to 'NSString' -

I want to ask very simple thing about conversion between type.
int theinteger = 75;
NSLog(#"Before theinteger is: %#", theinteger);
NSString *string = [NSString stringWithFormat:#"%d", theinteger];
NSLog(#"After theinteger is: %#", string);
Output is like
Before theinteger: 75
After theinteger: 114503696
What does this mean? Why after conversion my data is changed to 114503696?
When I tried
int theinteger = -1;
It's OK
Before theinteger: -1
After theinteger: -1
Am I missing something?
Without seeing any evidence of it, I assume theinteger is, in fact, of type NSInteger or int.
When using a specifier, try using %i:
NSInteger theinteger = 75;
NSLog(#"theinteger is: %i", theinteger);
Output
theinteger is: 75
Here's a list of specifiers.
You shouldn't be using %# as a format specifier for an integer, as in your first log statement. However, my guess is the code you've posted here isn't actually the code you're using, because this line NSLog(#"Before theinteger is: %#", the integer); won't actually compile due to the space in "the integer". Can you copy/paste your actual code?
Anyway, %# is the format specifier for Objective-C objects. When NSLog() sees a %#, it substitutes it with the NSString returned by calling -(NSString *)description on the corresponding object in the variables list. In your case, NSLog() sees the %# and assumes that means that theinteger is an Objective-C object, which it is not.
If you want to print an integer, you should use a format specifier of %i (or another of the several integer format specifiers):
NSLog(#"Before theinteger is: %i", theinteger);

Bad access on NSString length

with
NSString *responseData = [request responseString];
I get a string like (10).
Now I want to remove the brackets to get just the number. So I first wanted to get the length of the string
NSLog(#"%#",[responseData length]);
But I get a Thread 1: Program received signal: "EXC_BAD:ACCESS"
Any ideas?
NSString::length returns an unsigned integer. So, try -
NSLog(#"%i",[responseData length]); // format specifier is %i and not %#
// Even better if %u is used.
NSLog format specifiers

NSLog incorrect encoding

I've got a problem with the following code:
NSString *strValue=#"你好";
char temp[200];
strcpy(temp, [strValue UTF8String]);
printf("%s", temp);
NSLog(#"%s", temp);
in the first line of the codes, two Chinese characters are double quoted. The problem is printf function can display the Chinese characters properly, but NSLog can't.
Thanks to all. I figured out a solution for this problem. Foundation uses UTF-16 by default, so in order to use NSLog to output the c string in the example, I have to use cStringUsingEncoding to get UTF-16 c string and use %S to replace %s.
NSString *strValue=#"你好";
char temp[200];
strcpy(temp, [strValue UTF8String]);
printf("%s", temp);
strcpy(temp, [strValue cStringUsingEncoding:NSUTF16LittleEndianStringEncoding]);
NSLog(#"%S", temp);
NSLog's %s format specifier is in the system encoding, which seems to always be MacRoman and not unicode, so it can only display characters in MacRoman encoding. Your best option with NSLog is just to use the native object format specifier %# and pass the NSString directly instead of converting it to a C String. If you only have a C string and you want to use NSLog to display a message instead of printf or asl, you will have to do something like Don suggests in order to convert the string to an NSString object first.
So, all of these should display the expected string:
NSString *str = #"你好";
const char *cstr = [str UTF8String];
NSLog(#"%#", str);
printf("%s\n", cstr);
NSLog(#"%#", [NSString stringWithUTF8String:cstr]);
If you do decide to use asl, note that while it accepts strings in UTF8 format and passes the correct encoding to the syslog daemon (so it will show up properly in the console), it encodes the string for visual encoding when displaying to the terminal or logging to a file handle, so non-ASCII values will be displayed as escaped character sequences.
My guess is that NSLog assumes a different encoding for 8-bit C-strings than UTF-8, and it may be one that doesn't support Chinese characters. Awkward as it is, you might try this:
NSLog(#"%#", [NSString stringWithCString: temp encoding: NSUTF8StringEncoding]);
I know you are probably looking for an answer that will help you understand what's going on.
But this is what you could do to solve your problem right now:
NSLog(#"%#", strValue);
# define NSLogUTF8(a,b) NSLog(a,[NSString stringWithCString:[[NSString stringWithFormat:#"%#",b] cStringUsingEncoding:NSUTF8StringEncoding] encoding:NSNonLossyASCIIStringEncoding])
#define NSLogUTF8Ex(a,b) NSLog(a,[MLTool utf8toNString:[NSString stringWithFormat:#"%#",b]])
+(NSString*)utf8toNString:(NSString*)str{
NSString* strT= [str stringByReplacingOccurrencesOfString:#"\\U" withString:#"\\u"];
//NSString *strT = [strTemp mutableCopy];
CFStringRef transform = CFSTR("Any-Hex/Java");
CFStringTransform((__bridge CFMutableStringRef)strT, NULL, transform, YES);
return strT;
}