0

我正在尝试用 C 创建一个基本的绘图程序,我需要先输入图形,然后输入所述图形的坐标。我必须先输入图形,然后输入坐标,但是为了输入要传递给函数的特定图像的特定坐标,我必须做一个条件语句。我的代码是这样的

fgets(input,sizeof(input),stdin);
      if("\n"==input[strlen(input)-1]) // to remove '\n' from string
          input[strlen(input)-1]=='\0';
      if(strcmp(input,point)==0){
         scanf("%d %d",&x1,&y1);
         point(x1,y1); 
      }
      if(strcmp(input,rectangle)==0){
         scanf("%d %d",&x1,&y1,&x2,&y2);
         rectangle(x1,y1,x2,y2) // x1,y1 for top left coordinate x2,y2 for bottom right
      }

如果我运行代码并输入:

point // enter
12 13

它有效,但我必须像这样运行它:

point 12 13 // only one space in between those three inputs

我似乎不能那样运行它。输入图像应与输入坐标在同一行。我尝试使用scanf()thenif{ scanf() }但它不起作用。

有什么建议么?

4

2 回答 2

1

你不能用 == 比较字符串,你必须使用

strcmp(char *string1,char*string2)

你可以这样做:

char input[20];
int resul[4];
scanf("%s%d%d",input,&resul[0],&resul[1]);
if (input[0]=='r') scanf("%d%d",&resul[2],&resul[3]);
于 2013-09-02T13:59:23.223 回答
1

分析的代码开始于:

fgets(input,sizeof(input),stdin);
if("\n"==input[strlen(input)-1]) // to remove '\n' from string
    input[strlen(input)-1]=='\0';

您应该检查返回值,fgets()以便知道是否有input要分析的数据。

if应该是if (input[strlen(input)-1] == '\n'),测试字符而'\n'不是字符串"\n"*。您应该已经收到有关类型不匹配的编译器警告。如果您没有收到此类警告,请使用更好的编译器。如果您收到警告,请注意您的编译器;它比你更了解 C(并且不会仅仅为了好玩而生成警告)。

之后的赋值if需要一个单一=的而不是一个双重的==——你可能应该得到一个关于什么都不做的语句的警告。

* 我知道有些人推荐了这个订单if ('\n' == input[strlen(input)-1]),但对我来说并不好。该机制旨在防止条件中的==vs=错误。它是不完善的——例如,当 LHS 和 RHS 都是变量if (lhs = rhs)(伪装成任务)。

代码应该这样开始,因此:

