简体   繁体   English

此TRIE算法代码在CS50 IDE编译器上运行,但是在Windows的TDM-GCC中进入无限循环

[英]This TRIE algorithm code runs on CS50 IDE compiler but goes into an infinite loop in TDM-GCC on Windows

The wrote this code for searching a word in a dictionary using TRIE data structure. 编写此代码是为了使用TRIE数据结构在字典中搜索单词。 This code runs perfectly on my CS50 IDE compiler using both make(Clang) and GCC and always gives the right answer but when I run the same code on my GCC compiler(TDM-GCC), it goes into an infinite loop. 这段代码可以在我的CS50 IDE编译器上同时使用make(Clang)和GCC完美运行,并且始终能给出正确的答案,但是当我在GCC编译器(TDM-GCC)上运行相同的代码时,它将陷入无限循环。 it started using a lot of RAM (512 MB until I forcefully closed it). 它开始使用大量RAM(直到我强行关闭它之前,才占用512 MB)。 The code that I ran was exactly the same in both the cases. 在两种情况下,我运行的代码完全相同。 Also in both the cases the code compiled perfectly. 同样在两种情况下,代码都能完美编译。

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

struct trieblock123;
typedef struct trieblock123 trieblock;
typedef trieblock *node;
struct trieblock123 
{
    char alphabet;
    char reply[5];
    node pnt;
};


typedef struct 
{
    node first;
    int count;
}head;

void load(FILE* dict, head* header);
void init(node pointer);

int main(void)
{
    FILE* dict = fopen("large", "r");

    head* header = malloc(sizeof(head));
    (*header).count = 0;
    (*header).first = NULL;


    node curtrie = NULL;
    node temptrie = NULL;
    node temptrie1 = NULL;
    char temp;
    temp = fgetc(dict);
    int counter = 0;
    temptrie = (node)(malloc(26 * sizeof(trieblock)));
    int i;
    for(i = 0; i < 26; i++)
    {
        (temptrie[i]).alphabet = (char)(((int)('a')) + i);
        (temptrie[i]).pnt = NULL;
    }
    if(counter == 0)
    {
        (*header).first = temptrie;
    }
    while(((int)(temp) <= (int)('z') && (int)(temp) >= (int)('a')) || temp == '\n')
    {
        if(((int)(temp) > (int)('z') || (int)(temp) < (int)('a')) && temp != '\n')
            break;
        curtrie = temptrie;

        while(temp != '\n')
        {
            char temp1;
            temp1 = fgetc(dict);
            if((curtrie[(int)(temp) - (int)('a')]).pnt == NULL) 
            {
                if(temp1 != '\n')
                {
                    temptrie1 = (node)(malloc(26 * sizeof(trieblock)));
                    for(i = 0; i < 26; i++)
                    {
                        (temptrie1[i]).alphabet = (char)(((int)('a')) + i);
                        (temptrie1[i]).pnt = NULL;
                    }

                    (curtrie[(int)(temp) - (int)('a')]).pnt = temptrie1;
                    curtrie = temptrie1;
                }
                else
                {
                    strcpy((curtrie[(int)(temp) - (int)('a')]).reply, "yes");
                }
            }
            else if((curtrie[(int)(temp) - (int)('a')]).pnt != NULL)
            {
                curtrie = (curtrie[(int)(temp) - (int)('a')]).pnt;
            }
            fseek(dict, -1 * sizeof(char), SEEK_CUR);   
            temp = fgetc(dict);
        }


        if(temp == '\n')
        {
            temp = fgetc(dict);
        }

        counter++;
    }
    (*header).count = counter;

    char tocheck[100];
    scanf("%s", tocheck);

    i = 0;
    node start = NULL;
    start = temptrie;

    for(i = 0; i < strlen(tocheck); i++)
    {
        char cha = tocheck[i];
        if(i != strlen(tocheck) - 1)
        {
            if((start[(int)(cha) - (int)('a')]).pnt == NULL)
            {
                printf("mis-spelled\n");
                break;
            }
            else
            {
                start = (start[(int)(cha) - (int)('a')]).pnt;
            }
        }
        else
        {
            if(strcmp(((start[(int)(cha) - (int)('a')]).reply), "yes") == 0)
            {
                printf("correctly spelled\n");
                break;
            }
            else
            {
                printf("mis-spelled\n");
                break;
            }
        }
    }
    return 0;
}

