【问题标题】:Why am I getting an "undefined reference to `parseAndExecute' " error here?为什么我在这里得到一个“未定义的对 `parseAndExecute\' 的引用”错误?
【发布时间】:2022-10-15 02:43:16
【问题描述】:

我正在使用有关如何制作文本冒险游戏(在 VSC 中)的在线教程,但遇到了一个非常烦人的问题。即使从教程中复制了所有源代码,我也会收到“未定义的引用”错误。我尝试按照此处所述编辑“tasks.json”文件:undefined reference error in VScode 但没有成功。

该游戏由多个c文件组成,以便工作,源代码在页面底部:https://helderman.github.io/htpataic/htpataic05.html

这是所有文件,非常感谢您的帮助!

    <main.c>

#include <stdbool.h>
#include <stdio.h>
#include "parsexec.h"


static char input[100] = "look around";

static bool getInput(void)
{
   printf("\n--> ");
   return fgets(input, sizeof input, stdin) != NULL;
}

int main()
{
   printf("Welcome to Little Cave Adventure.\n");
   while (parseAndExecute(input) && getInput());
   printf("\nBye!\n");
   return 0;
}

<parsexec.h>

   

 extern bool parseAndExecute(char *input);

    <parsexec.c>

#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "location.h"
#include "inventory.h"

bool parseAndExecute(char *input)
{
   char *verb = strtok(input, " \n");
   char *noun = strtok(NULL, " \n");
   if (verb != NULL)
   {
      if (strcmp(verb, "quit") == 0)
      {
         return false;
      }
      else if (strcmp(verb, "look") == 0)
      {
         executeLook(noun);
      }
      else if (strcmp(verb, "go") == 0)
      {
         executeGo(noun);
      }
      else if (strcmp(verb, "get") == 0)
      {
         executeGet(noun);
      }
      else if (strcmp(verb, "drop") == 0)
      {
         executeDrop(noun);
      }
      else if (strcmp(verb, "give") == 0)
      {
         executeGive(noun);
      }
      else if (strcmp(verb, "ask") == 0)
      {
         executeAsk(noun);
      }
      else if (strcmp(verb, "inventory") == 0)
      {
         executeInventory();
      }
      else
      {
         printf("I don't know how to '%s'.\n", verb);
      }
   }
   return true;
}

<location.c>

#include <stdio.h>
#include <string.h>
#include "object.h"
#include "misc.h"
#include "noun.h"

void executeLook(const char *noun)
{
   if (noun != NULL && strcmp(noun, "around") == 0)
   {
      printf("You are in %s.\n", player->location->description);
      listObjectsAtLocation(player->location);
   }
   else
   {
      printf("I don't understand what you want to see.\n");
   }
}

void executeGo(const char *noun)
{
   OBJECT *obj = getVisible("where you want to go", noun);
   if (obj == NULL)
   {
      // already handled by getVisible
   }
   else if (obj->location == NULL && obj != player->location)
   {
      printf("OK.\n");
      player->location = obj;
      executeLook("around");
   }
   else
   {
      printf("You can't get much closer than this.\n");
   }
}

  <location.h>
    extern void executeLook(const char *noun);
    extern void executeGo(const char *noun);

<object.c>
#include <stdio.h>
#include "object.h"

OBJECT objs[] = {
   {"an open field", "field"   , NULL  },
   {"a little cave", "cave"    , NULL  },
   {"a silver coin", "silver"  , field },
   {"a gold coin"  , "gold"    , cave  },
   {"a burly guard", "guard"   , field },
   {"yourself"     , "yourself", field }
};

<object.h>
typedef struct object {
   const char    *description;
   const char    *tag;
   struct object *location;
} OBJECT;

extern OBJECT objs[];

#define field      (objs + 0)
#define cave       (objs + 1)
#define silver     (objs + 2)
#define gold       (objs + 3)
#define guard      (objs + 4)
#define player     (objs + 5)

#define endOfObjs  (objs + 6)

<noun.c>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "object.h"

static bool objectHasTag(OBJECT *obj, const char *noun)
{
   return noun != NULL && *noun != '\0' && strcmp(noun, obj->tag) == 0;
}

static OBJECT *getObject(const char *noun)
{
   OBJECT *obj, *res = NULL;
   for (obj = objs; obj < endOfObjs; obj++)
   {
      if (objectHasTag(obj, noun))
      {
         res = obj;
      }
   }
   return res;
}

OBJECT *getVisible(const char *intention, const char *noun)
{
   OBJECT *obj = getObject(noun);
   if (obj == NULL)
   {
      printf("I don't understand %s.\n", intention);
   }
   else if (!(obj == player ||
              obj == player->location ||
              obj->location == player ||
              obj->location == player->location ||
              obj->location == NULL ||
              obj->location->location == player ||
              obj->location->location == player->location))
   {
      printf("You don't see any %s here.\n", noun);
      obj = NULL;
   }
   return obj;
}

OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun)
{
   OBJECT *obj = NULL;
   if (from == NULL)
   {
      printf("I don't understand who you want to %s.\n", verb);
   }
   else if ((obj = getObject(noun)) == NULL)
   {
      printf("I don't understand what you want to %s.\n", verb);
   }
   else if (obj == from)
   {
      printf("You should not be doing that to %s.\n", obj->description);
      obj = NULL;
   }
   else if (obj->location != from)
   {
      if (from == player)
      {
         printf("You are not holding any %s.\n", noun);
      }
      else
      {
         printf("There appears to be no %s you can get from %s.\n",
                noun, from->description);
      }
      obj = NULL;
   }
   return obj;
}

<noun.h>
extern OBJECT *getVisible(const char *intention, const char *noun);
extern OBJECT *getPossession(OBJECT *from, const char *verb, const char *noun);

<inventory.c>
#include <stdio.h>
#include "object.h"
#include "misc.h"
#include "noun.h"
#include "move.h"

void executeGet(const char *noun)
{
   OBJECT *obj = getVisible("what you want to get", noun);
   if (obj == NULL)
   {
      // already handled by getVisible
   }
   else if (obj == player)
   {
      printf("You should not be doing that to yourself.\n");
   }
   else if (obj->location == player)
   {
      printf("You already have %s.\n", obj->description);
   }
   else if (obj->location == guard)
   {
      printf("You should ask %s nicely.\n", obj->location->description);
   }
   else
   {
      moveObject(obj, player);
   }
}

void executeDrop(const char *noun)
{
   moveObject(getPossession(player, "drop", noun), player->location);
}

void executeAsk(const char *noun)
{
   moveObject(getPossession(actorHere(), "ask", noun), player);
}

void executeGive(const char *noun)
{
   moveObject(getPossession(player, "give", noun), actorHere());
}

void executeInventory(void)
{
   if (listObjectsAtLocation(player) == 0)
   {
      printf("You are empty-handed.\n");
   }
}

<inventory.h>
extern void executeGet(const char *noun);
extern void executeDrop(const char *noun);
extern void executeAsk(const char *noun);
extern void executeGive(const char *noun);
extern void executeInventory(void);

<misc.c>
#include <stdio.h>
#include "object.h"

OBJECT *actorHere(void)
{
   OBJECT *obj;
   for (obj = objs; obj < endOfObjs; obj++)
   {
      if (obj->location == player->location && obj == guard)
      {
         return obj;
      }
   }
   return NULL;
}

int listObjectsAtLocation(OBJECT *location)
{
   int count = 0;
   OBJECT *obj;
   for (obj = objs; obj < endOfObjs; obj++)
   {
      if (obj != player && obj->location == location)
      {
         if (count++ == 0)
         {
            printf("You see:\n");
         }
         printf("%s\n", obj->description);
      }
   }
   return count;
}

<misc.h>

    extern OBJECT *actorHere(void);
    extern int listObjectsAtLocation(OBJECT *location);

<move.c>
#include <stdio.h>
#include "object.h"

static void describeMove(OBJECT *obj, OBJECT *to)
{
   if (to == player->location)
   {
      printf("You drop %s.\n", obj->description);
   }
   else if (to != player)
   {
      printf(to == guard ? "You give %s to %s.\n" : "You put %s in %s.\n",
             obj->description, to->description);
   }
   else if (obj->location == player->location)
   {
      printf("You pick up %s.\n", obj->description);
   }
   else
   {
      printf("You get %s from %s.\n",
             obj->description, obj->location->description);
   }
}

void moveObject(OBJECT *obj, OBJECT *to)
{
   if (obj == NULL)
   {
      // already handled by getVisible or getPossession
   }
   else if (to == NULL)
   {
      printf("There is nobody here to give that to.\n");
   }
   else if (obj->location == NULL)
   {
      printf("That is way too heavy.\n");
   }
   else
   {
      describeMove(obj, to);
      obj->location = to;
   }
}

<move.h>
extern void moveObject(OBJECT *obj, OBJECT *to);

VSC 中的问题图片: https://i.stack.imgur.com/5mkzV.png

【问题讨论】:

  • 你是怎么编译的?
  • 你为什么把它变成外部的?
  • 我使用了一个教程来使用 msys64 和 mingw64 设置我的 VSC,这不是我的代码,它直接来自我链接的教程,所以我不知道为什么使用 extern。
  • extern 对于另一个文件中定义的函数是正确的。人们有时会忽略它,因为它在大多数情况下都是隐含的,但实际上这是正确的存储类。
  • 在任何情况下,问题是您试图自己编译和链接main.c,这将不起作用,因为它取决于parsexec.c 中的内容。您需要同时编译main.cparsexec.c,然后将两者链接以生成可执行文件(或者您可以一次编译和链接所有内容,但通常人们会独立于链接编译多文件程序)。

标签: c visual-studio-code include


【解决方案1】:

您的代码无法编译,因为它依赖于您尚未与我们共享的头文件,以及我们没有实现的 executeAsk()。我从parsexec.c 中删除了缺失的位:

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

bool parseAndExecute(char *input) {
    char *verb = strtok(input, " 
");
    char *noun = strtok(NULL, " 
");
    if (verb != NULL) {
        printf("I don't know how to '%s'.
", verb);
    }
    return true;
}

然后能够构建和执行您的游戏:

gcc main.c parsexec.c -o game && ./game
Welcome to Little Cave Adventure.
I don't know how to 'look'.

--> look
I don't know how to 'look'.

--> ^C

这告诉我这是一个构建问题。具体来说,您可能没有将parsexec.o 链接到您的二进制文件。

【讨论】:

  • 我没有共享所有代码,因为我认为发布整个源代码的链接是可以的。我将编辑我的帖子并添加所有代码。
  • 不,您应该提供minimal reproducible example,在这种情况下,我们缺少的主要数据是您如何构建程序。代码很好。
  • 问题是,这不是我的代码,它来自一个教程,所以我不知道如何告诉你们它是如何构建的
  • “事情是,这不是我的代码”告诉我你不想为此付出任何努力,所以我当然不想竭尽全力帮助你。如果您不知道构建系统在 Visual Studio 代码中是如何工作的,那么当我们询问该信息时,最好在评论中告诉我们。我还用你的 ide 标记了这个问题。我从未使用过它,所以我不会特别有帮助。
  • 很抱歉,如果这看起来我没有付出努力,我是一个完全的新手,我不知道如何开始解释程序是如何构建的。
【解决方案2】:

结果证明是 VSC 中的编译器/设置错误,因为代码在另一台机器上运行良好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多