在C语言中如何获取字符串的值?

发布于 2024-12-26 01:55:18 字数 2821 浏览 1 评论 0原文

我正在用 C 语言编写一个机器人,我遇到了一个我似乎无法解决的问题。

解决这个问题的唯一方法是使用大量的 goto 语句。 我正在尝试找出一种方法来节省自己编写 100 多个 goto 点和语句以及 if 语句等,并且想知道是否有一种方法可以转到字符串的值。例如-

string Next = "beginning";
goto Next;
beginning:

有没有办法goto Next的值,或者将Next的值替换为goto< /代码>声明?

如果有办法做到这一点,那么我将能够仅更改每个驾驶命令的 Next 值,然后 goto 无论字符串 <代码>下一步是。

换句话说,只需将字符串转换为 goto 标识符,或用它代替标识符。

感谢您的帮助!

-编辑-

很多人都建议使用 switch 语句。我不确定这是否有效,因为我是如何编程的。程序的结构是这样的—— 顺便说一下,这段代码只包含了我实际拥有的一小部分,到目前为止我的实际代码已经超过 500 行。此外,驾驶命令也大大简化。但基本概念就在这里,比我想象的更容易理解。

task main()
{
  //integer list
  int forwardDrivingSelector = 0;
  int backwardDrivingSelector = 0;
  int rightRotatingSelector = 0;
  string nextCommand;
  int waitTime = 0;
  int countup = 0;

  //driving commands

  driveForward:
  while(forwardDrivingSelector == 1)
  {
    motor[leftMotor] = 127;
    motor[rightMotor] = 127;
    countup++;
    wait1Msec(1);
    if(countup == waitTime)
    {
      countup = 0;
      goto nextCommand;
    }
  }
  driveBackward:
  while(backwardDrivingSelector == 1)
  {
    motor[leftMotor] = -127;
    motor[rightMotor] = 127;
    countup++;
    wait1Msec(1);
    if(countup == waitTime)
    {
      countup = 0;
      goto nextCommand;
    }
  }
  rightRotate:
  while(rightRotatingSelector == 1)
  {
    motor[leftMotor] = 127;
    motor[rightMotor] = -127;
    countup++;
    wait1Msec(1);
    if(countup == waitTime)
    {
      countup = 0;
      goto nextCommand;
    }
  }

  //autonomous driving code

  //first command, drive forward for 1000 milliseconds
  forwardDrivingSelector = 1;
  nextCommand = "secondCommand";
  waitTime = 1000;
  goto driveForward;

  secondCommand:
  forwardDrivingSelector = 0;

  //second command, rotate right for 600 milliseconds
  rightRotatingSelector = 1;
  nextCommand = "thirdCommand";
  waitTime = 600;
  goto rightRotate;

  thirdCommand:
  rightRotatingSelector = 0;

  //third command, drive backwards for 750 milliseconds
  backwardDrivingSelector = 1;
  nextCommand = "end";
  waitTime = 750;
  goto driveBackward;

  end:
  backwardDrivingSelector = 0;

}

所以。这是如何运作的。 我有一个整数列表,包括驱动命令选择器、countup 和 waitTime 整数,以及我正在讨论的字符串 nextCommand。 接下来是驾驶命令。在我的真实代码中,我有大约 30 个命令,它们都连接到遥控器,仅驱动命令就有 400 多行。 接下来是自治代码。我这样设置的原因是为了让自主代码部分变得简短、简单、切题。几乎要向驱动代码添加命令,您打开选择器,告诉 nextCommand 字符串下一个命令是什么,设置 waitTime (这是执行命令的时间,以毫秒为单位),然后使代码转到您输入的驱动命令。驱动命令会驱动您输入的时间,然后转到下一个命令;

如果有一种方法可以使 goto 语句将字符串“解释”为标识符以便可以更改它,那么理论上这一切都是可行的。

我现在能想到的大约有 4 种简单的方法可以轻松解决这个问题,但它们会使代码变得非常非常长和混乱。

现在您对我的问题有了更好的理解,还有什么意见吗? :)

顺便说一句 - 我正在使用一个名为 robotsC 的程序,并且我正在编写一个 vex 机器人。所以我必须使用普通的、基本的、C 语言,而且我不能使用任何插件或任何东西...这是这很复杂的另一个原因,因为我不能有多个类和类似的东西...

I am programming a robot in C, and I have run into a problem I can't seem to figure out.

The only way to solve this problem would be to use a lot of goto statements.
I am trying to figure out a way to save myself writing over 100 goto points and statements and if statements, etc. and am wondering if there is a way to goto the value of a string. for example-

string Next = "beginning";
goto Next;
beginning:

Is there any way to goto the value of Next, or to substitute in the value of Next into the goto statement?

If there is a way to do this, then I will be able to just change the value of Next for each driving command, and then goto whatever the value of the string Next is.

In other words, just converting the string to a goto identifier, or substituting it in place of one.

Thanks for the help!

-EDIT-

