从我以前的问题:
Segmentation Fault in Bubble Sort
我解决了问题,我得到了以下代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void bubble_sort (void* base,
size_t num,
size_t width,
int (*compar)(const void*,const void*)){
int i,j,k;
unsigned char *ptr = base;
unsigned char tmp[256];
if(num < 2 || width == 0)
return;
for(i = num-1; i >= 0; i--)
{
for(j = 1; j <= i; j++)
{
k = compar((void*)(ptr + width * (j-1)), (void*)(ptr + width * j));
if(k > 0)
{
memcpy(tmp, ptr + width*(j-1), width);
memcpy(ptr + width*(j-1), ptr + width*j, width);
memcpy(ptr + width * j, tmp, width);
}
}
}
}
int compare_int(const void *a, const void *b)
{
int *c = (int *)a;
int *d = (int *)b;
return *c - *d;
}
int compare_string(const void *a, const void *b)
{
const char *c = (char *)a;
const char *d = (char *)b;
return strcmp(c, d);
}
现在这完全适用于:
int a[] = {1, 3, 4, 52, 2, 3};
char a[5][20] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"};
但我想用char *
数组实现它,如:
char *a[] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"}
尝试了一下并遇到了分段故障 所以需要一些帮助。
答案 0 :(得分:3)
您将变量'a'声明为char指针(字符串)。但你拥有的是一系列字符串。
因此'a'应该是这样的
char *a[] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"};
此外,您应该为变量赋予更有意义的名称。在这种情况下,字符串或单词会更清晰。
答案 1 :(得分:0)
首先注意声明:
char *a = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"};
不正确它应该是:
char *a[] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"};
这是一个char指针数组。 a[i]
中的每个索引都指向一个字符串文字。
问题在于您的比较功能。前两个数组是值数组,而a[]
是一个指针数组。
阅读difference between char* str[]
and char str[][]
and how both stores in memory?以了解char* a[]
的内存组织与char[][]
(二维继续分配的内存组织)的不同之处。
compare_()
函数中传递a[i]
的地址会发生什么情况(但不会将a[i]
传递给自己)。当a[i]
是值地址时,它可以找到,例如对于int[]
和char[][]
,而在char*[]
的情况下,您没有传递值的地址而是传递值的地址。我认为你的主要困惑是在2D字符数组char[][]
和文字字符串数组char*[]
之间传递。
首先要了解你传递给比较函数的是什么,假设你有以下数组,那么你传递的是内容x
,y
,z
的地址(即&amp; a [ i])但不是x
,y
,z
(即[i])。
a
+--------+
343 | |
| a[0]=x |
| |
+--------+
| |
347 | a[1]=y |
| |
+--------+
| |
351 | a[2]=z |
| |
| |
+--------+
* you are passing &a[i]
现在查看char a[5][20]
的内存组织以防,因为&a[i]
和a[i]
的内存组织值相同。检查以下代码及其输出:
#include<stdio.h>
int main(){
char a[5][20] = { "jhsa", "asndb", "drtfe", "nhurh", "bvhr"};
int i = 0;
for(i = 0; i < 5; i++)
printf(
"&a[i] = %p, a[i] = %p, *a[i] = %c, string a[i] = \"%s\"\n",
(void*)&a[i], // you are passingg this &a[i]
(void*)a[i], // compare &a[i] and a[i] address value
*a[i],
a[i]
);
return 0;
}
<强>输出强>:
$ gcc x.c -Wall -pedantic -o x
$ ./x
&a[i] = 0x7fff1dfb28b0, a[i] = 0x7fff1dfb28b0, *a[i] = j, string a[i] = "jhsa"
&a[i] = 0x7fff1dfb28c4, a[i] = 0x7fff1dfb28c4, *a[i] = a, string a[i] = "asndb"
&a[i] = 0x7fff1dfb28d8, a[i] = 0x7fff1dfb28d8, *a[i] = d, string a[i] = "drtfe"
&a[i] = 0x7fff1dfb28ec, a[i] = 0x7fff1dfb28ec, *a[i] = n, string a[i] = "nhurh"
&a[i] = 0x7fff1dfb2900, a[i] = 0x7fff1dfb2900, *a[i] = b, string a[i] = "bvhr"
虽然&a[i]
和a[i]
不相同但价值相同。要理解这些差异,请阅读Difference between &str
and str
, when str
is declared as char str[10]
?。
但是&a[i]
和a[i]
的值在char*[]
的情况下不相同检查以下代码:y.c(类似于上面的x.c)及其输出:
#include<stdio.h>
int main(){
char *a[] = {"jhsa", "asndb", "drtfe", "nhurh", "bvhr"};
int i = 0;
for(i = 0; i < 5; i++)
printf("&a[i] = %p, a[i] = %p, *a[i] = %c, string a[i] = \"%s\"\n",
(void*)&a[i],
(void*)a[i],
*a[i],
a[i]);
return 0;
}
输出
$ gcc y.c -Wall -pedantic -o y
$ ./y
&a[i] = 0x7fffa4674730, a[i] = 0x400690, *a[i] = j, string a[i] = "jhsa"
&a[i] = 0x7fffa4674738, a[i] = 0x400695, *a[i] = a, string a[i] = "asndb"
&a[i] = 0x7fffa4674740, a[i] = 0x40069b, *a[i] = d, string a[i] = "drtfe"
&a[i] = 0x7fffa4674748, a[i] = 0x4006a1, *a[i] = n, string a[i] = "nhurh"
&a[i] = 0x7fffa4674750, a[i] = 0x4006a7, *a[i] = b, string a[i] = "bvhr"
现在,&a[i]
和a[i]
的通知值不同(实际上,偏移地址值显示不同的段并且a [i]获取堆栈中的地址空间,而a[i]
获取地址空间字符串 literal 存储在哪里,但这是另一回事。)
因此,在字符串比较函数中:int compare_string()
语句return strcmp(c, d);
不适用于char*[]
,它应该类似于return strcmp(*c, *d);
(虽然它适用于{{ 1}} char[][]
和&[i]
的值相同的第一种情况我使用a[i]
编译代码而-Wall
它没有发出任何警告,所以我认为使用没问题它作为字符串地址 - 但我也不确定。因此,您需要一个单独版本的compare_string_ for -pedantic
,您可以在其中调用char*[]
。但现在问题是函数参数是strcmp(*c, *d);
并且取消引用cont是未定义的行为。为了纠正您的代码,我从每个地方删除了cont void*
,并为const
添加了一个新功能int compare_string_v2( void *a, void *b)
,如下所示:
char* a[]
只需将您的代码编译为:int compare_string_v2( void *a, void *b)
{
char **c = a;
char **d = b;
return strcmp(*c, *d);
}
它应该可以正常工作。在这里,您可以查看@ working instance of code
答案 2 :(得分:0)
您可以使用此代码,越简单越好! 首先在main()中编写Isless函数,有点像这样:
static int IsLess(void* num1, void* num2)
{
return (*(int*)num1 > *(int*)num2) ? TRUE : FALSE;
}
然后使用此代码。
static void Swap(void* ptr1, void* ptr2, size_t _sizeof)
{
void* temp = malloc(_sizeof);
memcpy(temp,ptr2, _sizeof);
memcpy(ptr2,ptr1, _sizeof);
memcpy(ptr1,temp, _sizeof);
free(temp);
}
static void BubbleUp(int _end, void* _arr[], size_t _sizeofitem, fp _IsLess)
{
size_t j;
for(j = 0; j < _end; ++j)
{
if(_IsLess((char*)_arr + j*_sizeofitem, (char*)_arr + (j+1)*_sizeofitem))
{
Swap((char*)_arr + j*_sizeofitem, (char*)_arr + (j+1)*_sizeofitem, _sizeofitem);
}
}
}
void SortGen(void* _arr, size_t _sizeofitem, size_t _numOfItems, fp _IsLess)
{
int i;
if(_arr == NULL)
{
return;
}
for(i = (int)_numOfItems -1; i >= 0; i--)
{
BubbleUp(i, _arr, _sizeofitem, _IsLess);
}
}