从文件错误中读取单词

时间:2016-01-23 13:27:48

标签: c file tree binary-tree

我从文件中读取单词并将其传递给二叉树时出现问题。当我调试它时,它说:

  if (characterquality == "Slayer"){
        int HP = 150;
        int Attack = 75;
        int Defense = 50;
        int MP = 20;
        int EXP = 0;
        int Gold = 50;

       boolean firstbattle = true;
       while (firstbattle){
          int firstbattlehealth = HP;
          int firstbattleattack = Attack;
          int firstbattledefense = Defense;
          int firstbattleMP = MP;
          int firstbattleEXP = EXP;
          int firstbattlegold = Gold;

          int firstattack = (int) Math.ceil(Math.random() * 6);
          int firstdefense = (int) Math.ceil(Math.random() * 6);

          int firstenemyattack = (int) Math.ceil(Math.random() * 6);
          int firstenemydefense = (int) Math.ceil(Math.random() * 6);

          int firstenemyhealth = (int) Math.ceil(Math.random() * 50);

          int firstenemyhitpoints = (int) Math.ceil(Math.random() * 25);
          boolean firstkill = true;
          while (firstkill) {
              if (firstattack > firstenemydefense){
                  int firsthitpoints = (int) Math.ceil(Math.random() * firstbattleattack);

              }
              int firstenemynewhealth = firstenemyhealth - firsthitpoints;

              if (firstenemynewhealth <= 0){
                  firstkill = false;
              }
              if (firstattack <= firstenemydefense){
                 System.out.println("Attack failed!");
              }
              if (firstenemyattack > firstdefense){
                  int firstenemyhitpointattack = (int) Math.ceil(Math.random() * firstenemyhitpoints);
                  System.out.println("The enemy did " + firstenemyhitpointattack + " damage to you. You have " + firstbattlehealth + " health remaining.");
               }
              if (firstenemyattack <= firstdefense){
                  System.out.println("Enemy attack missed!");
              }
          }
          int firstenemynewhealth = firstenemynewhealth;
          if (firstenemynewhealth <= 0){
              firstbattle = false;
           }
       }
    }

以下是源代码:

Unhandled exception at 0x76E7773B(ntdll.dll) in Projekt.exe: 0.C00000005:
    Access violation reading location 0x0037902A.

1 个答案:

答案 0 :(得分:1)

您的计划有几个问题:

    在函数zero
  • ,你过早释放指针,你应该将free(aTree);作为最后一个语句移动,否则你调用未定义的行为,可能是崩溃(但不是你的那个)有,因为你从来没有称这个功能):

    void zero(Tree *aTree) {
        if (aTree != NULL) {
            zero(aTree->left);
            zero(aTree->right);    
            free(aTree);
    }
    
  • 在函数alpha中,使用递归,其中一个简单的循环就足够了。编译器可能会将其转换为循环,但确实如此。这不是一个错误,但为什么不使用更惯用的方法,如:

    int alpha(const char *word1, const char *word2) {
        for (size_t i = 0;; i++) {
            if (word1[i] == '\0' && word2[i] == '\0')
                return 2;
    
            if (word1[i] == word2[i])
                continue;
    
            if (word1[i] < word2[i])
                return 1;
            else
                return 0;
        }
    }
    
  • 在函数create中,为字符串分配一个字节,这肯定是导致崩溃的原因。您应该分配strlen(word) + 1或使用strdup(word)。您不应该转换malloc()的返回值:

    Tree *create(const char *word) {
        Tree *temp;
        temp = malloc(sizeof(Tree));
        temp->left = temp->right =  NULL;
        temp->val = 1;
        temp->word = strdup(word);
        return temp;
    }
    
  • 在函数insert中,您多次调用alpha,效率很低:您可以使用switch语句:

    Tree *insert(Tree *aTree, const char *word) {
        if (aTree == NULL) {
            return create(word);
    
        switch (alpha(aTree->word, word)) {
            case 0:
                aTree->left = insert(aTree->left, word);
                break;
            case 1:
                aTree->right = insert(aTree->right, word);
                break;
            case 2:
                aTree->val++;
                break;
            }
        }
        return aTree;
    }
    
  • 函数main有多个问题:

    • 您不检查是否为程序提供了argv[1]。如果程序在没有命令行参数的情况下运行,则为NULL
    • 您对文件结尾的测试不正确:temp应定义为int,您应该在使用getc()从文件中读取字节后测试其值,这是惯用的名称c用于此的变量。
    • 您应该使用字符文字而不是硬编码的ASCII值。
    • 测试if (c >= 'A' && c <= 'Z')适用于ASCII,这在今天几乎是通用的,但使用isupper(c)代替它更可靠。
    • 您无需清除buffer,在插入单词之前设置'\0'即可。
    • 您还应该检查缓冲区溢出并拒绝处理超过255个字符的单词。
    • fclose(fp)fp时,您不应致电NULL,这是未定义的行为。

    以下是更正后的版本:

    int main(int argc, char *argv[]) {
        Tree *myTree = NULL;
        char buffer[256];
        int c;
        size_t i;
        FILE *fp;
    
        if (argc < 2) {
            printf("missing argument\n");
            return 2;
        }
    
        fp = fopen(argv[1], "r");
        if (fp == NULL)  {
            printf("cannot open %s\n", argv[1]);
            return 1;
        }
        i = 0;
        while ((c = getc(fp)) != EOF) {
            c = toupper(c);
            if (isupper(c)) {
                if (i < sizeof(buffer))
                    buffer[i] = c;
                i++;
            } else {
                if (i > 0 && i < sizeof(buffer)) {
                    buffer[i] = '\0';
                    puts(buffer);
                    myTree = insert(myTree, buffer);
                    i = 0;
                }
            }
        }
        fclose(fp);
        show(myTree);
        return 0;
    }