C:检查数组是否包含相等的连续元素
C: Check if array includes consecutive elements that are equal
昨天考了C,最后一题没弄明白:
我们得到了两种数组的两个数组:包含相等的连续元素的数组(例如:{"stack"、"heap"、"heap"})和其中的数组没有连续的元素相等(例如:{1,2,3,4,5,6,7,8,9})。
然后我们被要求找到一个函数,如果给定的数组是否包含双精度数,则返回 1 或 0。所以这个函数必须同时处理整数数组和 char * 数组。
这就是我今天想到的(但它总是给出错误的答案,然后在比较字符串时崩溃或出现分段错误)
编辑:正确的代码(感谢@BLUEPIXY!)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int contains_dup(void *array, size_t size, size_t sizeoftype, int (*cmp)(const void*, const void*)){
//array != NULL, size != 0
char *obj = array;
size_t i;
for(i = 0; i < size-1; ++i){
if(cmp(obj + sizeoftype * i, obj + sizeoftype * (i+1)))
return 1;
}
return 0;
}
int eqi(const void *a, const void *b){
int x = *(const int *)a;
int y = *(const int *)b;
return x == y;
}
int eqs(const void *a, const void *b){
return strcmp(a, b) == 0;
}
#define TEST(name, cmp)\
do{\
int test;\
puts(#name ":");\
test = contains_dup(name, sizeof(name)/sizeof(*name), sizeof(*name), cmp);\
test ? puts("doubles? Yes\n") : puts("doubles? No\n");\
}while(0)\
/**/
int main(void){
int ints_yes[] = {0,1,2,2,2,3,4,4,5};
int ints_no[] = {0,1,2,3,4,5,6,7,8};
char *strings_yes[]={"heap","stack","stack","overflow"};
char *strings_no[] ={"heap","stack","heap","stack","overflow"};
puts("test:");
TEST(ints_yes, eqi);
TEST(ints_no, eqi);
TEST(strings_yes, eqs);
TEST(strings_no, eqs);
return 0;
}
错误的旧代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int array_contains_doubles(void ** array, int size, int sizeoftype){
int i;
char **out =(char**) malloc(size * sizeof(char*));
for(i=0;i<size;i++){ //trying to convert the array of ints to an
out[i] = array+i*sizeoftype; //array of char * eg: {1,2} ->{"1","2"}
// *out[i] +='a';
printf("%c\n",*out[i]);
}
out[i]= NULL;
while(*(out+1)!=NULL){
if(strcmp(*out,*(out++))==0){ //<- where i get the segmentation error
return 1;
}
}
return 0;
}
int main(void){
int i;
int ints_yes[] = {0,1,2,2,2,3,4,4,5};
int ints_no[]={0,1,2,3,4,5,6,7,8};
char * strings_yes[]={"heap","stack","stack","overflow"};
char * strings_no[]={"heap","stack","heap","stack","overflow"};
int test = array_contains_doubles((void **) ints_no,
sizeof(ints_no)/sizeof(ints_no[0]), sizeof(int));
(test) ? (printf("doubles? Yes")) : (printf("doubles? No"));
}
对于任何拼写错误,我深表歉意,英语不是我的母语。
你的老师可能想要的是让你实现一个 "functor" 类似于传递给 bsearch
的函数指针(研究这个函数)。类似这样的事情:
typedef int comp_func_t (const void*, const void*);
bool equal (const void* obj1, const void* obj2, comp_func_t* comp)
{
return comp(obj1, obj2)==0;
}
您从您的应用程序中调用 equal
,并使用指向要比较的对象的指针,无论它们是什么类型的对象。函数指针指定应该如何比较这种类型的对象。然后为每种类型实现比较函数:
int comp_int (const void* obj1, const void* obj2)
{
int a = *(const int*)obj1;
int b = *(const int*)obj2;
if(a < b)
{
return -1;
}
else if(a > b)
{
return 1;
}
else // a == b
{
return 0;
}
}
int comp_str (const void* obj1, const void* obj2)
{
...
}
典型用途可能是:
int x;
int y;
...
if(equal(&x, &y, comp_int))
{
...
}
现在这只比较两个对象,所以你必须通过 1) 对数组排序和 2) 对排序数组中的每两个相邻项调用它来为数组扩展它,以查明是否有等于。
以上是在 C 中实现特定类型行为的旧 "de facto standard" 方法。在较新版本的语言中,通过 _Generic
关键字可以使用更优雅的方法,但这会可能不会在初学者级别上解决 class.
昨天考了C,最后一题没弄明白:
我们得到了两种数组的两个数组:包含相等的连续元素的数组(例如:{"stack"、"heap"、"heap"})和其中的数组没有连续的元素相等(例如:{1,2,3,4,5,6,7,8,9})。
然后我们被要求找到一个函数,如果给定的数组是否包含双精度数,则返回 1 或 0。所以这个函数必须同时处理整数数组和 char * 数组。
这就是我今天想到的(但它总是给出错误的答案,然后在比较字符串时崩溃或出现分段错误)
编辑:正确的代码(感谢@BLUEPIXY!)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int contains_dup(void *array, size_t size, size_t sizeoftype, int (*cmp)(const void*, const void*)){
//array != NULL, size != 0
char *obj = array;
size_t i;
for(i = 0; i < size-1; ++i){
if(cmp(obj + sizeoftype * i, obj + sizeoftype * (i+1)))
return 1;
}
return 0;
}
int eqi(const void *a, const void *b){
int x = *(const int *)a;
int y = *(const int *)b;
return x == y;
}
int eqs(const void *a, const void *b){
return strcmp(a, b) == 0;
}
#define TEST(name, cmp)\
do{\
int test;\
puts(#name ":");\
test = contains_dup(name, sizeof(name)/sizeof(*name), sizeof(*name), cmp);\
test ? puts("doubles? Yes\n") : puts("doubles? No\n");\
}while(0)\
/**/
int main(void){
int ints_yes[] = {0,1,2,2,2,3,4,4,5};
int ints_no[] = {0,1,2,3,4,5,6,7,8};
char *strings_yes[]={"heap","stack","stack","overflow"};
char *strings_no[] ={"heap","stack","heap","stack","overflow"};
puts("test:");
TEST(ints_yes, eqi);
TEST(ints_no, eqi);
TEST(strings_yes, eqs);
TEST(strings_no, eqs);
return 0;
}
错误的旧代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int array_contains_doubles(void ** array, int size, int sizeoftype){
int i;
char **out =(char**) malloc(size * sizeof(char*));
for(i=0;i<size;i++){ //trying to convert the array of ints to an
out[i] = array+i*sizeoftype; //array of char * eg: {1,2} ->{"1","2"}
// *out[i] +='a';
printf("%c\n",*out[i]);
}
out[i]= NULL;
while(*(out+1)!=NULL){
if(strcmp(*out,*(out++))==0){ //<- where i get the segmentation error
return 1;
}
}
return 0;
}
int main(void){
int i;
int ints_yes[] = {0,1,2,2,2,3,4,4,5};
int ints_no[]={0,1,2,3,4,5,6,7,8};
char * strings_yes[]={"heap","stack","stack","overflow"};
char * strings_no[]={"heap","stack","heap","stack","overflow"};
int test = array_contains_doubles((void **) ints_no,
sizeof(ints_no)/sizeof(ints_no[0]), sizeof(int));
(test) ? (printf("doubles? Yes")) : (printf("doubles? No"));
}
对于任何拼写错误,我深表歉意,英语不是我的母语。
你的老师可能想要的是让你实现一个 "functor" 类似于传递给 bsearch
的函数指针(研究这个函数)。类似这样的事情:
typedef int comp_func_t (const void*, const void*);
bool equal (const void* obj1, const void* obj2, comp_func_t* comp)
{
return comp(obj1, obj2)==0;
}
您从您的应用程序中调用 equal
,并使用指向要比较的对象的指针,无论它们是什么类型的对象。函数指针指定应该如何比较这种类型的对象。然后为每种类型实现比较函数:
int comp_int (const void* obj1, const void* obj2)
{
int a = *(const int*)obj1;
int b = *(const int*)obj2;
if(a < b)
{
return -1;
}
else if(a > b)
{
return 1;
}
else // a == b
{
return 0;
}
}
int comp_str (const void* obj1, const void* obj2)
{
...
}
典型用途可能是:
int x;
int y;
...
if(equal(&x, &y, comp_int))
{
...
}
现在这只比较两个对象,所以你必须通过 1) 对数组排序和 2) 对排序数组中的每两个相邻项调用它来为数组扩展它,以查明是否有等于。
以上是在 C 中实现特定类型行为的旧 "de facto standard" 方法。在较新版本的语言中,通过 _Generic
关键字可以使用更优雅的方法,但这会可能不会在初学者级别上解决 class.