why cannot I use struct like this? - objective-c

why cannot I use struct like this?
typedef struct { unsigned char FirstName; unsigned char LastName; unsigned int age; } User;
User UserNick = {Nick, Watson, 24};
NSLog(#"Your paint job is (R: %NSString, G: %NSString, B: %u)",
UserNick.FirstName, UserNick.LastName, UserNick.age);
I mean I have used a struct like this for sure:
typedef struct {unsigned char red; unsigned char green; unsigned char blue; } Color;
Color carColor = {255, 65,0};
NSLog(#"Your paint job is (R: %hhu, G: %hhu, B: %hhu)",
carColor.red, carColor.green, carColor.blue);

If you want to use C strings you need the following code:
typedef struct { unsigned char *FirstName; unsigned char *LastName; unsigned int age; } User;
User UserNick = {"Nick", "Watson", 24};
NSLog(#"Your paint job is (R: %s, G: %s, B: %u)",
UserNick.FirstName, UserNick.LastName, UserNick.age);
C strings are char *. C string literals need to be in quotes. %s is the format specifier for C strings.
One other suggestion - start field names (and variables names) with lowercase letters.
And since you are working with Objective-C, you would probably end up being better off if you make User a real class instead of a struct. Then you can use properties and proper memory management. The names could be NSString instead of C strings. This makes it easy to store the objects in collections and do other useful things that are hard with a plain old struct.

In your definition, FirstName is an unsigned char which means it is a variable that can hold only one char as its value. However, Nick is a string, namely an array of chars.
One could do
typedef struct {
unsigned char * FirstName;
unsigned char * LastName;
unsigned int age;
} User;
User Nick = {"Nick", "Watson", 24};

Related

OpenCL Kernel: unsigned char -> signed char (aka cl_char)

The following kernel accepts a char* array (alphabet):
kernel void generate_cl(global char* alphabet,
global int* rand_buffer,
int len,
int max,
global bool *stop)
However, by compiling it becomes:
extern void (^generate_cl_kernel)(const cl_ndrange *ndrange, cl_char* alphabet, cl_int* rand_buffer, cl_int len, cl_int max, bool* stop);
Obviously alphabet is now a cl_char (aka signed char).
My Problem: I need a unsigned/const char array. (see code below)
My Question: How do I cast unsigned char to signed char (if possible)? Or is there any other approach?
const char* alphabet_ = ... //char array, received from [NSString UTF8String]
generate_cl_kernel(&range,alphabet,..); //throws semantic issue [!]

scanf function in objective-c, float and double

I just a beginner in objective-C.
Below is a calculator of temperature.
I find a solution on the internet. The problem is the scanf.
At first, I set the f as a double, but program has problem.
So I change it to float.
May I ask what's going on on scanf function in objective-c?
Only can set character, int and float?
Another question is, what if I want to set a double, to use in another function which only accept double variable?
Thanks
import
int main(int argc, const char * argv[])
{
#autoreleasepool {
double c;
float f;
NSLog(#"Please enter F temp");
scanf("%f", &f);
c = (f-32) / 1.8;
//c = 1.3E-3;
// insert code here...
NSLog(#"The C temp is %.3f", c);
}
return 0;
}
Use %f for float and %lf for double. However be sure to check the return value from scanf() (or sscanf()) to ensure it parsed the correct number of values:
double d;
printf("Entry thy number mortal: ");
if (scanf("%lf", &d)) == 1) {
printf("Oh that's nice, you entered %f\n", d);
}

Comparing char with enum

I have an enum defined this way:
typedef enum : unsigned char {
START_DELIMITER = 0xAA,
END_DELIMITER = 0xBB,
} Delimiter;
When I compare the delimiter value with with char byte from const char*, like so:
// data is NSData;
const char *bytes = [data bytes];
if (bytes[0] == START_DELIMITER) { }
The above test is false even though bytes[0] contains 0xAA.
If I define START_DELIMITER as const char, the comparison is true. Why does the test against the enum fails even though the enum is already defined as unsigned char?
The char is signed, and the enum is unsigned. Perhaps the compiler sign-extends before making the comparison?

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 );

Struct array in struct [Objective-c]

Let say I have these:
typedef id Title;
typedef struct{
Title title;
int pages;
}Book;
So far, the code is okay. But the problem is here:
typedef struct{
int shelfNumber;
Book book; //How can I make this an array of Book?
}Shelf;
Like what I have stated in the comment in the code, I want to make Book as array so that it can hold a number of books. Is that even possible? If it is, how can I do it?
typedef struct{
int shelfNumber;
Book book[10]; // Fixed number of book: 10
}Shelf;
or
typedef struct{
int shelfNumber;
Book *book; // Variable number of book
}Shelf;
in the latter case you'll have to use malloc to allocate the array.
Note that you could use a flexible array member to achieve this effect:
typedef struct {
int shelfNumber;
size_t nbooks;
Book book[];
} Shelf;
This is an elegant use case because you have the simplicity of use of a static array but if you need to allocate a Shelf object of size sz, you only have to do one malloc:
Shelf *mkShelf(int num, size_t sz) {
Shelf *s = malloc(sizeof(Shelf) + sz * sizeof(Book));
if (!s) return NULL;
*s = (Shelf){ num, sz };
return s;
}
Compound literals and flexible array members that I used above are C99 features, so if you program with VC++ it might not be available.