I have an assignment I’ve been working on for a few hours now, and I can’t seem to get it quite right. The assignment is to take a random number of names (from stdin), sort them, and then output them in alphabetical order. I can’t find any sites online that handle this kind of sorting specifically, and have had no luck trying to implement qsort() into my code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int stringcmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return strcmp(*ia, *ib);
}
void main(int argc, char *argv[])
{
char *input[] = {" "};
char temp[20][20];
int i = 0;
int num = 0;
int place = 0;
int stringlen = sizeof(temp) / sizeof(char);
printf("How many names would you like to enter? ");
scanf("%d", &num);
while (place < num)
{
printf("Please input a name(first only): ");
scanf("%s", input[place]);
printf("The name you entered is: ");
printf("%s\n", input[place]);
place++;
}
//qsort(temp, stringlen, sizeof(char *), stringcmp); <-- just an idea I was messing with
qsort(input, stringlen, sizeof(char *), stringcmp);
printf("Names:\n");
for(i=0; i<place; i++)
printf("%s\n", input[i]);
system("PAUSE");
return(EXIT_SUCCESS);
}
The main problem is, when I go to output my code, I cannot use the char *input variable because of how its declared. The temp[] will display, but will not be sorted by qsort because it is not declared as a pointer. Any ideas?
You can’t declare your input array like that. Since you know how many the user requires, you can dynamically allocate the array:
Likewise, when you read your strings in, they need somewhere to go. Simply passing an uninitialized pointer to
scanfis not okay. I suggest you define the maximum length of a name and have a temporary buffer for reading it:[Note this does not prevent the user from overflowing the ‘name’ buffer. I used
scanffor illustrative purposes only]You seem to be passing the wrong array length to
qsort. Try this:When you are finished, you need to release memory for all the names and the array.
Yep, in the case where I used it, I am telling C that to get a single character, I have to dereference a pointer twice. When you index a pointer, it’s dereferencing. So I allocated an array by requesting a block of memory containing
num * sizeof(char*)bytes. Because I assigned that pointer to achar**, the compiler knows that I am pointing to a chunk of memory that containschar*values.If I ask for
input[0](this is the same as*input) it should look at the very start of that memory and pull out enough bytes to form achar*. When I ask forinput[1], it skips past those bytes and pulls out the next bunch of bytes that form achar*. Etc… Likewise, when I index achar*, I am pulling out single characters.In your
stringcmpfunction, you have the following situation. You passed avoid*pointer toqsortso it doesn’t actually know the size of the data values stored in your array. That’s why you have to pass both the array length AND the size of a single element. Soqsortjust blindly rips through this arbitrary-length array of arbitrary-sized values and fires off memory addresses that ought to contain your data for comparison. Becauseqsortdoesn’t know anything else about your array elements except where they are located, it just usesvoid*.But YOU know that those pointers are going to be the memory addresses of two of your array elements, and that your array elements are
char*. So you need the address of achar*(hence you cast the pointers tochar**). Now you need to dereference these pointers when you callstrcmp()because that function requires achar*(ie a value that points directly to the memory containing your string characters). That is why you use the*instrcmp(*ia, *ib).