问题
I wrote below code but something is wrong as seen from the output. I made a pointer mistake maybe. Can you help?
Unsorted Names:
Newyork Georgia Boston
Sorted Names:
Bostork Georgia Newyon
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 3
void sort(char x[3][100]);
void swap(char **, char **);
int i,j;
char names[SIZE][100];
char *temp;
int main(void){
//get the names of the cities
puts("Enter names of cities");
for (i = 0; i < SIZE; i++)
{
fgets( names[i], 99, stdin );
}
//print entered names
puts("\nUnsorted Names:\n");
for (i = 0; i < SIZE; i++)
{
printf("%s", names[i]);
}
sort(names);
//print sorted names
puts("\nSorted Names:\n");
for (i = 0; i < SIZE; i++)
{
printf("%s", names[i]);
}
getch();
}
//sorting function
void sort(char angut[3][100]){
for (i = 0; i < SIZE-1; i++)
{
for (j = i+1; j < SIZE; j++)
{
if (strcmp( angut[i], angut[j] ) >0)
{
swap(&angut[i],&angut[j]);
}
}
}
}
//swapping function
void swap(char **first, char **second){
temp=*second;
*second=*first;
*first=temp;
}
回答1:
You're in the realm of undefined behavior. Let's compile your code with a real compiler, such as gcc. This is the (relevant) output:
a.c: In function 'sort':
a.c:50:13: warning: passing argument 1 of 'swap' from incompatible pointer type [enabled by default]
a.c:8:6: note: expected 'char **' but argument is of type 'char (*)[100]'
a.c:50:13: warning: passing argument 2 of 'swap' from incompatible pointer type [enabled by default]
a.c:8:6: note: expected 'char **' but argument is of type 'char (*)[100]'
As you can see, you are giving bad arguments to swap
. Why is that bad argument? Here's why:
angut
is a 2d array, which in reality is just a single array that is divided in rows. angut[i]
is a row of that array. Note that this is not a pointer, it's really the whole row of that array, of type char [100]
. (Side note: If you pass it to a function, it decays to a pointer). Now you are taking its address, i.e., the address of a row in that array, which is of type char (*)[100]
.
This is now a pointer that you are trying to pass to swap
. But wait, this is not a pointer to a pointer (to char), it's a pointer to a row of an array. That's were the incompatibility comes from and that's why you get wrong results.
This should be enough of an answer to your problem, but here's what's happening underneath and hence the strange results. Let's look at a char **
:
+----------+ +----------+ +----------+
| char **a | ----> | char *b | ----> | char c |
+----------+ +----------+ +----------+
by changing *a
, you are changing b
. Now let's see what you have actually sent to that function:
+----------------+ +--------------+
| char (*a)[100] | ----> | char b[100] |
+----------------+ +--------------+
So now changing *a
actually changes b
, which is your data, not pointer to your data. The swap
function doesn't know that, so it thinks a
is a char **
. So what swap
thinks *a
means is a pointer to some string, right? What you are actually giving it is the string itself.
So when you do *a1 = *a2;
, the compiler takes 4 bytes (in your architecture) from where a2
points to and writes it to 4 bytes from a1
points to.
Do you see what's happening? Basically, the first four bytes of your strings are being swapped, framed as pointers. That's why you see Bostork
and Newyon
where the first four characters are swapped.
回答2:
Try using actual string copies in your swap function, would be inefficient, but work (instead of pointer assignment).
void swap(char **first, char **second){
char temp[100];
strcpy(temp, *second);
strcpy(*second, *first);
strcpy(*first, temp);
}
来源:https://stackoverflow.com/questions/18984713/output-sorted-in-a-weird-way