A lot of you guys are suggesting the use of switch statements. I am not sure this would work because of how i have it programmed. The structure of the program is here--
by the way this code only includes a little of what i actually have, my real code is over 500 lines so far. Also, the driving commands are majorly simplified. but the basic concept is here, easier to understand than what i wouldve had.

task main()
{
  //integer list
  int forwardDrivingSelector = 0;
  int backwardDrivingSelector = 0;
  int rightRotatingSelector = 0;
  string nextCommand;
  int waitTime = 0;
  int countup = 0;

  //driving commands

  driveForward:
  while(forwardDrivingSelector == 1)
  {
    motor[leftMotor] = 127;
    motor[rightMotor] = 127;
    countup++;
    wait1Msec(1);
    if(countup == waitTime)
    {
      countup = 0;
      goto nextCommand;
    }
  }
  driveBackward:
  while(backwardDrivingSelector == 1)
  {
    motor[leftMotor] = -127;
    motor[rightMotor] = 127;
    countup++;
    wait1Msec(1);
    if(countup == waitTime)
    {
      countup = 0;
      goto nextCommand;
    }
  }
  rightRotate:
  while(rightRotatingSelector == 1)
  {
    motor[leftMotor] = 127;
    motor[rightMotor] = -127;
    countup++;
    wait1Msec(1);
    if(countup == waitTime)
    {
      countup = 0;
      goto nextCommand;
    }
  }

  //autonomous driving code

  //first command, drive forward for 1000 milliseconds
  forwardDrivingSelector = 1;
  nextCommand = "secondCommand";
  waitTime = 1000;
  goto driveForward;

  secondCommand:
  forwardDrivingSelector = 0;

  //second command, rotate right for 600 milliseconds
  rightRotatingSelector = 1;
  nextCommand = "thirdCommand";
  waitTime = 600;
  goto rightRotate;

  thirdCommand:
  rightRotatingSelector = 0;

  //third command, drive backwards for 750 milliseconds
  backwardDrivingSelector = 1;
  nextCommand = "end";
  waitTime = 750;
  goto driveBackward;

  end:
  backwardDrivingSelector = 0;

}

so. how this works.
i have a list of integers, including driving command selectors, the countup and waitTime integers, and the string that i was talking about, nextCommand.
next comes the driving commands. in my real code, i have about 30 commands, and they are all hooked up to a remote control and its over 400 lines for just the driving commands.
next comes the autonomous code. the reason i set it up like this is so that the autonomous code part would be, short, simple, and to the point. pretty much to add a command to the driving code, you turn on the selector, tell the nextCommand string what the next command is, set the waitTime (which is how long it does the command, in milliseconds), then you make the code goto the driving command which you are putting in. the driving command drives for the amount of time you put in, then does goto nextCommand;

This would all theoretically work if there was a way to make the goto statement 'interpret' the string as an identifier so it can be changed.

There are about 4 simple ways i can think of right now that could get past this easily, but they would make the code really really long and cluttered.

Now that you have a better understanding of my question, any more input? :)

btw - i am using a program called robotC, and i am programming a vex robot. so i HAVE to use plain, basic, C, and i cant use any addons or anything... which is another reason this is complicated because i cant have multiple classes and stuff like that...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

夏末染殇 2025-01-02 01:55:18

作为 C 语言的扩展,GCC 提供了一个名为 的功能计算的 goto,它允许您转到运行时计算的标签。但是,我强烈建议您重新考虑您的设计

不要使用带有一百多个标签的 gotos(这很容易导致不可维护的意大利面条式代码),而是考虑使用函数指针。代码将更加结构化和可维护。

As an extension to the C language, GCC provides a feature called computed gotos, which allow you to goto a label computed at runtime. However, I strongly recommend you reconsider your design.

Instead of using gotos with over a hundred labels (which will easily lead to unmaintainable spaghetti code), consider instead using function pointers. The code will be much more structured and maintainable.

幽梦紫曦~ 2025-01-02 01:55:18

我会调用 100 个函数之一,而不是 goto。虽然 C 不会为您处理从字符串到函数的转换,但使用排序的结构数组非常容易:

struct fn {
    char name[whatever];
    void (*func)(void);
};

然后(例如)对数组进行二分搜索以查找与字符串匹配的函数。

另请注意,许多实际系统提供诸如 GetProcAddress (Windows) 或 dlsym (Unix/Linux) 之类的东西来为您处理一些工作。

Instead of goto's, I'd call one of 100 functions. While C won't handle the conversion from string to function for you, it's pretty easy to use a sorted array of structs:

struct fn {
    char name[whatever];
    void (*func)(void);
};

Then do (for example) a binary search through the array to find the function that matches a string.

Also note that many real systems provide things like GetProcAddress (Windows) or dlsym (Unix/Linux) to handle some of the work for you.

没企图 2025-01-02 01:55:18

你思考这个问题的方式是错误的。您需要调用的每个操作都应该是一个函数,然后您可以通过检查“下一个”变量来选择接下来应该调用哪个函数。

