Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.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,这是一个地址: struct Adress { char name[31], lastname[31], email[48]; }; 目标是在主函数中有一个地址簿,用户应该能够键入一个字符串,程序将列出地址簿中所有姓名或姓氏包含给定字符串的人。 例如,如果通讯簿包含“john”“doe”、“jane”“doey”和“george”“johnson”,并且用户键入“doe”,则输出为: 1. john doe johndoe@email.com 2. jane doey janedo

这是一个地址:

struct Adress {
    char name[31], lastname[31], email[48];
};
目标是在主函数中有一个地址簿,用户应该能够键入一个字符串,程序将列出地址簿中所有姓名或姓氏包含给定字符串的人。 例如,如果通讯簿包含“john”“doe”、“jane”“doey”和“george”“johnson”,并且用户键入“doe”,则输出为:

 1. john doe johndoe@email.com
 2. jane doey janedoey@email.com
这部分主函数应该使用一个函数

int search(struct Adress array[], int size_of_the_addressbook, char* string_to_search)
它返回第一个找到的地址的索引,如果没有找到地址,则返回-1

以下是我的尝试:

在我的主函数的代码段中(这里不需要发布输入内容):

以下是搜索功能:

int search(struct Adress array[], int size_of_the_addressbook, char* string_to_search)
{
    int j, index;
    struct Adress *i;
    i = array;

    while (strstr((*i).name, string_to_search) == 0 && strstr((*i).lastname, string_to_search) == 0)
    {
        index = ((i - array)/(sizeof (struct Adress)));
        if (index == size_of_the_addressbook)   return -1;
        ++i;
    }
    index = ((i - array)/(sizeof (struct Adresa)));
    return index;
}

然而,当地址簿中有多个成员时,该程序几乎在任何情况下都会陷入无限循环。我怀疑在while循环中,搜索不是从以前找到的成员开始的,而是每次都从开始开始,因此每次都会继续查找相同的、最先找到的成员。