if (fgets(input, sizeof(input), stdin) != 0)
{
    if (input[strlen(input)-1] == '\n')
        input[strlen(input)-1] = '\0';

我忽略了重复调用的“低效率” strlen();还有更大的问题需要担心。注意修改后的代码检查输入操作的结果;如果fgets()检测到 EOF 或错误并且您没有测试fgets().

然后代码的原始版本继续:

if(input == "point"){
   scanf("%d %d",&x1,&y1);
   point(x1,y1); 
}
if(input == "rectangle"){
   scanf("%d %d",&x1,&y1,&x2,&y2);
   rectangle(x1,y1,x2,y2) // x1,y1 for top left coordinate x2,y2 for bottom right
}

正如jambono在他的回答中正确指出的那样,这是行不通的;你不能像那样比较字符串。

不幸的是,重写是:

if(strcmp(input,point)==0){
   scanf("%d %d",&x1,&y1);
   point(x1,y1); 
}
if(strcmp(input,rectangle)==0){
   scanf("%d %d",&x1,&y1,&x2,&y2);
   rectangle(x1,y1,x2,y2) // x1,y1 for top left coordinate x2,y2 for bottom right
}

这也应该从编译器产生警告,因为字符串被更改为函数指针——编译器应该一直在抱怨将函数指针转换到const char *或附近。

正确的比较可能是:

if (strcmp(input, "point") == 0)
if (strcmp(input, "rectangle") == 0)

只要单词单独出现在一行上,这些数据就可以工作,并且数据在单独的一行中:

point
1 2
rectangle
2 3 4 5

为了便于阅读,在问题格式化之前回答

当然,第二个scanf()需要修复格式字符串,您应该始终测试它是否scanf()按预期工作:

if (scanf("%d %d %d %d", &x1, &y1, &x2, &y2) != 4)
    ...deal with error...

请注意,该scanf()调用将留下换行符,准备好被另一个调用读取为该行fgets()上唯一的字符(剩下的)。我认为您可能会通过第二次调用来更好fgets()地读取包含数据的行,然后用于sscanf()解析该行。

组装所有更改(使用scanf()):

if (fgets(input, sizeof(input), stdin) != 0)
{
    if (input[strlen(input)-1] == '\n')
        input[strlen(input)-1] = '\0';
    if (strcmp(input, "point") == 0)
    {
        if (scanf("%d %d",&x1,&y1) != 2)
            ...report format error and return/exit...
        point(x1, y1); 
    }
    else if (strcmp(input, "rectangle") == 0)
    {
        if (scanf("%d %d %d %d", &x1, &y1, &x2, &y2) != 4)
            ...report format error and return/exit...
        rectangle(x1, y1, x2, y2);
    }
    else
        ...unexpected input (format error)...
}

使用fgets()sscanf()

if (fgets(input, sizeof(input), stdin) != 0)
{
    if (input[strlen(input)-1] == '\n')
        input[strlen(input)-1] = '\0';
    if (strcmp(input, "point") == 0)
    {
        if (fgets(input, sizeof(input), stdin) == 0)
            ...report unexpected EOF and return/exit...
        if (sscanf(input, "%d %d",&x1,&y1) != 2)
            ...report format error and return/exit...
        point(x1, y1); 
    }
    else if (strcmp(input, "rectangle") == 0)
    {
        if (fgets(input, sizeof(input), stdin) == 0)
            ...report unexpected EOF and return/exit...
        if (sscanf(input, "%d %d %d %d", &x1, &y1, &x2, &y2) != 4)
            ...report format error and return/exit...
        rectangle(x1, y1, x2, y2);
    }
}

请注意,在使用 的示例中fgets(),您拥有可以向用户报告的整行输入,这对于他们来说可能比在scanf()阅读了某些行并拒绝转换其余行之后找到剩下的内容更容易。例如,如果输入是:

rectangle
10 10 2O 22

O转换将在( 应该是 a )上失败0,但是您可以从输入中收集到的唯一信息以向用户报告是O 22,这可能不如能够显示整行有用。

为了便于阅读,问题被格式化后回答

输入是单行:

point 1 1
rectangle 1 0 0 1

在这种情况下,您不能使用scanf()来获取数字(因为fgets()已经阅读了整行),因此您将需要使用sscanf()并且不需要第二次调用fgets(). 但是,您必须修改比较代码以及对sscanf(). 我会创建一个小函数来检查给定字符串是否是另一个字符串的前缀:

int str_prefix(const char *haystack, const char *needle)
{
    return strncmp(haystack, needle, strlen(needle)) == 0;
}

如果needle可以在 的开头找到,则返回 true haystack。如果您有 C99 或更高版本的编译器,则可以使用static inline(并且可以明智地将返回类型更改为boolor _Bool)对其进行限定。

if (fgets(input, sizeof(input), stdin) != 0)
{
    if (input[strlen(input)-1] == '\n')
        input[strlen(input)-1] = '\0';
    if (str_prefix(input, "point "))
    {
        if (sscanf(input, "point %d %d",&x1,&y1) != 2)
            ...report format error and return/exit...
        point(x1, y1); 
    }
    else if (str_prefix(input, "rectangle "))
    {
        if (sscanf(input, "rectangle %d %d %d %d", &x1, &y1, &x2, &y2) != 4)
            ...report format error and return/exit...
        rectangle(x1, y1, x2, y2);
    }
}

请注意“针”字符串上的尾随空格。这可以防止您将“尖锐的评论”误解为“点”线的开始。

您可以在关键字之后开始搜索,而不是使用关键字开始格式字符串sscanf()

if (sscanf(&input[sizeof("rectangle")], "%d %d %d %d", &x1, &y1, &x2, &y2) != 4)
于 2013-09-02T15:00:29.067 回答