正如您所提到的,这可能是一个字符串,但您最好使用枚举类型来编写可读但更高效的代码。

另一种选择(虽然可能有点过分)是确保您的函数都使用相同的参数和返回类型,然后使用函数指针来跟踪接下来应该执行哪一段代码。

小提示:如果您认为需要 1 个以上的 goto 语句才能实现某个目标,那么您可能并不是在寻找最佳解决方案。

You're thinking about this the wrong way. Each of the actions you need to call should be a function, then you can choose which function should be called next by inspecting a "next" variable.

This could be a string as you've mentioned, but you might be best using a enumerated type to make readable, but more efficient code.

The alternative, though probably overkill, would be to ensure your functions all use the same parameters and return types, and then use a function pointer to track which piece of code should be executed next.

Small tip: If you ever think you need more than 1 goto statement to achieve a certain goal you're probably not looking at the best solution.

孤星 2025-01-02 01:55:18

您需要退后一步,考虑您要解决的问题的其他解决方案。其中之一可能如下所示:

void DoSomething() {
    printf("Something\n");
}

void DoSomethingElse() {
    printf("Something else\n");
}

void (*nextStep)(void) = NULL;

nextStep = DoSomething;
nextStep();
nextStep = DoSomethingElse;
nextStep();

查看实际操作

You need to step back and consider other solutions for the problem you are trying to solve. One of them might look like this:

void DoSomething() {
    printf("Something\n");
}

void DoSomethingElse() {
    printf("Something else\n");
}

void (*nextStep)(void) = NULL;

nextStep = DoSomething;
nextStep();
nextStep = DoSomethingElse;
nextStep();

See it in action.

弥繁 2025-01-02 01:55:18

开关怎么样?使用 int/enum/whatever 或检查字符串的值(例如循环遍历它和 strcmp)来找出目的地。

const char *dsts[n_dsts] = {"beginning","middle",...};
...
int i;
for(i = 0; i < n_dsts; i++) if(strcmp(dsts[i]) == 0) break;
switch(i) {
    case 0: // whatever
    case 1: // whatever
    ...
        break;
    default: // Error, dest not found
}

How about a switch? Either use an int/enum/whatever or inspect the value of the string (loop over it and strcmp, for instance) to figure out the destination.

const char *dsts[n_dsts] = {"beginning","middle",...};
...
int i;
for(i = 0; i < n_dsts; i++) if(strcmp(dsts[i]) == 0) break;
switch(i) {
    case 0: // whatever
    case 1: // whatever
    ...
        break;
    default: // Error, dest not found
}
墨离汐 2025-01-02 01:55:18

首先,让我同意其他人的观点:这可能不是完成您想要做的事情的正确方法。特别是,我认为您可能想要一个有限状态机,我推荐

话虽这么说。 。 。您或多或少可以通过使用 switch 语句来做到这一点。例如:(

Next = BEGINNING;
HelperLabel:
switch(Next)
{
   case BEGINNING:
     .
     .
     .
     Next = CONTINUING;
     goto HelperLabel;
   case ENDING:
     .
     .
     .
     break;
   case CONTINUING:
     .
     .
     .
     Next = ENDING;
     goto HelperLabel;
}

请注意,switch 语句需要整数或类似整数的值,而不是字符串,但您可以使用 enum 以简单的方式创建这些整数。)

请参阅 http://en.wikipedia.org/wiki/Duff's_device 了解原始内容,使用的典型示例switch/case 作为 goto

Firstly, let me preface this by agreeing with everyone else: this is probably not the right way to go about what you're trying to do. In particular, I think you probably want a finite-state machine, and I recommend this article for guidelines on how to do that.

That said . . . you can more or less do this by using a switch statement. For example:

Next = BEGINNING;
HelperLabel:
switch(Next)
{
   case BEGINNING:
     .
     .
     .
     Next = CONTINUING;
     goto HelperLabel;
   case ENDING:
     .
     .
     .
     break;
   case CONTINUING:
     .
     .
     .
     Next = ENDING;
     goto HelperLabel;
}

(Note that a switch statement requires integers or integer-like values rather than strings, but you can use an enum to create those integers in a straightforward way.)

See http://en.wikipedia.org/wiki/Duff's_device for the original, canonical example of using switch/case as a goto.

用心笑 2025-01-02 01:55:18
#define GOTO_HELPER(str, label) \
    if (strcmp(str, #label) == 0) goto label;

#define GOTO(str) do { \
    GOTO_HELPER(str, beginning) \
    GOTO_HELPER(str, end) \
    } while (0)


int main (int argc, char ** argv) {
    GOTO("end");
beginning:
    return 1;
end:
    return 0;
}
#define GOTO_HELPER(str, label) \
    if (strcmp(str, #label) == 0) goto label;

#define GOTO(str) do { \
    GOTO_HELPER(str, beginning) \
    GOTO_HELPER(str, end) \
    } while (0)


int main (int argc, char ** argv) {
    GOTO("end");
beginning:
    return 1;
end:
    return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文