This may not be the kind of an answer you would expect, however. 但是,这可能不是您期望的答案。

Your code is hard to debug and maintain because of this problems: 由于以下问题,您的代码难以调试和维护:

  1. repetitions - this is error prone, use functions instead 重复-这容易出错,请改用函数
  2. too many unnecessary casts - check C type system and how types are implicitly converted to each other 过多的不必要的类型转换-检查C类型系统以及类型如何隐式转换为彼此
  3. weird typedefs - do not redefine pointer types unless you are using some kind of suffix or prefix to indicate that the respective typedef is indeed a pointer 奇怪的typedefs-不要重新定义指针类型,除非您使用某种后缀或前缀来表示相应的typedef确实是指针
  4. too many parentheses, you do not need the most of them (especially the kind of stuff (*s).a = something use -> instead) 括号太多,则不需要最多的括号(尤其是那种东西(* s).a =使用->代替)

Some other issues are: 其他一些问题是:

  1. Whenever you malloc do not just expect to have zeros in there (in fact do not expect to get any memory in any time at all), your original code may segfault in case reply comes initialized with some garbage. 每当您不仅仅希望malloc那里有零(实际上根本不希望在任何时候获得任何内存)时,您的原始代码可能会出现段错误,以防应答被某些垃圾初始化。
  2. strings in C are zero terminated, hence doing strlen involves iteration over the entire string, unless you are modifying it just cache the result once in a variable and use it. C中的字符串以零结尾,因此执行strlen涉及整个字符串的迭代,除非您要对其进行修改,否则只需将结果缓存在变量中一次并使用它即可。
  3. Track your conditional statements there is no need to doublecheck the negative conditions. 跟踪条件语句,无需仔细检查否定条件。
  4. Working with IO try to minimize calls whenever appropriate. 在适当的情况下,使用IO尝试尽量减少调用。
  5. Do not mix responsibility. 不要混淆责任。 For instance code checking for string existance in your trie structure should not be the one responsible to print the answer. 例如,检查您的特里结构中是否存在字符串的代码不应成为打印答案的负责人。
  6. Do not use strings as flags this is just plainly confusing. 不要将字符串用作标志,这很容易造成混淆。

This one should be an equivalent (unless I messed up): 这应该是等效的(除非我搞砸了):

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

typedef struct node_s node_t;
struct node_s {
  char alphabet;
  char present;
  node_t *pnt;
};

typedef struct {
    node_t *first;
    int count;
} head_t;

#define NLETTERS 26
inline static int is_letter(char c) { return c <= 'z' && c >= 'a'; }

inline static node_t* new_trieblock() {
  const int size = NLETTERS * sizeof(node_t);
  node_t* block = malloc(size);
  memset(block, 0, size);
  for (int i = 0; i < NLETTERS; i++) {
    block[i].alphabet = 'a' + i;
  }
  return block;
}

inline static int trie_has(node_t *n, char *str) {
  node_t *trie = n;
  int len = strlen(str);
  for (int i = 0; i < len - 1; i++) {
    trie = trie[str[i] - 'a'].pnt;
    if (!trie) return 0;    
  }
  return trie[str[len-1] - 'a'].present;
}

int main(void) {
    FILE* dict = fopen("large", "r");

    head_t *header = malloc(sizeof(head_t));
    header->count = 0;
    header->first = new_trieblock();

    node_t *trie = header->first;
    char c = fgetc(dict);
    int nc;
    while(is_letter(c) || c == '\n') {
        nc = fgetc(dict);

        if (nc == '\n' || nc == EOF) {
            trie[c - 'a'].present = 1;
            header->count++;
        } else {
          if (!trie[c - 'a'].pnt) {
            trie = trie[c - 'a'].pnt = new_trieblock();
          } else {
            trie = trie[c - 'a'].pnt;
          }
        }

        c = nc;
        while (c == '\n') {
          trie = header->first;
          c = fgetc(dict);
        }
    }

    char tocheck[100];
    scanf("%s", tocheck);

    if (trie_has(header->first, tocheck)) {
        printf("correctly spelled\n");
    } else {
        printf("mis-spelled\n");
    }

    return 0;
}

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

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