问题
Sorry, I'm not even sure how to ask, since I'm a complete newbie at C, pointers and stuff like that. There's a function that accepts an argument: char **arg
. If I write that argument like so:
char *cargs[] = {"blah", NULL};
and pass it to the function:
function(cargs);
it works. but ... I have an NSArray
of NSStrings
and I need to make this array out of values from NSArray
. I figured it should be a matter of creating a C array of the same element count as NSArray
and copy the strings, converting them with cStringUsingEncoding
. But I honestly have no idea how to do this, since I get confused with all those pointers and such. Any help would be appreciated.
回答1:
Well, the rough steps can be:
use count method of NSArray to know how many NSStrings are there in the NSArray.
use malloc to allocate memory for cargs, something like this
char **cargs = (char **) malloc(sizeof(char *) * count);
by your example, you may need to one more room for NULL which will be at the end of cargs.
use a loop and objectAtIndex: of NSArray to get out the NSStrings, like NSString *nsstring = [array objectAtIndex:index];
use method cStringUsingEncoding: to get the c-string out, better make a copy
put these c-string pointers in cargs
pass cargs to your function, clean and free things needed to.
It's a lot of work. 'Cause the mix of c and obj-c stuff. And a lot of manual malloc and free , messy stuff. Can't you avoid it?
--add sample code--
I'm not quite sure what your real intent is. Hope this will help.
void func(char **arg)
{
int i;
for(i = 0; arg[i] != NULL; i++) {
printf("%d=%s\n", i, arg[i]);
}
}
int main(int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *s1 = [NSString stringWithString:@"first"];
NSString *s2 = [NSString stringWithString:@"second"];
NSString *s3 = [NSString stringWithString:@"third"];
NSArray *array = [NSArray arrayWithObjects: s1, s2, s3, nil];
//by now, we have an NSArray of three NSStrings
int count = [array count];
char **cargs = (char **) malloc(sizeof(char *) * (count + 1));
//cargs is a pointer to 4 pointers to char
int i;
for(i = 0; i < count; i++) {
NSString *s = [array objectAtIndex:i];//get a NSString
const char *cstr = [s cStringUsingEncoding:NSUTF8StringEncoding];//get cstring
int len = strlen(cstr);//get its length
char *cstr_copy = (char *) malloc(sizeof(char) * (len + 1));//allocate memory, + 1 for ending '\0'
strcpy(cstr_copy, cstr);//make a copy
cargs[i] = cstr_copy;//put the point in cargs
}
cargs[i] = NULL;
func(cargs);//call the function to do something
for(i = 0; i < count; i++) {
free(cargs[i]);
}
free(cargs);
[pool drain];
return 0;
}
回答2:
@yehnan your answer is GREAT - especially because I thought that const ** cStyle[arrays]
were NOT able to be created dynamically... (I really wish there was somewhere with just basic information about C
pointers and variables and crap... I find the most basic "C primitives" to be far more bewildering than anything else...) Here's your nice little example "bundled up" into a function... "for the children..."
char ** cArrayFromNSArray ( NSArray* array ){
int i, count = array.count;
char **cargs = (char**) malloc(sizeof(char*) * (count + 1));
for(i = 0; i < count; i++) { //cargs is a pointer to 4 pointers to char
NSString *s = array[i]; //get a NSString
const char *cstr = s.UTF8String; //get cstring
int len = strlen(cstr); //get its length
char *cstr_copy = (char*) malloc(sizeof(char) * (len + 1));//allocate memory, + 1 for ending '\0'
strcpy(cstr_copy, cstr); //make a copy
cargs[i] = cstr_copy; //put the point in cargs
}
cargs[i] = NULL;
return cargs;
}
来源:https://stackoverflow.com/questions/3091251/objective-c-nsarray-to-c-array