Turtle Graphics 程序 (C) 上的不可读输入

我被要求做一个简单的 20x20 海龟图形程序,但出于某种原因,我遇到了一个可能与第 42 行到 150 行相关的问题(只有它们最初出现在帖子中,但我对其进行了编辑,因为有人要求我在评论):

proc summary data=data median nway;
var var1 var2 var3-var8 var11--var14;
class c1 c2 c3;
output out=medians(drop=_:) median= / autoname;
*if no autoname option;
*output out=medians(drop = _:) median = var1_median var2_median
var3_median ...... ;
run;

基本上,在代码的开头有一个“while”等待用户输入,直到与 'e' 和 'E' 不同,并且在大多数情况下它似乎工作正常

问题是,当我在右转或左转(通过在字符“r”或“l”之后输入“w”)或尝试多次使用“w”输入后行走时,程序不断要求由于某种原因没有读取“w”的输入(对于变量 com,而不是 step)

任何其他输入,如 'p'、'e' 甚至 'l' 和 'r' 再次工作正常,但 'w' 特别不起作用,如果我使用 'p'('e' 't count 因为它会停止重复)然后'w'输入也会被识别

所有这些ifs的算法有点糟糕,但这是我自己能想到的最简单易懂的

abcd_219616 回答:Turtle Graphics 程序 (C) 上的不可读输入

#include "turtle.h"

int main()
{
    turtle_init(300,300);          // initialize the image to be 600x600

    turtle_forward(50);
    turtle_turn_left(90);
    turtle_forward(50);
    turtle_draw_turtle();

    turtle_save_bmp("output.bmp");  // save the turtle drawing

    return EXIT_SUCCESS;
}
,

当我运行你的程序并输入 l 作为第一个命令和 w 作为第二个命令时,它将执行以下循环:

while (p2 - step < 0)
{
    scanf("%d",&step);
    getchar();
}

因为此时 p2 == 0,这个循环将永远运行,直到用户输入零或负数。这似乎不是故意的。此外,程序似乎并不打算在不事先告诉用户输入什么的情况下读取用户的输入。

诊断此类问题的最佳方法是在 debugger 中逐行运行程序,同时监视所有变量的值。这样,很容易看出您的程序在哪一点停止按预期运行。

另外,你的程序还有以下问题:


似乎语句 getchar(); 应该丢弃换行符。但是,这仅在用户输入采用预期格式时才有效,即换行符位于预期位置。如果用户没有输入字符或输入太多字符,则这不会总是有效。

对于基于行的输入,我建议您使用函数 fgets 而不是 scanf/getchar,因为函数 fgets 总是在一次读取一行时间(假设缓冲区足够大以存储整行)。您可能需要阅读以下内容:A beginners' guide away from scanf()


一般来说,声明一个只有一个成员的数组是没有意义的。因此,将 com 声明为简单的 char 而不是 char 的数组可能更有意义。


下面的代码有点麻烦:

if (com[0] == 'e' || com[0] == 'E')
{
    [...]
}
else
{
    if (com[0] == 'u' || com[0] == 'U')
    {
        [...]
    }
    if (com[0] == 'd' || com[0] == 'D')
    {
        [...]
    }
    if (com[0] == 'r' || com[0] == 'R')
    {
        [...]
    }
    if (com[0] == 'l' || com[0] == 'L')
    {
        [...]
    }
    if (com[0] == 'w' || com[0] == 'W')
    {
        [...]
    }
    if (com[0] == 'p' || com[0] == 'P')
    {
        [...]
    }
}

可以简化为:

switch ( toupper( (unsigned char)com[0] ) )
{
    case 'E':
        [...]
        break;
    case 'U':
        [...]
        break;
    case 'D':
        [...]
        break;
    case 'R':
        [...]
        break;
    case 'L':
        [...]
        break;
    case 'W':
        [...]
        break;
    case 'P':
        [...]
        break;
    default:
        fprintf( stderr,"unexpected error!\n" );
        exit( EXIT_FAILURE );
}

以下代码有误:

if (!strcmp(compass,"westm"))
{
    strncpy(compass,"south",6);
}
if (!strcmp(compass,"south"))
{
    strncpy(compass,"eastm","eastm"))
{
    strncpy(compass,"north","north"))
{
    strncpy(compass,"westm",6);
}

例如,如果 compass 包含字符串 "westm",那么第一个 if 块会将字符串更改为 "south"。但是现在第二个 if 块的条件为真,所以第二个 if 块会将其更改为 "eastm"。现在第三个 if 块的条件为真,因此第三个 if 块将其更改为 "north"。现在第四个 if 块的条件为真,所以第四个 if 块将把它改回 "westm"。这样,您将完成一个完整的轮换。这可能不是您想要的。

为了打破这个链条,你应该在每个 else 语句之前添加一个 if,第一个 if 语句除外:

if (!strcmp(compass,6);
}
else if (!strcmp(compass,6);
}

然而,与将方向 (compass) 存储为字符串相比,将其存储为 enum 会更有效,如下所示:

enum direction
{
    DIRECTION_NORTH,DIRECTION_SOUTH,DIRECTION_WEST,DIRECTION_EAST
};

这样,您可以简单地编写以下内容,而不是编写一系列 if/else if 语句(假设 compass 是一个 int 而不是字符串) :

switch ( compass )
{
    case DIRECTION_WEST:
        compass = DIRECTION_SOUTH;
        break;
    case DIRECTION_SOUTH:
        compass = DIRECTION_EAST;
        break;
    case DIRECTION_EAST:
        compass = DIRECTION_NORTH;
        break;
    case DIRECTION_NORTH:
        compass = DIRECTION_WEST;
        break;
    default:
        fprintf( stderr,"unexpected error!\n" );
        exit( EXIT_FAILURE );
}

这更有效的原因是计算机在处理数字方面比字符串更好。

本文链接:https://www.f2er.com/7859.html

大家都在问