简体   繁体   English

C bsearch导致分段错误

[英]C bsearch causing segmentation fault

I have the function call userInteractive(*anangramInfo) which pass in the pointer of struct anangramInfo and this struct contains the pointer "anagramPointer" to a actual anagrams. 我有函数调用userInteractive(* anangramInfo),它传入struct anangramInfo的指针,这个struct包含指向实际anagrams的指针“anagramPointer”。 So, i get the stdin from the user. 所以,我从用户那里得到了stdin。 then use that as a key of bsearch to find the pointer thoese anagram has the same anangram.sorted. 然后使用它作为bsearch的键来找到指针thoese anagram具有相同的anangram.sorted。 then move the pointer to left until the key is not matching the anagram.sorted, then move back to the right printf the anagram.word until the anagram.sorted is not match. 然后将指针移动到左边,直到键与anagram.sorted不匹配,然后向右移动打印anagram.word,直到anagram.sorted不匹配。 But it causing me the segmentation problems 但它导致我的分割问题

#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "anagrams.h"
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

#define SIZE 80

//struct
struct anagram {
    char word[SIZE];
    char sorted[SIZE];
};

struct anagramInfo {
    struct anagram *anagramPtr;
    int             numOfAnagrams;
};



/* qsort struct comparision function (product C-string field) */ 
int sortedMemberCompare( const void *ptr1, const void *ptr2 )
{ 
    struct anagram *ia = (struct anagram *)ptr1;
    struct anagram *ib = (struct anagram *)ptr2;

    return strcmp(ia->sorted, ib->sorted);
    /* strcmp functions works exactly as expected from
    comparison function */ 
}

void userInteractive( struct anagramInfo *anagramInfoPtr ){

    struct anagram a;
    char data[SIZE];
    char *pos;

    printf("Enter a word to search for anagrams [^D to exit]:\n");
    fgets(data, SIZE, stdin);

    //get ripe of the '\n'
    pos=strchr(data, '\n');
    *pos = '\0';

    strncpy(a.word,data,sizeof(data));

    //lowercase word
    int i;
    for(i=0;data[i] != '\0';i++)
      {
        data[i]=(char)tolower(data[i]);
      }

    /* sort array using qsort functions */ 
    qsort(data,strlen(data), 1, charCompare);

    strncpy(a.sorted,data,sizeof(data));

    //struct pointer to the elements
    struct anagram *ptr= (struct anagram *)bsearch(a.sorted,anagramInfoPtr-> anagramPtr ->sorted,anagramInfoPtr-> numOfAnagrams,sizeof(struct anagram),sortedMemberCompare);

    printf(ptr->word);

    while(strncmp(ptr ->sorted,a.sorted,sizeof(a.sorted))==0) {
        ptr--;
    }

    while(strncmp(ptr ->sorted,a.sorted,sizeof(a.sorted))==0) {
        printf(ptr ->word);
        printf(" ");
        ptr++;
    }

}

Your oversight is that bsearch is not searching on a contiguous array ; 你的疏忽是bsearch 没有在一个连续的数组上搜索 ; it is not even searching in the right place, since you are searching for sorted strings , but you ought to search for sorted members of anagrams : 它甚至没有在正确的位置搜索,因为您正在搜索已排序的字符串 ,但您应该搜索已排序的字谜成员

struct anagram *ptr = (struct anagram *)bsearch(&a,
            anagramInfoPtr-> anagramPtr,
            anagramInfoPtr-> numOfAnagrams,
            sizeof(struct anagram),
            sortedMemberCompare);

Then, when bsearch fails and returns NULL , you do not check that ptr is NULL and use it; 然后,当bsearch失败并返回NULL ,你不检查ptr是否为NULL并使用它; hence the segfault. 因此,段错误。 (You also do not check NULL at the Ctrl-D). (您也不要在Ctrl-D处检查NULL )。

Test 测试

This is a modified version - I added back the charCompare function and whipped up a main() with five fixed strings in order to make it work, after a fashion. 这是一个修改过的版本 - 我添加了一个charCompare函数并用一个时尚的方式将一个带有五个固定字符串的main()掀起来使其工作。

#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

#define SIZE 80

//struct
struct anagram {
    char word[SIZE];
    char sorted[SIZE];
};

