Converting int to NSString - ios

I thought I had nailed converting an int to and NSString a while back, but each time I run my code, the program gets to the following lines and crashes. Can anyone see what I'm doing wrong?
NSString *rssiString = (int)self.selectedBeacon.rssi;
UnitySendMessage("Foo", "RSSIValue", [rssiString UTF8String] );
These lines should take the rssi value (Which is an NSInt) convert it to a string, then pass it to my unity object in a format it can read.
What am I doing wrong?

NSString *rssiString = [NSString stringWithFormat:#"%d", self.selectedBeacon.rssi];
UPDATE: it is important to remember there is no such thing as NSInt. In my snippet I assumed that you meant NSInteger.

If you use 32-bit environment, use this
NSString *rssiString = [NSString stringWithFormat:#"%d", self.selectedBeacon.rssi];
But you cann't use this in 64-bit environment, Because it will give below warning.
Values of type 'NSInteger' should not be used as format arguments; add
an explicit cast to 'long'
So use below code, But below will give warning in 32-bit environment.
NSString *rssiString = [NSString stringWithFormat:#"%ld", self.selectedBeacon.rssi];
If you want to code for both(32-bit & 64-bit) in one line, use below code. Just casting.
NSString *rssiString = [NSString stringWithFormat:#"%ld", (long)self.selectedBeacon.rssi];

I'd like to provide a sweet way to do this job:
//For any numbers.
int iValue;
NSString *sValue = [#(iValue) stringValue];
//Even more concise!
NSString *sValue = #(iValue).stringValue;

NSString *rssiString = [self.selectedBeacon.rssi stringValue];
For simple conversions of basic number values, you can use a technique called casting. A cast forces a value to perform a conversion based on strict rules established for the C language. Most of the rules dictate how conversions between numeric types (e.g., long and short versions of int and float types) are to behave during such conversions.
Specify a cast by placing the desired output data type in parentheses before the original value. For example, the following changes an int to a float:
float myValueAsFloat = (float)myValueAsInt;
One of the rules that could impact you is that when a float or double is cast to an int, the numbers to the right of the decimal (and the decimal) are stripped off. No rounding occurs. You can see how casting works for yourself in Workbench by modifying the runMyCode: method as follows:
- (IBAction)runMyCode:(id)sender {
double a = 12345.6789;
int b = (int)a;
float c = (float)b;
NSLog(#"\ndouble = %f\nint of double = %d\nfloat of int = %f", a, b, c);
}
the console reveals the following log result:
double = 12345.678900
int of double = 12345
float of int = 12345.000000
original link is http://answers.oreilly.com/topic/2508-how-to-convert-objective-c-data-types-within-ios-4-sdk/

If self.selectedBeacon.rssi is an int, and it appears you're interested in providing a char * string to the UnitySendMessage API, you could skip the trip through NSString:
char rssiString[19];
sprintf(rssiString, "%d", self.selectedBeacon.rssi);
UnitySendMessage("Foo", "RSSIValue", rssiString );

Related

How do I convert NSString to an encoding other than UTF-8?

I'm working with c in iOS Project I'm trying to convert my string to respected type in c , below code is supposed to send to core Library
typedef uint16_t UniCharT;
static const UniCharT s_learnWord[] = {'H', 'e','l','\0'};
what i have done till now is string is the one what I'm passing
NSString * string = #"Hel";
static const UniCharT *a = (UniCharT *)[string UTF8String];
But it is failing to convert when more than one character , If i pass one character then working fine please let me where i miss, How can i pass like s_learnWord ?
and i tried in google and StackOverFLow none of the duplicates or answers didn't worked for me like this
Convert NSString into char array I'm already doing same way only.
Your question is a little ambiguous as the title says "c type char[]" but your code uses typedef uint16_t UniCharT; which is contradictory.
For any string conversions other than UTF-8, you normally want to use the method getCString:maxLength:encoding:.
As you are using uint16_t, you probably are trying to use UTF-16? You'll want to pass NSUTF16StringEncoding as the encoding constant in that case. (Or possibly NSUTF16BigEndianStringEncoding/NSUTF16LittleEndianStringEncoding)
Something like this should work:
include <stdlib.h>
// ...
NSString * string = #"part";
NSUInteger stringBytes = [string maximumLengthOfBytesUsingEncoding];
stringBytes += sizeof(UniCharT); // make space for \0 termination
UniCharT* convertedString = calloc(1, stringBytes);
[string getCString:(char*)convertedString
maxLength:stringBytes
encoding:NSUTF16StringEncoding];
// now use convertedString, pass it to library etc.
free(convertedString);

How to convert a NSString to long double?

I am dealing with a long double value that can have huge values.
At one time I have this number represented as NSString and I need to convert it to long double. I see that the only API I have is
[myString doubleValue];
I don't see a longDoubleValue.
Trying to convert this number using doubleValue...
long double x = (long double)[#"3765765765E933" doubleValue];
gives me inf and the number in question is a legit long double value, as these numbers can go up to 1.18973149535723176502E+4932.
How do I do that?
Perhaps create a category on NSString yourself
NSArray *array = [myString componentsSeparatedByString:#"E"];
long double mantis = (long double)[array[0] doubleValue];
long double exponent = (long double)[array[1] doubleValue];
return mantis * exponent;
There will possibly be a loss of data though
edit
It would seem that long double on iOS is the same size as double. Maybe you will need a custom class to hold such large numbers.
You could probably do:
long double s = strtold(myString.UTF8String, NULL);
but if sizeof(long double) is the same as sizeof(double) as mag_zbc says, you might still get Inf.
If you want to go the pow() route, there is powl() which takes and returns long doubles.
You can do this using the C library sscanf function. Here is a sample Objective-C wrapper:
long double stringToLongDouble(NSString *str)
{
long double result = 0.0L;
int ret = sscanf(str.UTF8String, "%Lg", &result);
if (ret != 1)
{
// Insert your own error handling here, using NSLog for demo
NSLog(#"stringToLongDouble: could not parse '%#' as long double", str);
return 0.0L;
}
return result;
}
The return from sscanf will be 1 if it succeeds. For possible error returns see the documentation (man 3 scanf in Terminal) and you need to decide how to handle these, the above example just does an NSLog.
Note: The size & precision of long double may vary by platform/OS version. The above has been tested with your value on El Capitan and iOS 10 (simulator only) using Xcode 8.
HTH
In fact the answer of mag_zbc is almost there. The last line is incorrect.
Considering that the string has exponent, the correct is:
- (long double)longDoubleValue {
NSArray *array = [string componentsSeparatedByString:#"E"];
long double mantis = (long double)[array[0] doubleValue];
long double exponent = (long double)[array[1] doubleValue];
long double multiplier = powl(10.0L, exponent);
return mantis * multiplier;
}

Get the data stored in address using the * operator

int i = 17;
int *addressOfI = &i;
printf("the int stored at addressOfI is %d\n", *addressOfI);
The question is: If I can get the data stored in addressOfI using the * operator, why it doesn't works for type NSString? like following:
NSString *string = #"Hello world!"
printf("the NSString stored at string is %#\n", *string);
why it doesn't works for type NSString?
Because NSString is an Objective-C object and not a primitive type. The NSString * pointer actually points to a struct objc_object which provides the framework for the object system. You can probably "see" some primitive types within this framework (i.e. members of objc_object) however it's supposed to be a black box to normal developers.
The actual reason your second piece of code will crash is that the %# format specifier expects to call the description method on the object you pass in as an argument and you have dereferenced that object pointer so it's no longer a valid object pointer.

Objective-C how to convert a keystroke to ASCII character code?

I need to find a way to convert an arbitrary character typed by a user into an ASCII representation to be sent to a network service. My current approach is to create a lookup dictionary and send the corresponding code. After creating this dictionary, I see that it is hard to maintain and determine if it is complete:
__asciiKeycodes[#"F1"] = #(112);
__asciiKeycodes[#"F2"] = #(113);
__asciiKeycodes[#"F3"] = #(114);
//...
__asciiKeycodes[#"a"] = #(97);
__asciiKeycodes[#"b"] = #(98);
__asciiKeycodes[#"c"] = #(99);
Is there a better way to get ASCII character code from an arbitrary key typed by a user (using standard 104 keyboard)?
Objective C has base C primitive data types. There is a little trick you can do. You want to set the keyStroke to a char, and then cast it as an int. The default conversion in c from a char to an int is that char's ascii value. Here's a quick example.
char character= 'a';
NSLog("a = %ld", (int)test);
console output = a = 97
To go the other way around, cast an int as a char;
int asciiValue= (int)97;
NSLog("97 = %c", (char)asciiValue);
console output = 97 = a
Alternatively, you can do a direct conversion within initialization of your int or char and store it in a variable.
char asciiToCharOf97 = (char)97; //Stores 'a' in asciiToCharOf97
int charToAsciiOfA = (int)'a'; //Stores 97 in charToAsciiOfA
This seems to work for most keyboard keys, not sure about function keys and return key.
NSString* input = #"abcdefghijklkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%^&*()_+[]\{}|;':\"\\,./<>?~ ";
for(int i = 0; i<input.length; i ++)
{
NSLog(#"Found (at %i): %i",i , [input characterAtIndex:i]);
}
Use stringWithFormat call and pass the int values.

Poor compiler warnings

how to get rid of the compiler warning in XCode 5.1
in Stringtable is of course a string with a format specifier (updated: now in front of code)
"fmtDetail" = "Count: %d";
int number = 0;
//Compiler warning: Data argument not used by format string
NSString *text = [NSString stringWithFormat:NSLocalizedString(#"fmtDetail", nil), number];
//this gets no warning
NSString *fmtDetail = NSLocalizedString(#"fmtDetail", nil);
NSString *text2 = [NSString stringWithFormat:fmtDetail, number];
It is not the compiler warning that is poor - you should correct your code.
There seems to be an %d (or similar) missing in the #"fmDetail".
Or you should get rid of the number argument - that is not used.
Depends on what you are actually trying to do...
NSString *text = [NSString stringWithFormat:NSLocalizedString(#"fmtDetail%d", nil), number];
NSString *text = [NSString stringWithFormat:NSLocalizedString(#"fmtDetail %d", nil), number];
NSString *text = [NSString stringWithString:NSLocalizedString(#"fmtDetail", nil)];
Second note: this #"fmtDetail%d" should match the key in the plist dictionary (translated strings). It could also be simly #"theDeatils" - the string that returned from your plist is the one that should actually hold formatting data for the string.
Why would one want to use the %d in the key? Because NSLocalizedString returns the key as the result if it doesn't find string with appropriate key.
EDIT: MartinR found the real reason for why this warning appears. Just a note that might be useful: since localizing strings usually means translation into many languages (duh) you might need to use numbered placeholders - not all languages share the same basic sentence structure.
This seems to be not a bug, but a new feature of the compiler that comes with Xcode 5.1 (beta). It expects now that in
[NSString stringWithFormat:NSLocalizedString(key, ...), arguments... ]
the key itself is a valid format for the given arguments.
(In other words, the key uses the same format specifiers as its value from the strings file).
For example:
// Source code:
[NSString stringWithFormat:NSLocalizedString(#"Count = %d", nil), number]
// Localizable.strings:
"Count = %d" = "Die Anzahl ist %d";
This is an advantage because the compiler can now check that the number and types
of the format specifiers match the actual arguments even with localizable format
strings. That was not possible before (as far as I know).
For example, this will cause a warning in Xcode 5.1 beta, but not in Xcode 5.0.2:
[NSString stringWithFormat:NSLocalizedString(#"fmtDetail %f", nil), 13];
// warning: format specifies type 'double' but the argument has type 'int' [-Wformat]
(And as #rokjarc already had pointed out, using a valid format string as key makes
sense anyway, because NSLocalizedString() returns the key if no matching string
is found in the Localizable.strings file.)

Resources