obtaining objective c nsstring from c char[] - objective-c

code below.
i'm tryind to obtain string answers like "a1", "c4"
this is what i'm having instead of "a1": "adresse finale: \340}00\214"
with this prinf:
printf("\nadresse finale: %s",[self convertCGPointToSquareAdress:self.frame.origin]);
the method is:
-(NSString *) convertCGPointToSquareAdress:(CGPoint ) point{
int x= point.x /PIECE_WIDTH;
int y=point.y/PIECE_WIDTH;
char lettreChiffre[2];
//char chiffre;
NSString *squareAdress;
//ascii a=97 , b=98... h=105
for (int i=97; i<105; i++) {
for (int j=8; j>0; j--) {
if(i-97==x && j-1==y ){
NSLog(#"enterrrrrrrrrred if convertCGPointToSquareAdress");
lettreChiffre[0]=i;
lettreChiffre[1]=(char) j;
printf(" lettreChiffre: %s ", lettreChiffre);
NSString *squareAdress=[NSString stringWithFormat:#"%s", lettreChiffre];
break;
}
}
}
return squareAdress;
}
can you please help me?
thanks in advance.

There are three problems I can see with your code:
1.
When you do
lettreChiffre[1]=(char) j;
remember j is a number between 1 and 8, so you're getting the ASCII character whose value is j, not the character 1...8. You should use
lettreChiffre[1]= '0' + j;
2.
lettreChiffre is a char array of length 2, which means there's no room for the terminal null character. This may work, but may give you gibberish. You should instead declare
char lettreChiffre[3];
lettreChiffre[2] = '\0';
3.
You're trying to use printf to print an NSString, which it can't do. Either use
NSLog(#"adresse finale: %#", mynsstring)
or convert the NSString back to a C-string:
printf("adresse finale: %s", [mynsstring UTF8String]);
Also, as noted by #dreamlax, you don't really need the loop. I assumed you were doing something else and ran into this trouble, so we're not really seeing the full code. But, if this is really the entirety of your code, then you can simply remove the loop as #dreamlax suggested.

What is the purpose of the loop? You have a loop that essentially brute forces a matrix to calculate the “square address”. Your method will also return an uninitialized pointer if x is greater than 8.
Your entire method could be made much simpler.
- (NSString *) convertCGPointToSquareAdress:(CGRect) point
{
unsigned int x = point.x / PIECE_WIDTH;
unsigned int y = point.y / PIECE_WIDTH;
// Do some range checking to ensure x and y are valid.
char lettreChiffre[3];
lettreChiffre[0] = 'a' + x;
lettreChiffre[1] = '1' + y;
lettreChiffre[2] = '\0';
return [NSString stringWithCString:letterChiffre encoding:NSASCIIStringEncoding];
}

Related

Converting NSString to array of chars inside For Loop

I'm trying to use an existing piece of code in an iOS project to alphabetize a list of words in an array (for instance, to make tomato into amoott, or stack into ackst). The code seems to work if I run it on its own, but I'm trying to integrate it into my existing app.
Each word I want it to alphabetize is stored as an NSString inside an array. The issue seems to be that the code takes the word as an array of chars, and I can't get my NSStrings into that format.
If I use string = [currentWord UTFString], I get an error of Array type char[128] is not assignable, and if I try to create the char array inside the loop (const char *string = [curentWord UTF8String]) I get warnings relating to Initializing char with type const char discards qualifiers. Not quite sure how I can get around it – any tips? The method is below, I'll take care of storing the alphabetized versions later.
- (void) alphabetizeWord {
char string[128], temp;
int n, i, j;
for (NSString* currentWord in wordsList) {
n = [currentWord length];
for (i = 0; i < n-1; i++) {
for (j = i+1; j < n; j++) {
if (string[i] > string[j]) {
temp = string[i];
string[i] = string[j];
string[j] = temp;
}
}
}
NSLog(#"The word %# in alphabetical order is %s", currentWord, string);
}
}
This should work :
- (void)alphabetizeWord {
char str[128];
for (NSString *currentWord in wordList)
{
int wordLength = [currentWord length];
for (int i = 0; i < wordLength; i++)
{
str[i] = [currentWord characterAtIndex:i];
}
// Adding the termination char
str[wordLength] = 0;
// Add your word
}
}
EDIT : Sorry, didn't fully understand at first. Gonna check this out.

Converting a octal String to Decimal in Objective-C?

I trying to do conversions between Binary, Octal, Decimal and Hexadecimal in Objective-C.
I had problems converting Octal to Decimal.
I have tried the following:
NSString *decString = [NSString stringWithFormat:#"%d", 077];
It works fine, returning 63 as expected, but my Octal value is a NSString. How can I tell the computer that it is a Octal;
I know there is a method called "scanHexInt:" which I used to convert Hexadecimal to decimal, but it seems there is no scanOctInt...
Any help would be appreciated!
The cleanest solution is probably:
long result = strtol(input.UTF8String, NULL, 8);
or
long long result = strtoll(input.UTF8String, NULL, 8);
Define a category on NSString (put this on top of any of your source code modules or into a new .m/.h file pair, #interface goes into .h, #implementation into .m):
#interface NSString (NSStringWithOctal)
-(int)octalIntValue;
#end
#implementation NSString (NSStringWithOctal)
-(int)octalIntValue
{
int iResult = 0, iBase = 1;
char c;
for(int i=(int)[self length]-1; i>=0; i--)
{
c = [self characterAtIndex:i];
if((c<'0')||(c>'7')) return 0;
iResult += (c - '0') * iBase;
iBase *= 8;
}
return iResult;
}
#end
Use it like that:
NSString *s = #"77";
int i = [s octalIntValue];
NSLog(#"%d", i);
The method returns an integer representing the octal value in the string. It returns 0, if the string is not an octal number. Leading zeroes are allowed, but not necessary.
Alternatively, if you want to drop down to C, you can use sscanf
int oct;
sscanf( [yourString UTF8String], "%o", &oct );

In Objective-C, how to print out N spaces? (using stringWithCharacters)

The following is tried to print out N number of spaces (or 12 in the example):
NSLog(#"hello%#world", [NSString stringWithCharacters:" " length:12]);
const unichar arrayChars[] = {' '};
NSLog(#"hello%#world", [NSString stringWithCharacters:arrayChars length:12]);
const unichar oneChar = ' ';
NSLog(#"hello%#world", [NSString stringWithCharacters:&oneChar length:12]);
But they all print out weird things such as hello ÔÅÓñüÔÅ®Óñü®ÓüÅ®ÓñüÔ®ÓüÔÅ®world... I thought a "char array" is the same as a "string" and the same as a "pointer to a character"? The API spec says it is to be a "C array of Unicode characters" (by Unicode, is it UTF8? if it is, then it should be compatible with ASCII)... How to make it work and why those 3 ways won't work?
You can use %*s to specify the width.
NSLog(#"Hello%*sWorld", 12, "");
Reference:
A field width, or precision, or both, may be indicated by an asterisk
( '*' ). In this case an argument of type int supplies the field width
or precision. Applications shall ensure that arguments specifying
field width, or precision, or both appear in that order before the
argument, if any, to be converted.
This will get you what you want:
NSLog(#"hello%#world", [#"" stringByPaddingToLength:12 withString:#" " startingAtIndex:0]);
I think the issue you have is you are misinterpreting what +(NSString *)stringWithCharacters:length: is supposed to do. It's not supposed to repeat the characters, but instead copy them from the array into a string.
So in your case you only have a single ' ' in the array, meaning the other 11 characters will be taken from whatever follows arrayChars in memory.
If you want to print out a pattern of n spaces, the easiest way to do that would be to use -(NSString *)stringByPaddingToLength:withString:startingAtIndex:, i.e creating something like this.
NSString *formatString = #"Hello%#World";
NSString *paddingString = [[NSString string] stringByPaddingToLength: n withString: #" " startingAtIndex: 0];
NSLog(formatString, paddingString);
This is probably the fastest method:
NSString *spacesWithLength(int nSpaces)
{
char UTF8Arr[nSpaces + 1];
memset(UTF8Arr, ' ', nSpaces * sizeof(*UTF8Arr));
UTF8Arr[nSpaces] = '\0';
return [NSString stringWithUTF8String:UTF8Arr];
}
The reason your current code isn't working is because +stringWithCharacters: expects an array with a length of characters of 12, while your array is only 1 character in length {' '}. So, to fix, you must create a buffer for your array (in this case, we use a char array, not a unichar, because we can easily memset a char array, but not a unichar array).
The method I provided above is probably the fastest that is possible with a dynamic length. If you are willing to use GCC extensions, and you have a fixed size array of spaces you need, you can do this:
NSString *spacesWithLength7()
{
unichar characters[] = { [0 ... 7] = ' ' };
return [NSString stringWithCharacters:characters length:7];
}
Unfortunately, that extension doesn't work with variables, so it must be a constant.
Through the magic of GCC extensions and preprocessor macros, I give you.... THE REPEATENATOR! Simply pass in a string (or a char), and it will do the rest! Buy now, costs you only $19.95, operators are standing by! (Based on the idea suggested by #JeremyL)
// step 1: determine if char is a char or string, or NSString.
// step 2: repeat that char or string
// step 3: return that as a NSString
#define repeat(inp, cnt) __rep_func__(#encode(typeof(inp)), inp, cnt)
// arg list: (int siz, int / char *input, int n)
static inline NSString *__rep_func__(char *typ, ...)
{
const char *str = NULL;
int n;
{
va_list args;
va_start(args, typ);
if (typ[0] == 'i')
str = (const char []) { va_arg(args, int), '\0' };
else if (typ[0] == '#')
str = [va_arg(args, id) UTF8String];
else
str = va_arg(args, const char *);
n = va_arg(args, int);
va_end(args);
}
int len = strlen(str);
char outbuf[(len * n) + 1];
// now copy the content
for (int i = 0; i < n; i++) {
for (int j = 0; j < len; j++) {
outbuf[(i * len) + j] = str[j];
}
}
outbuf[(len * n)] = '\0';
return [NSString stringWithUTF8String:outbuf];
}
The stringWithCharaters:length: method makes an NSString (or an instance of a subclass of NSString) using the first length characters in the C array. It does not iterate over the given array of characters until it reaches the length.
The output you are seeing is the area of memory 12 Unicode characters long starting at the location of your passed 1 Unicode character array.
This should work.
NSLog(#"hello%#world", [NSString stringWithCharacters:" " length:12]);

How do I convert a Hexa-Tri-Decimal number into an int in objective c?

The Hexa-Tri-Decimal number is 0-9 and A-Z. I know I can covert from hex with a NSScanner but not sure how to go about converting Hexa-Tri-Decimal.
For example I have a NSString with "0XPM" the int value should be 43690, "1BLC" would be 61680.
Objective C is built on top of C, and luckily enough you can use the functions there to accomplish the conversion. What you're looking for is strtol or one of it's sibling functions. If I recall correctly strtol handles up to base36 (the hexa-tri-decimal you refer to).
http://www.cplusplus.com/reference/clibrary/cstdlib/strtol/
I can only think to do this using C strings, as they offer easier access to individual characters.
This seemed like an interesting problem to solve, so I had a go at writing it:
int parseBase36Number(NSString *input)
{
const char *inputCString = [[input lowercaseString] UTF8String];
size_t inputLength = [input length];
int orderOfMagnitudeMultiplier = 1;
int result = 0;
// iterate backward through the number
for (int i = inputLength - 1; i >= 0; i--)
{
char inputChar = inputCString[i];
int charNumericValue;
if (isdigit(inputChar))
{
charNumericValue = inputChar - '0';
}
else if (islower(inputChar))
{
charNumericValue = inputChar - 'a' + 10;
}
else
{
// unhanded character, throw error
}
result += charNumericValue * orderOfMagnitudeMultiplier;
orderOfMagnitudeMultiplier *= 36;
}
return result;
}
NOTE: I've not tested this at all, so take care and let me know how it goes!

using if statements with a string of letters and user input

Helllo I am still new to programing and had a question about using if statements while using user input with the research I have conducted i can't seem to find what I am doing wrong?
Below is my posted simple multiplication calculator.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
int a ;
int b ;
int c ;
printf("\n");
printf("\n");
printf("Welcome to calculator");
printf("\n");
printf("\n");
printf("what would you like to choose for first value?");
scanf("%d", &a);
printf("\n");
printf("What would you like to input for the second value?");
scanf("%d", &b);
c = a * b;
printf("\n");
printf("\n");
printf(" Here is your product");
printf("\n");
NSLog(#"a * b =%i", c);
char userinput ;
char yesvari = "yes" ;
char novari = "no";
printf("\n");
printf("\n");
printf("Would you like to do another calculation?");
scanf("%i", &userinput);
if (userinput == yesvari) {
NSLog(#" okay cool");
}
if (userinput == novari) {
NSLog(#"okay bye");
}
return 0;
}
You are scanning the character incorrectly with %i and you need to compare them using strcmp. If you are looking for a string from the user you need to use %s and you need a character buffer large enough to hold the input.
Try this
//Make sure userinput is large enough for 3 characters and null terminator
char userinput[4];
//%3s limits the string to 3 characters
scanf("%3s", userinput);
//Lower case the characteres
for(int i = 0; i < 3; i++)
userinput[i] = tolower(userinput[i]);
//compare against a lower case constant yes
if(strcmp("yes", userinput) == 0)
{
//Logic to repeat
printf("yes!\n");
}
else
{
//Lets just assume they meant no
printf("bye!\n");
}
I think you are reading a char using the wrong format %i: scanf("%i", &userinput);
And I think it is a better to use #NSString instead of simple char (I am not even sure what will happen in ObjC if you write char a = "asd", since you are giving a char a char[] value) . In that case, since strings are pointers, you cannot use == to compare them. You could use isEqualToString or isEqualTo instead. If you are interested in the difference between the two, look at this post would help.
In C, you can't compare strings using ==, so you would have to use a function like strcmp(), like this:
if ( !strcmp(userinput, yesvari) ) {
//etc.
}
The bang (!) is used because strcmp() actually returns 0 when the two strings match. Welcome to the wonderful world of C!