Output sorted in a weird way

醉酒当歌 提交于 2020-01-15 09:46:25

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!