您有一些问题要提

  • 在主循环中调用两次
    search()
    ,这是绝对不必要的,应该调用一次并存储它的返回值

  • 您的
    成员
    指针永远不会指向第一个匹配项之后,因此始终会找到第一个匹配项, 导致无限循环

  • 增加
    成员
    指针,但仍将
    元素数
    传递给搜索函数。当您增加
    成员
    指针时,其结果位置左侧至右侧的元素数量将减少与您增加
    成员
    相同的数量

  • 这个表达式没有给出您认为的值

    ((i - array)/(sizeof (struct Adress)));
    
    因为您正在计算两个指针
    i
    array
    之间的距离,然后将其除以
    sizeof(struct Address)
    ,即
    110
    ,并且如另一个答案所述,该值会自动缩放,因此

    ((i - array)/(sizeof (struct Adress))); -> i - array;
    
    要了解我的意思,您可以尝试打印此值

    printf("\t%d\n", ((void*)member - (void*)adressbook));
    printf("\t%d\n", ((void*)member - (void*)adressbook) / sizeof(*member));
    printf("\t%d\n", member - adressbook);
    
    注意:如果操作系统为64位,请将格式说明符更改为
    “%ld”

  • 这是将执行您需要的操作的代码

    int search(struct Adress **array, int size_of_the_addressbook, char* string_to_search)
    {
        int            index;
        struct Adress *pointer;
    
        if ((size_of_the_addressbook == 0) || (array == NULL) || (*array == NULL))
            return -1;
    
        pointer = *array;
        index   = 0;
        while (strstr(pointer->name, string_to_search) == 0 && 
                   strstr(pointer->lastname, string_to_search) == 0)
        {
            /* check that we are not at the end of the array. */
            if (++index == size_of_the_addressbook)
                return -1;
            /* not found yet, increment both arrays */
            (*array)++;
    
            pointer = *array;
        }
    
        return index;
    }
    
    main()中

    在这种方法中,在
    search()
    函数中增加
    member
    指针,以指向找到的元素,并添加一个计数器以反映已提前多少

    search()
    函数返回后,成员应再次增加1以指向下一个元素,并且
    number\u of_elements
    应减少查找到的元素的搜索函数中的高级元素数+1


    另外,保留一个变量,在每次迭代时更新该变量,该变量将为您提供数组中元素的实际
    索引。

    您的搜索实际上从未返回-1,您对该搜索的调用也因此没有退出条件。此外,您应该将下一次搜索的每个起始点调整为超出上一个发现点的一个插槽

    我几乎可以肯定这就是你想要做的。我没有对此进行过测试(没有数据可以测试,也没有关于调用此功能的任何信息),但我希望这一点是显而易见的:

    int search(const struct Adress array[],
               int size_of_the_addressbook,
               const char* string_to_search)
    {
        const struct Adress *end = array + size_of_the_addressbook;
        const struct Adress *i = array;
    
        for (; i != end; ++i)
        {
            if (strstr(i->name, string_to_search) != NULL ||
                strstr(i->lastname, string_to_search) != NULL)
                break;
        }
    
        return i == end ? -1 : (int)(i - array);
    }
    
    void do_search(const struct Adress *array,
                   int number_of_elements,
                   const char *string_to_search)
    {
        int i = search(array, number_of_elements, string_to_search), base=0;
        if (i == -1)
        {
            printf("No person found.\n");
            return;
        }
    
        while (i != -1)
        {
            base += i;
            printf("%d. %s %s - %s\n", base,
                   array[base].name,
                   array[base].lastname,
                   array[base].email);
    
            base += 1;
    
            // note adjustment of starting point using pointer arithmetic.
            i = search(array + base,
                       number_of_elements - base,
                       string_to_search);
        }
    }
    

    希望能有帮助。祝你好运。

    为什么要调用搜索两次??一旦保存了结果,测试-1,如果没有,使用结果作为偏移量,而不是再次使用相同的参数调用相同的函数?而且您不需要在
    搜索
    中计算
    索引
    。指针数学可以帮你做到这一点<代码>索引=(i-数组)应该足以获得正确的索引。嗯,没有这个除法,我如何获得索引?我知道事情可以优化一点,但首先我需要让它工作,并找出它为什么会进入无限循环。这是一段奇怪的代码。为什么不使用整数索引
    i
    ,它从
    0
    迭代到数组的长度,并引用
    array[i].name
    等?对于无限循环,在传递给函数之前,如何计算地址簿的
    size\u?同样,指针算法。它在这个代码中做了两次,都是错误的。你所做的事情不需要任何规模的部门。因此,函数中的循环仍然可以从
    0
    迭代
    int i
    number\u of_elements-1
    引用
    array[i]
    。它会更干净,你的循环至少会正确终止,留下你来解决其他问题。如果我将它与地址簿-1的大小相比较,它仍然卡在一个无限循环中。@BaneBojanić你怎么知道它是一个无限循环?你使用调试器了吗?假设我有两个成员,他们的姓氏相同,名字不同。如果我搜索姓氏(或其一部分),程序将打印出无限行的I。第一个成员的名字第一个成员的姓氏,i从1到无穷大。@BaneBojanić为什么要调用搜索两次?非常感谢您的帮助。:)此行:*end=数组+地址簿的大小;数组+地址簿的大小可能超出地址簿数组?编辑:没关系,我在第二个函数中看到了调整。不幸的是,你的函数打印出包含第一个找到的成员的无限多行,就像我的函数一样…@BaneBojanić是的,我刚刚意识到这一点<代码>基准
    未正确调整。现在应该可以了。这将教会我发布未经测试的代码。非常感谢。我想我应该发布整个代码,但这很难,因为我必须将所有变量翻译成英语,使其可读。。。
    int index;
    int foundIndex;
    
    index = 1;
    while ((foundIndex = search(&member, number_of_elements, string_to_seach)) != -1)
    {
        printf("%d. %s %s - %s\n", index, member->name, member->lastname, member->email);
    
        index              += 1 + foundIndex;
        number_of_elements -= 1 + foundIndex;
    
        ++member;
    }
    
    int search(const struct Adress array[],
               int size_of_the_addressbook,
               const char* string_to_search)
    {
        const struct Adress *end = array + size_of_the_addressbook;
        const struct Adress *i = array;
    
        for (; i != end; ++i)
        {
            if (strstr(i->name, string_to_search) != NULL ||
                strstr(i->lastname, string_to_search) != NULL)
                break;
        }
    
        return i == end ? -1 : (int)(i - array);
    }
    
    void do_search(const struct Adress *array,
                   int number_of_elements,
                   const char *string_to_search)
    {
        int i = search(array, number_of_elements, string_to_search), base=0;
        if (i == -1)
        {
            printf("No person found.\n");
            return;
        }
    
        while (i != -1)
        {
            base += i;
            printf("%d. %s %s - %s\n", base,
                   array[base].name,
                   array[base].lastname,
                   array[base].email);
    
            base += 1;
    
            // note adjustment of starting point using pointer arithmetic.
            i = search(array + base,
                       number_of_elements - base,
                       string_to_search);
        }
    }