struct anagramInfo {
    struct anagram *anagramPtr;
    int             numOfAnagrams;
};

/* qsort struct comparision function (product C-string field) */
int sortedMemberCompare( const void *ptr1, const void *ptr2 )
{
    struct anagram *ia = (struct anagram *)ptr1;
    struct anagram *ib = (struct anagram *)ptr2;

    return strcmp(ia->sorted, ib->sorted);
    /* strcmp functions works exactly as expected from
    comparison function */
}

int charCompare(const void *a, const void *b)
{
        const char *aa = a, *bb = b;
        if (*aa < *bb)
                return -1;
        if (*aa == *bb)
                return 0;
        return 1;
}

void userInteractive( struct anagramInfo *anagramInfoPtr ){

    struct anagram a;
    char data[SIZE];
    char *pos;

    printf("Enter a word to search for anagrams [^D to exit]:\n");
    fgets(data, SIZE, stdin);

    //get ripe of the '\n'
    pos=strchr(data, '\n'); // In Windows this might be a "\r" maybe?
    if (NULL == pos)
       exit(0);

    *pos = '\0';

    strncpy(a.word,data,sizeof(data));

    //lowercase word
    int i;
    for(i=0;data[i] != '\0';i++)
    {
        data[i]=(char)tolower(data[i]);
    }

    /* sort array using qsort functions */
    qsort(data, strlen(data), 1, charCompare);
    strncpy(a.sorted,data,sizeof(data));

    //struct pointer to the elements
    struct anagram *ptr = (struct anagram *)bsearch(&a,
                anagramInfoPtr-> anagramPtr,
                anagramInfoPtr-> numOfAnagrams,
                sizeof(struct anagram),
                sortedMemberCompare);

    // You must check that ptr is not NULL.
    if (NULL == ptr)
    {
        printf("Not found\n");
        return;
    }

    printf("Found: %s\n", ptr->word);

    /* Here there is a subtle error. If you find the FIRST item of the list,
       this code will position itself BEFORE THE BEGINNING of the list, and
       run a strncmp() against who knows what. Other segfault lurking! */

    while(ptr > anagramInfoPtr -> anagramPtr && strncmp(ptr ->sorted,a.sorted,strlen(a.sorted))==0) {
        ptr--;
    }

    // while(strncmp(ptr ->sorted,a.sorted,sizeof(a.sorted))==0) {
    //    ptr--;
    //}

    // Here too you should check you do not pass max number of anagrams,
    // if you hit the last item of the lot.
    while(strncmp(ptr ->sorted,a.sorted,sizeof(a.sorted))==0) {
        printf(ptr ->word);
        printf(" ");
        ptr++;
    }

}

int main()
{
        int i;
        struct anagramInfo *root;

        root = malloc(sizeof(struct anagramInfo));

        root->numOfAnagrams     = 5;
        root->anagramPtr        = malloc(root->numOfAnagrams * sizeof(struct anagram));

        strcpy(root->anagramPtr[0].word, "oriental");
        strcpy(root->anagramPtr[1].word, "teaching");
        strcpy(root->anagramPtr[2].word, "senator");
        strcpy(root->anagramPtr[3].word, "admirer");
        strcpy(root->anagramPtr[4].word, "rescued");

        for (i = 0; i < root->numOfAnagrams; i++)
        {
            int j;
            for (j = 0; root->anagramPtr[i].word[j]; j++)
               root->anagramPtr[i].word[j] = tolower(root->anagramPtr[i].word[j]);
            strcpy(root->anagramPtr[i].sorted, root->anagramPtr[i].word);
            qsort(root->anagramPtr[i].sorted, strlen(root->anagramPtr[i].sorted), 1, charCompare);
        }
        qsort(root-> anagramPtr, root-> numOfAnagrams, sizeof(struct anagram), sortedMemberCompare);
        for (;;)
            userInteractive(root);
    }

Run

$ gcc -W -Wall -o anagram anagram.c
$ ./anagram
Enter a word to search for anagrams [^D to exit]:
treason
Found: senator

Enter a word to search for anagrams [^D to exit]:
cheating
Found: teaching

Enter a word to search for anagrams [^D to exit]:
relation
Found: oriental

Enter a word to search for anagrams [^D to exit]:

$

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM