2014-01-29 73 views
-3

我必须做一个字典模拟器的二进制搜索,现在这是我的功能,我不知道为什么它会崩溃,如果有人可以帮助我我会很高兴..! ^^strcmp与结构2d数组

这是我的结构:

typedef struct 
{ 
    char *world; 
    char *meaning; 
} par; 

,这里是不起作用的代码。 我要为我的英语和意大利变数的名称感到抱歉,但我是意大利人... ^^ 如果你需要一些建议,请告诉我..! p.s. 我试着评论,因为我可以,再次抱歉..!

#include <stdio.h> 
#include <stdlib.h> 

#define MAX 40 
typedef struct 
{ 
    char *Parola; 
    char *Significato; 
} par; 

int Ricerca(par Dizionario[MAX][21], char Richiesta[20], int Min, int Max, int Iniziale); 

int main() 
{ 
    par Dizionario[MAX][21] = 
    { 
     { 
      /////////////////////load my 2d array//////////////////// 
      //seconda riga 
      {"Accendere", "Trasmettere energia elettrica a un apparecchio o dispositivo per farlo funzionare"}, 
      {"Bellezza","Qualita' di ciò che è bello"}, 
      {"Comune","Che e' di tutti, o che appartiene a piu' persone o cose"}, 
      {NULL, NULL}, 
      {"Elenco", "Nota, registro ordinato"}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {"Impetuoso","Che si muove con impeto [anche in senso figurato]; che si lascia vincere dall'impeto"}, 
      {"Lancio","Atto, effetto del lanciare o del lanciarsi"}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {"Produrre","Presentare, allegare, citare"}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {"Saccone","Grosso sacco, imbottito generalmente di paglia, che si mette sotto il materasso o si usa talvolta in sua vece"}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {"Verticale","Perpendicolare a un piano orizzontale; che sta ritto con la parte superiore in alto e l'inferiore in basso"}, 
      {NULL, NULL} 
     } 
    }; 


    int i, j, flag, Iniziale = 0; 
    par temp; 
    char Richiesta[20], Rtemp[20]; 

    /////////////////////bubble sort///////////////////// 
    for(j=0; j<21;j++) 
    { 
     for(i=0; i<MAX && Dizionario[i+1][j].Parola != NULL; i++) 
     { 
      if(strcmp(Dizionario[i][j].Parola, Dizionario[i+1][j].Parola) == 1) 
      { 
       temp=Dizionario[i][j]; 
       Dizionario[i][j] = Dizionario[i+1][j]; 
       Dizionario[i+1][j] = temp; 
      } 
     } 
    } 
//i'm gonna ask to the user what word he want 
    printf("Che parola vuole cercare?"); 
    gets (Richiesta); 
    strcpy(Rtemp, Richiesta); 
    printf("%s", Rtemp); 
    Rtemp[0] = toupper(Rtemp[0]); 
    printf("\n%s", Rtemp); 
//I'm checking what's the first char, if it's a, i'm gonna assign 0 so it's 
//it's gonna to the 'n' column and shifting there 
    switch(Rtemp[0]) 
    { 
     case 'A': Iniziale = 0; 
        break; 
     case 'B': Iniziale = 1; 
        break; 
     case 'C': Iniziale = 2; 
        break; 
     case 'D': Iniziale = 3; 
        break; 
     case 'E': Iniziale = 4; 
        break; 
     case 'F': Iniziale = 5; 
        break; 
     case 'G': Iniziale = 6; 
        break; 
     case 'H': Iniziale = 7; 
        break; 
     case 'I': Iniziale = 8; 
        break; 
     case 'L': Iniziale = 9; 
        break; 
     case 'M': Iniziale = 10; 
        break; 
     case 'N': Iniziale = 11; 
        break; 
     case 'O': Iniziale = 12; 
        break; 
     case 'P': Iniziale = 13; 
        break; 
     case 'Q': Iniziale = 14; 
        break; 
     case 'R': Iniziale = 15; 
        break; 
     case 'S': Iniziale = 16; 
        break; 
     case 'T': Iniziale = 17; 
        break; 
     case 'U': Iniziale = 18; 
        break; 
     case 'V': Iniziale = 19; 
        break; 
     case 'Z': Iniziale = 20; 
        break; 
    } 
    flag = Search(Dizionario, Rtemp, 0, MAX, Iniziale); 
    printf("%d", flag); 

    system("PAUSE");  
    return 0; 
} 
int Search(par Dictionary[MAX][21], char Request[20], int Min, int Max, int init) 
{ 
    int Median; 
    Median = (Min+Max)/2; 

    if(strcmp(Request, Dizionario[Median][Init].world) == 0) 
    return Median; 
    else if(Max <= Min) // elemento non trovato 
    { 
     return -1; 
    } 

    else if(strcmp(Request, Dictionary[Median][Init].world)>= 1) 
    { 
     return Search(Dictionary, Request, Median+1, Max, Init); 
     printf("ok"); 
    }else{ 
     return Search(Dictionary, Request, Min, Median-1, Init); 
     printf("ok"); 
    } 
} 

@ john3136 如果我要去这样做(Iniziale = RTEMP [0] - 'A'),我可以eaven知道我得走了。 我解释得更好一些,rwason为什么开关是如果我有'A',我知道所有的开始与'A'的世界是在posizion [x] [0] B相同,但[ x] [1]等等......我不知道我是否明白我的意思,让我知道.. ^^ ps 我有问题还做<,或者==>比0至少比1 ..

@Uli科勒 他会崩溃的功能,因为我理解调试,问题是出在了“的strcmp() “呼叫 特地在这里

if(strcmp(Request, Dizionario[Median][Init].world) == 0) 

这里

else if(strcmp(Request, Dictionary[Median][Init].world)>= 1) 

@cnicutar 增加了对空控制,它的崩溃一样 我已经编辑这样

if(strcmp(Richiesta, Dizionario[Mediano][Iniziale].Parola) == 0 && Dizionario[Mediano][Iniziale].Parola != NULL) // elemento trovato 
if(strcmp(Richiesta, Dizionario[Mediano][Iniziale].Parola)> 0 && Dizionario[Mediano][Iniziale].Parola != NULL) 

这些都是我的2个控制现在...

@BLUEPIXY 我不能使用bsearch,我都用我自己......

做二进制搜索
+1

请提供关于为何未能如预期 –

+1

'STRCMP运行更多详细资料()'返回<0, 0 or > 0,所以你的== 1检查是非常具体的 - 我怀疑这是不是你真正想要的东西。另外,用'Iniziale = Rtemp [0] - 'A'替换​​该开关;最后但并非最不重要的请不要用大写字母开头变量名! – John3136

+0

一个问题是,您从不检查以确保'Dictionary [Median] [Init]'不是'NULL'。 – cnicutar

回答

0

经过大量的代码研究之后,我发现你试图把你的字典组织成二维数组,所以你可以从正确的第一个字母开始。不幸的是,这使得你的代码要复杂得多 - 和致命错误忙里偷闲

例如,在该行

if(strcmp(Request, Dictionary[Median][init].word) == 0) 

您正在访问的元素,可能永远不会被初始化字典元素的.word - 事实上,由于每个字母的字母只有一个输入,并且您编码为MAX,这是确定的。所以你发现自己有一个空指针 - 不是一个很好的字符串来比较。你必须知道每行数据是多长时间。为了解决这个问题,你的二分查找需要从搜索字典的末尾开始。这导致以下(工作)代码:

include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define MAX 40 
typedef struct 
{ 
    char *word; 
    char *meaning; 
} par; 

int Ricerca(par Dizionario[MAX][21], char Richiesta[20], int Min, int Max, int Iniziale, int depth); 

int main() 
{ 
    par Dizionario[MAX][21] = 
    { 
     { 
      /////////////////////load my 2d array//////////////////// 
      //seconda riga 
      {"Accendere", "Trasmettere energia elettrica a un apparecchio o dispositivo per farlo funzionare"}, 
      {"Bellezza","Qualita' di ciò che è bello"}, 
      {"Comune","Che e' di tutti, o che appartiene a piu' persone o cose"}, 
      {NULL, NULL}, 
      {"Elenco", "Nota, registro ordinato"}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {"Impetuoso","Che si muove con impeto [anche in senso figurato]; che si lascia vincere dall'impeto"}, 
      {"Lancio","Atto, effetto del lanciare o del lanciarsi"}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {"Produrre","Presentare, allegare, citare"}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {"Saccone","Grosso sacco, imbottito generalmente di paglia, che si mette sotto il materasso o si usa talvolta in sua vece"}, 
      {NULL, NULL}, 
      {NULL, NULL}, 
      {"Verticale","Perpendicolare a un piano orizzontale; che sta ritto con la parte superiore in alto e l'inferiore in basso"}, 
      {NULL, NULL} 
     } 
    }; 


    int i, j, flag, Iniziale = 0; 
    par temp; 
    char Richiesta[20], Rtemp[20]; 

    /////////////////////bubble sort///////////////////// 
    printf("unsorted array:\n"); 
    for(j=0; j<21;j++) 
    { 
     if (Dizionario[0][j].word != NULL) printf("%d: %s\n", j, Dizionario[0][j].word); 
     for(i=0; i<MAX && Dizionario[i+1][j].word != NULL; i++) 
     { 
      if(strcmp(Dizionario[i][j].word, Dizionario[i+1][j].word) < 0) 
      { 
       temp=Dizionario[i][j]; 
       Dizionario[i][j] = Dizionario[i+1][j]; 
       Dizionario[i+1][j] = temp; 
      } 
     } 
    } 

//i'm gonna ask to the user what word he want 
    printf("Che parola vuole cercare?\n"); 
    fgets (Richiesta, sizeof(Richiesta)-1, stdin); 
    strncpy(Rtemp, Richiesta, strlen(Richiesta)-1); // do not copy newline 
    Rtemp[0] = toupper(Rtemp[0]); 
    printf("\nLooking for '%s'\n", Rtemp); 
//I'm checking what's the first char, if it's a, i'm gonna assign 0 so it's 
//it's gonna to the 'n' column and shifting there 
// changed from lengthy switch() to more compact array: 
    char firstLetter[] = {0,1,2,3,4,5,6,7,8,-1,-1,9,10,11,12,13,14,15,16,17,18,19,-1,-1,-1,20}; 
    Iniziale = firstLetter[Rtemp[0] - 'A']; 
#if 0 
    switch(Rtemp[0]) 
    { 
     case 'A': Iniziale = 0; 
        break; 
     case 'B': Iniziale = 1; 
        break; 
     case 'C': Iniziale = 2; 
        break; 
     case 'D': Iniziale = 3; 
        break; 
     case 'E': Iniziale = 4; 
        break; 
     case 'F': Iniziale = 5; 
        break; 
     case 'G': Iniziale = 6; 
        break; 
     case 'H': Iniziale = 7; 
        break; 
     case 'I': Iniziale = 8; 
        break; 
     case 'L': Iniziale = 9; 
        break; 
     case 'M': Iniziale = 10; 
        break; 
     case 'N': Iniziale = 11; 
        break; 
     case 'O': Iniziale = 12; 
        break; 
     case 'P': Iniziale = 13; 
        break; 
     case 'Q': Iniziale = 14; 
        break; 
     case 'R': Iniziale = 15; 
        break; 
     case 'S': Iniziale = 16; 
        break; 
     case 'T': Iniziale = 17; 
        break; 
     case 'U': Iniziale = 18; 
        break; 
     case 'V': Iniziale = 19; 
        break; 
     case 'Z': Iniziale = 20; 
        break; 
    } 
#endif 
    if (Iniziale == -1) { 
     printf("no word with that first letter!\n"); 
     return 0; 
    } 
    printf("Iniziale = %d\n", Iniziale); 
    flag = Search(Dizionario, Rtemp, 0, MAX, Iniziale, 0); 
    printf("result of search was flag = %d\n", flag); 

    //system("PAUSE"); 
    return 0; 
} 
int Search(par Dictionary[MAX][21], char Request[20], int Min, int Max, int init, int depth) 
{ 
    int Median; 
    Median = (Min+Max)/2; 
    //printf("calling Search with min =%d, max = %d, median = %d, depth = %d\n", Min, Max, Median, depth); 
    depth++; 
    if (depth > 10) return 0; // trap an infinite loop - with MAX of 40, binary search should take only 6 iterations 
    par *temp; 

    if(Max <= Min) // elemento non trovato 
    { 
     printf("element not found!\n"); 
     return -1; 
    } 

    if(Dictionary[Median][init].word==NULL) { 
     // out of bounds in the dictionary 
     return Search(Dictionary, Request, Min, Median, init, depth); 
    } 
    if(strcmp(Dictionary[Median][init].word, Request) == 0) { 
     printf("Word was found!\nDefinition = %s\n", Dictionary[Median][init].meaning); 
     return 1; 
    } 

    if(strcmp(Request, Dictionary[Median][init].word) > 0) 
    { 
     return Search(Dictionary, Request, Median+1, Max, init, depth); 
    } else { 
     return Search(Dictionary, Request, Min, Median-1, init, depth); 
    } 
} 

