Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中对不同类型结构的数组使用搜索函数_C_Arrays_Search - Fatal编程技术网

在C中对不同类型结构的数组使用搜索函数

在C中对不同类型结构的数组使用搜索函数,c,arrays,search,C,Arrays,Search,我目前正在从事初学者编程课程项目,在该项目中,我必须在结构数组中执行多个搜索,例如,我有以下两种不同的结构: typedef struct{ char name[SIZE]; int number, year, isbn; }magazine; typedef struct{ char title[SIZE]; char author[SIZE]; int isbn, year; }book; 正如您所看到的,书籍和杂志都将isbn作为一个公共元素,使用isbn进行的查询

我目前正在从事初学者编程课程项目,在该项目中,我必须在结构数组中执行多个搜索,例如,我有以下两种不同的结构:

typedef struct{
  char name[SIZE];
  int number, year, isbn;
}magazine;

typedef struct{
  char title[SIZE];
  char author[SIZE];
  int isbn, year;
}book;
正如您所看到的,书籍和杂志都将isbn作为一个公共元素,使用isbn进行的查询可以针对两种数据结构进行,我的问题是,我如何制作(或使用glibc)通用功能,而不必这样做:

book *search_book(book *array, int key){
   //We search a book by its isbn and return the pointer.
}

magazine *search_mag(magazine *array, int key){
  //We search a magazine by its isbn and return the pointer
}

而不是能够在一个函数中执行两个数据结构的搜索?

您可以考虑使用这样的结构并编写一个函数来检查类型,然后调用一个知道如何搜索书籍和杂志的专门函数。
typedef enum { INVALID, BOOK, MAGAZINE } itemType;

typedef struct {
  union {
  book b;
  magazine m;
  } u;

  itemType type;
} Item;
您可以使用项目初始化数组,还可以为每个项目设置类型。最后一项可以是类型无效的项,以表示数组的结束,也可以将大小传递给搜索函数

该函数大致如下所示:

Item *search(Item *array, int key){
    Item * result = NULL;
    ...
    switch (array[i].type)
    {
       case BOOK: < do book search here using array[i].u.b >
                  if (found) result = array[i];
       break;
       case MAGAZINE: < do magazine search here using array[i].u.m>
                  if (found) result = array[i];
       break;
       default: // handle invalid case here
       break;
    }
    ...
    return result;
}
Item*搜索(Item*数组,int键){
项目*结果=空;
...
开关(数组[i]。类型)
{
案例书:<使用数组[i]在此处进行图书搜索.u.b>
如果(找到)结果=数组[i];
打破
案例杂志:<使用数组[i]在此处搜索杂志。u.m>
如果(找到)结果=数组[i];
打破
默认值://在此处处理无效的大小写
打破
}
...
返回结果;
}

<代码> > P>这是C++模板适合的地方。然而,在纯C中,这是一个地狱: 首先,数组需要一个公共类型,它可能是
void*
,但这也会删除任何类型信息。
因此,搜索函数还需要知道一个元素的大小以及一个元素在
isbn
成员中的偏移量


这就是指针算法发挥作用的地方,作为初学者,你肯定不想做什么。如果你想这样,看看 SeZOOS,也许是C++代码中常用的Me宏的<代码>偏移,但是我真的认为这是相当先进的。

< P>其他答案是很好的,但是仅仅因为你的代码在C中,并不意味着它不能在C++中。p>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#define SIZE 256

struct Base {
    int isbn;
    char name[SIZE];
    int year;
};

struct Book {
    struct Base base; // Inheritance, C style
    int number;
};

struct Magazine {
    struct Base base;  // Inheritance, C style
    char author[SIZE];
};

/* 
You're going to need to cast the arguments and return value.
Also provide the size of the element.
However: the code is generic, casting always works (if `Base` is the first element) , and there is no need for IF or SWITCH statements.
*/
struct Base* search(struct Base* array,int length,size_t size,int key){
    for (int i=0;i<length;++i){
        if (array->isbn == key){
            return array;
        }
        // array[i] won't work, because the size of Base is not the size we need to jump in.
        array = (struct Base*)((uint8_t*)array + size);
    }
    return NULL;
}

int main(int argc,char** argv){

    // Initialize some data
    struct Book books[] = {
        { {123,"Moby Dick",1851},1 },
        { {124,"Oliver Twist",1837},2 }
    };
    struct Magazine magazines[] = {
        {{ 125,"Wired",2020 }, "Some author"},
        {{ 126,"Byte",1990 }, "Some author"}
    };

    // Search for a book and a magazine
    struct Book* book = (struct Book*)search((struct Base*)books,2,sizeof(struct Book),124);
    struct Magazine* magazine = (struct Magazine*)search((struct Base*)magazines,2,sizeof(struct Magazine),126);

    if (book){
        printf("Found book %s, number: %d\n",book->base.name,book->number);
    }
    if (magazine){
        printf("Found magazine %s, author: %s\n",magazine->base.name,magazine->author);
    }
}
#包括
#包括
#包括
#定义大小256
结构基{
国际标准书号;
字符名称[大小];
国际年;
};
结构书{
struct Base;//继承,C样式
整数;
};
结构库{
struct Base;//继承,C样式
字符作者[大小];
};
/* 
您需要强制转换参数并返回值。
还提供元素的大小。
但是:代码是通用的,强制转换总是有效的(如果'Base'是第一个元素),并且不需要if或SWITCH语句。
*/
结构基*搜索(结构基*数组,整数长度,大小,整数键){
for(int i=0;iisbn=key){
返回数组;
}
//数组[i]不起作用,因为基的大小不是我们需要跳入的大小。
数组=(结构基*)((uint8_t*)数组+大小);
}
返回NULL;
}
int main(int argc,字符**argv){
//初始化一些数据
结构图书[]={
{{123,“白鲸”,1851},1},
{{124,《雾都孤儿》,1837},2}
};
结构杂志[]={
{{125,“连线”,2020},“一些作者”},
{{126,“Byte”,1990},“某个作者”}
};
//搜索一本书和一本杂志
struct Book*Book=(struct Book*)搜索((struct Base*)Book,2,sizeof(struct Book),124);
结构库*库=(结构库*)搜索((结构库*)库,2,sizeof(结构库),126);
如果(书){
printf(“找到的书本%s,编号:%d\n”,书本->基础。名称,书本->编号);
}
if(杂志){
printf(“找到杂志%s,作者:%s\n”,杂志->基本名称,杂志->作者);
}
}

我喜欢认为我熟悉指针算法,但看起来我必须以简单的方式完成这项工作,最后这只是一个优化练习,以某种方式完成这项工作不会幸运地影响我的成绩。是的,这更好+1这很好,我将看看是否可以实现它,因为我还必须从文件加载结构数组,并且我希望一次只拥有一个活动数组(使用malloc分配内存,当我不再需要数组时使用free()。