![](/img/trans.png)
[英]How can I implement a 'Do while' loop only using GOTO in the C language?
[英]How can I goto the value of a String in C?
我正在用C語言編寫一個機器人,我遇到了一個我似乎無法弄清楚的問題。
解決這個問題的唯一方法是使用很多goto
語句。 我試圖找出一種方法來節省自己寫100多個goto
點和語句和if語句等,並且我想知道是否有一種方法來轉換字符串的值。 例如-
string Next = "beginning";
goto Next;
beginning:
有沒有辦法goto
Next
的值,或者將Next
的值替換為goto
語句?
如果有一種方法可以做到這一點,那么我就可以只改變的值Next
每個驅動命令,然后goto
任何字符串的值Next
是。
換句話說,只需將字符串轉換為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(這是命令執行的時間,以毫秒為單位),然后你使代碼轉到你輸入的駕駛命令。駕駛命令驅動你輸入的時間,然后轉到nextCommand;
如果有一種方法可以使goto語句“解釋”字符串作為標識符,那么這在理論上都可以工作,因此可以對其進行更改。
我現在可以想到的有四種簡單的方法可以很容易地解決這個問題,但是它們會使代碼真的很長而且雜亂無章。
現在你對我的問題有了更好的理解,還有更多的輸入? :)
順便說一句 - 我正在使用一個名為robotC的程序,我正在編寫一個vex機器人。 所以我必須使用普通,基本,C,我不能使用任何插件或任何東西......這是另一個原因,這是復雜的,因為我不能有多個類和類似的東西......
作為C語言的擴展,GCC提供了一個名為computed gotos的功能,允許您goto
在運行時計算的標簽。 但是, 我強烈建議您重新考慮您的設計 。
而不是使用帶有超過一百個標簽的gotos
(這很容易導致不可維護的意大利面條代碼),而是考慮使用函數指針。 代碼將更加結構化和可維護。
而不是goto,我會調用100個函數之一。 雖然C不會為你處理從字符串到函數的轉換,但是使用排序的結構數組很容易:
struct fn {
char name[whatever];
void (*func)(void);
};
然后(例如)通過數組進行二進制搜索以找到與字符串匹配的函數。
另請注意,許多真實系統提供諸如GetProcAddress
(Windows)或dlsym
(Unix / Linux)之類的東西來為您處理一些工作。
你正在考慮這個錯誤的方法。 您需要調用的每個操作都應該是一個函數,然后您可以通過檢查“next”變量來選擇下一個應該調用的函數。
這可能是您提到的字符串,但您可能最好使用枚舉類型來生成可讀但更有效的代碼。
替代方法雖然可能過度,但可以確保您的函數都使用相同的參數和返回類型,然后使用函數指針來跟蹤下一個應該執行的代碼段。
小提示:如果您認為自己需要超過1個goto語句才能實現某個目標,那么您可能不會考慮最佳解決方案。
您需要退一步考慮其他解決方案,以解決您要解決的問題。 其中一個可能看起來像這樣:
void DoSomething() {
printf("Something\n");
}
void DoSomethingElse() {
printf("Something else\n");
}
void (*nextStep)(void) = NULL;
nextStep = DoSomething;
nextStep();
nextStep = DoSomethingElse;
nextStep();
看到它在行動 。
首先,讓我通過與其他所有人達成一致來形容這一點:這可能不是你正在嘗試做什么的正確方法。 特別是,我認為你可能想要一個有限狀態機,我推薦這篇文章來指導如何做到這一點。
那就是說。 。 。 您可以使用switch
語句或多或少地執行此switch
。 例如:
Next = BEGINNING;
HelperLabel:
switch(Next)
{
case BEGINNING:
.
.
.
Next = CONTINUING;
goto HelperLabel;
case ENDING:
.
.
.
break;
case CONTINUING:
.
.
.
Next = ENDING;
goto HelperLabel;
}
(請注意, switch
語句需要整數或類似整數的值而不是字符串,但您可以使用enum
以直接的方式創建這些整數。)
有關將switch
/ case
用作goto
的原始典型示例,請參見http://en.wikipedia.org/wiki/Duff's_device 。
switch
怎么樣? 要么使用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
}
#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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.