我做了不少变化!为了帮助你弄清楚我做了什么,这里是你原来的代码和编译结束的代码之间的diff。注 - 我用一对#if 0 ... #endif陈述包围了您的巨大switch声明;并用数组替换它们。这实际上并没有被打破(除了缺少default声明外),但仍然非常难看。我相信你知道如何阅读diff - >表示“添加了一些东西”,而<表示“删除了某些东西”。

我稍微改变了Search的签名,其中包括depth因素。事实证明,你的分段错误是通过64k递归调用Search函数来调用的......在调试过程中,我添加了这个参数来查看早期迭代中发生了什么。

看看现在是否有意义。

2a3 
> #include <string.h> 
7,8c8,9 
<  char *Parola; 
<  char *Significato; 
--- 
>  char *word; 
>  char *meaning; 
11c12 
< int Ricerca(par Dizionario[MAX][21], char Richiesta[20], int Min, int Max, int Iniziale); 
--- 
> int Ricerca(par Dizionario[MAX][21], char Richiesta[20], int Min, int Max, int Iniziale, int depth); 
49a51 
>  printf("unsorted array:\n"); 
52c54,55 
<   for(i=0; i<MAX && Dizionario[i+1][j].Parola != NULL; i++) 
--- 
>  if (Dizionario[0][j].word != NULL) printf("%d: %s\n", j, Dizionario[0][j].word); 
>  for(i=0; i<MAX && Dizionario[i+1][j].word != NULL; i++) 
54c57 
<   if(strcmp(Dizionario[i][j].Parola, Dizionario[i+1][j].Parola) == 1) 
--- 
>   if(strcmp(Dizionario[i][j].word, Dizionario[i+1][j].word) < 0) 
61a65 
> 
63,66c67,69 
<  printf("Che parola vuole cercare?"); 
<  gets (Richiesta); 
<  strcpy(Rtemp, Richiesta); 
<  printf("%s", Rtemp); 
--- 
>  printf("Che parola vuole cercare?\n"); 
>  fgets (Richiesta, sizeof(Richiesta)-1, stdin); 
>  strncpy(Rtemp, Richiesta, strlen(Richiesta)-1); // do not copy newline 
68c71 
<  printf("\n%s", Rtemp); 
--- 
>  printf("\nLooking for '%s'\n", Rtemp); 
70a74,77 
> // changed from lengthy switch() to more compact array: 
>  char firstLetter[] = {0,1,2,3,4,5,6,7,8,-1,-1,9,10,11,12,13,14,15,16,17,18,19,-1,-1,-1,20}; 
>  Iniziale = firstLetter[Rtemp[0] - 'A']; 
> #if 0 
116,119c123,132 
<  flag = Search(Dizionario, Rtemp, 0, MAX, Iniziale); 
<  printf("%d", flag); 
< 
<  system("PAUSE");  
--- 
> #endif 
>  if (Iniziale == -1) { 
>  printf("no word with that first letter!\n"); 
>  return 0; 
>  } 
>  printf("Iniziale = %d\n", Iniziale); 
>  flag = Search(Dizionario, Rtemp, 0, MAX, Iniziale, 0); 
>  printf("result of search was flag = %d\n", flag); 
>  
>  //system("PAUSE");  
122c135 
< int Search(par Dictionary[MAX][21], char Request[20], int Min, int Max, int init) 
--- 
> int Search(par Dictionary[MAX][21], char Request[20], int Min, int Max, int init, int depth) 
125a139,142 
>  //printf("calling Search with min =%d, max = %d, median = %d, depth = %d\n", Min, Max, Median, depth); 
>  depth++; 
>  if (depth > 10) return 0; // trap an infinite loop - with MAX of 40, binary search should take only 6 iterations 
>  par *temp; 
127,129c144 
<  if(strcmp(Request, Dizionario[Median][Init].world) == 0) 
<  return Median; 
<  else if(Max <= Min) // elemento non trovato 
--- 
>  if(Max <= Min) // elemento non trovato 
130a146 
>   printf("element not found!\n"); 
134c150,159 
<  else if(strcmp(Request, Dictionary[Median][Init].world)>= 1) 
--- 
>  if(Dictionary[Median][init].word==NULL) { 
>  // out of bounds in the dictionary 
>  return Search(Dictionary, Request, Min, Median, init, depth); 
>  } 
>  if(strcmp(Dictionary[Median][init].word, Request) == 0) { 
>  printf("Word was found!\nDefinition = %s\n", Dictionary[Median][init].meaning); 
>  return 1; 
>  } 
> 
>  if(strcmp(Request, Dictionary[Median][init].word) > 0) 
136,140c161,163 
<   return Search(Dictionary, Request, Median+1, Max, Init); 
<   printf("ok"); 
<  }else{ 
<   return Search(Dictionary, Request, Min, Median-1, Init); 
<   printf("ok"); 
--- 
>   return Search(Dictionary, Request, Median+1, Max, init, depth); 
>  } else { 
>   return Search(Dictionary, Request, Min, Median-1, init, depth); 
1
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 

typedef struct { 
    char *Parola; 
    char *Significato; 
} par; 

par *Ricerca(par *Dizionario, char Richiesta[20], int num); 

int main(){ 
    par Dizionario[] = { 
     {"Accendere", "Trasmettere energia elettrica a un apparecchio o dispositivo per farlo funzionare"}, 
     {"Bellezza","Qualita' di cio che e bello"}, 
     {"Comune","Che e' di tutti, o che appartiene a piu' persone o cose"}, 
     {"Elenco", "Nota, registro ordinato"}, 
     {"Impetuoso","Che si muove con impeto [anche in senso figurato]; che si lascia vincere dall'impeto"}, 
     {"Lancio","Atto, effetto del lanciare o del lanciarsi"}, 
     {"Produrre","Presentare, allegare, citare"}, 
     {"Saccone","Grosso sacco, imbottito generalmente di paglia, che si mette sotto il materasso o si usa talvolta in sua vece"}, 
     {"Verticale","Perpendicolare a un piano orizzontale; che sta ritto con la parte superiore in alto e l'inferiore in basso"}, 
    }; 

    char Richiesta[20], Rtemp[20]; 
    int numOfData = sizeof(Dizionario)/sizeof(*Dizionario); 

    par *temp; 

    printf("Che parola vuole cercare? :"); 
    gets (Richiesta); 
    strcpy(Rtemp, Richiesta); 
    printf("%s\n", Rtemp); 
    Rtemp[0] = toupper(Rtemp[0]); 
    //printf("%s\n", Rtemp); 
    temp = Ricerca(Dizionario, Rtemp, numOfData); 
    if(temp != NULL) 
     printf("%s\n", temp->Significato); 
    else, 
     printf("not found\n"); 

    system("PAUSE");  
    return 0; 
} 

int cmp(const void *a, const void *b){ 
    const par *x = a; 
    const par *y = b; 
    return strcmp(x->Parola, y->Parola); 
} 

par *Ricerca(par *Dizionario, char Richiesta[20], int num){ 
    par key = { Richiesta, NULL }; 
    //replaced by the binary search function that your implements 
    return bsearch(&key, Dizionario, num, sizeof(key), cmp); 
} 
+0

所有这些努力 - 请指出永远不要使用'gets',而是使用'fgets'。 'gets()'是非常不安全的,我的编译器会在运行时输出一个警告!...哦 - 并且OP确实说他不能使用'bsearch'。仍然给予你投入这项努力的投票权。 – Floris

+0

我当然不应该使用它。 – BLUEPIXY

+0

没有理由不使用已经存在的函数。我可以看到这种方法(处理一个不包含NULL的范围)在此是正确的,因为暂时存在原始代码的各种问题。 – BLUEPIXY