I am working on a project for my CS1 class and I have run into something I have never thought of before. I know at all arrays in C are essentially pointer to the first element of an array, and a string is really just a character array. However, for my assignment we have to read in a file, and part of the file is the following:
Brad Tim Rick (more man names separated by spaces) Lucy Angela Tina (more women names separated by spaces)
This is a short example, but what I have to do is extract the names and store them into two separate arrays, one for men and one for females.
I have never worked with something like this, so of course I am confused. This is what I am trying to do, and of course its not working… oh yeah, and I’m trying to store them in dynamic allocation. The only spec says that the names will never exceed 19 characters (should I say twenty to allow the ‘/0’ at the end of the string to still be there no matter what?) How can I tell the compiler, “hey I want an array of strings, and each string can hold 19 characters + 1 for the “string trailer ‘/0’ “? And then how do I access those through pointers?
char **mens_names, **womens_names;
mens_names = malloc(number_of_couples * sizeof(char[19]));
womens_names = malloc(number_of_couples * sizeof(char[19]));
if(mens_names == NULL){
printf("Malloc failed! Memory could not be allocated to variable mens_names.");
return -1;
}
int i;
for(i = 0; i < number_of_couples; i++){
fscanf(input_file, "%s", &mens_names[i]);
}
if(womens_names == NULL){
printf("Malloc failed! Memory could not be allocated to variable womens_names.");
return -1;
}
for(i = 0; i < number_of_couples; i++){
fscanf(input_file, "%s", &womens_names[i]);
}
for(i = 0; i < number_of_couples; i++){
printf("Man: %s ", mens_names[i]);
printf("Woman: %s\n", womens_names[i]);
}
Not quite. Arrays and pointers are two different things entirely. Except when it is the operand of the
sizeof,_Alignof, or unary&operator, or is a string literal being used to initialize an array in a declaration, an expression of type “N-element array ofT” will be converted to an expression of type “pointer toT” and its value will be the address of the first element in the array.Given the declaration
the object that
adesignates is always and forever a 10-element array ofint; however, the expressionamay be treated as a pointer to the first element.If you know your strings will never be more than 19 characters long (20 elements including the terminator), but don’t know the number of strings ahead of time, you can do something like this:
In this case, we’ve declared
mens_namesandwomens_namesas pointers to 20-element arrays ofchar(the parentheses matter). Thus,sizeof *mens_namesis equivalent tosizeof (char [20]).You would access each individual character as you would with a regular 2-d array:
mens_names[i]implicitly dereferences themens_namespointer (remember that the expressiona[i]is interpreted as*(a + i)).This method has a couple of advantages over KBart’s method. First, all the memory is allocated contiguously as a single chunk, which may matter if caching becomes an issue. Secondly, you only need one
mallocand onefreefor each array. Of course, this assumes that the maximum size of each name array is a) fixed and b) known at compile time.If you won’t know the size of the name until runtime, and you’re using a C99 compiler or a C2011 compiler that supports variable-length arrays, you can do something like this:
If you won’t know the size of the name until runtime, and you’re using a compiler that doesn’t support VLAs, then you’ll need to use KBart’s method.
If you wanted to get really fancy, you could use a single 3-dimensional array instead of two 2-dimensional arrays: