【问题标题】:Unable to get rid of errors even after using the right headers即使使用正确的标题也无法摆脱错误
【发布时间】:2018-08-01 21:39:20
【问题描述】:

我刚开始学习如何用 C 编程,我无法摆脱错误。这是我的程序:

/* This program rolls two dice and presents the total. It then asks the user 
to guess if the next total will be higher, lower, or equal. It then rolls 
two more dice and tells the user how they did. */

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

int main(void)
{
    int  dice1, dice2, total, total1= 0;
    char ans[25], dans[25];
    char higher[] = "HIGHER", lower[] = "LOWER", equal[] = "EQUAL";

    //the following 3 lines, throws the dice and adds them. 
    dice1 = (rand() % 5) + 1;
    dice2 = (rand() % 5) + 1;
    total = dice1 + dice2;

    //the next few ask the question. 
    printf("Will the next number be higher, lower or equal to %d ?\n", total);
    puts("Type higher, lower or equal.");
    // scanf("&s", ans); //had to remove this line, because apparently we can't use &s to get the string input

    fgets(ans, 25, stdin);
    strcpy(dans, strupr(ans));

    //the next few throw the dice two more times
    dice1 = (rand() % 5) + 1;
    dice2 = (rand() % 5) + 1;
    total1 = dice1 + dice2;

    /*All of these check if the user input matches the actual output and 
    then tells the user if he/she was right.*/
    printf("The upper string is %s.\n", ans);
    if ((ans == higher) && (total1 > total))
    {
        printf("You're right, it is higher!\n");
    }
    else if ((ans == lower) && (total1 < total))
    {
        printf("You're right, it is lower!\n");
    }
    else if ((ans == equal) && (total1 = total))
    {
        printf("You're right. they are equal!\n");
    }
    else
    {
        printf("Your prediction was wrong.\n");
    }



}

我得到的错误:

test.c:25:22: 错误:函数“strupr”的隐式声明在 C99 中无效 [-Werror,-Wimplicit-function-declaration]

   strcpy(dans, strupr(ans));

                 ^

test.c:25:22: 错误:不兼容的整数到指针转换将“int”传递给“const char *”类型的参数 [-Werror,-Wint-conversion]

   strcpy(dans, strupr(ans));

                 ^~~~~~~~~~~

/usr/include/string.h:129:70:注意:在此处将参数传递给参数“__src” extern char *strcpy (char *__restrict __dest, const char *__restrict __src)

                                                                ^

test.c:33:18: 错误:数组比较总是评估为假 [-Werror,-Wtautological-compare]

   if ((ans == higher) && (total1 > total))

           ^

test.c:37:23: 错误:数组比较总是评估为假 [-Werror,-Wtautological-compare]

   else if ((ans == lower) && (total1 < total))

              ^

test.c:41:23: 错误:数组比较总是评估为假 [-Werror,-Wtautological-compare]

   else if ((ans == equal) && (total1 = total))

请帮助我解决错误。

还有,

  1. strupr 应该在stdlib 中,为什么我仍然收到错误消息?

  2. 当我将字符串转换为大写字符串时,它如何变为 int?

  3. 为什么我不能在scanf 中使用%s? (我以前用过这个)

谢谢。

【问题讨论】:

  • strupr() 不是标准的 C 函数,尽管我相信它可以在 MS C 中找到。因为它没有被声明,C 编译器假定它返回一个 int,它是'不适合strcpy() 的参数。其余的问题似乎是因为您没有使用strcmp() 来比较字符串。您还需要处理 fgets() 在输入数据中保留的换行符。
  • 检查字符串是否相等,使用strcmp
  • ans == higher 不是比较字符串的正确方法。 anshigher 是指向两个不同数组的指针。这些指针永远不会相等。你应该使用strcmp(ans, higher)。而且 C 中没有标准函数可以将字符串转换为大写。
  • 这看起来很糟糕:(total1 = total)) 。不是警告的原因,但可能不是你想要的。 PS:去掉所有多余的()。 if (a > b || c b) || (c

标签: c c-strings


【解决方案1】:

[回答这个多问问题的一个问题]

为什么我不能在 scanf 中使用 %s?

你可以,但实际上你使用&amp;s

  // scanf("&s", ans); //had to remove this lin

%s不同。

【讨论】:

    【解决方案2】:

    [回答这个多问题的另一个问题]

    error: implicit declaration of function 'strupr' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    

    上面的消息告诉你编译器在这一行第一次看到strupr。所以它“隐式声明它。不知道更好的是它假设这个函数返回int。这样做是C标准规定的。

    所以下次编译器看到strupr() 时会返回一个int 并发出警告

    error: incompatible integer to pointer conversion passing 'int' to parameter of type 'const char *' [-Werror,-Wint-conversion]
    

    告诉你 int 作为第二个参数传递给 strcpy() 不是预期的。

    所有这些都表明您使用的 C 实现不提供名为 strupr() 的函数。这很好,因为C 标准知道这个函数

    您可以通过滚动自己的方式来解决此问题,例如:

    char * strupr(char * s)
    {
      assert(s);
    
      char * pc = s;
      while (*pc)
      {
        *pc = toupper(*pc); /* toupper() requires <ctype.h> */
        ++pc;
      }
    
      return s;
    }
    

    【讨论】:

      【解决方案3】:

      您有许多问题需要解决。您对strupr 的使用不是标准的C 函数,可能仅在windoze 上可用。您的标准替代方法是编写一个短函数,并使用标题 &lt;ctype.h&gt; 中的函数 isupper()islower() 循环遍历每个字符,如果从小写变为大写,则调用 toupper()是必需的。

      一个简短的函数可以非常有效地为您完成所有这些工作。比如:

      /** convert string to uppercase.
       *  returns string with all chars converted to uppercase.
       */
      char *str2upper (char *str)
      {
          if (!str) return NULL;
      
          char *p = str;
      
          for ( ; *p; p++)
              if ('a' <= *p && *p <= 'z')
                  *p += 'A' - 'a';
      
          return str;
      }
      

      就是你所需要的。它只是遍历作为输入提供的字符串,如果字符是小写,则将其转换为大写。

      您的下一个问题是如何处理由fgets 填充的缓冲区。作为一个面向行的输入函数,它将读取并包含输入末尾的'\n',包括asn中的最后一个字符.现在,无论您如何处理转化,dans 永远不会匹配 higherlowerequal -- 你知道为什么了吗?

      让我们看看你的“更高”

      'H','I','G','H','E','R'
      

      现在让我们看看 dans 是否包含相同的单词(但 '\n' 字符仍然悬在末尾):

      'H','I','G','H','E','R','\n'
      

      由于您使用fgets 阅读并且没有删除尾随的'\n',因此它将始终阻止dand 与您的任何字符串之间的有效比较。如何解决?

      简单,只需检查ans 中由fgets 填充的最后一个字符是否是'\n',然后用一个以nul 结尾的字符删除它来覆盖'\n'。 (此外,您应该通过生成手动EOF 提前退出来检查用户是否没有取消输入。您可以在一个简单的小输入循环中执行所有这些操作,同时要求您的用户输入一个有效的字符串,直到他这样做或决定取消,例如

          if (!fgets (ans, 25, stdin)) {  /* check for user cancle with EOF */
              fprintf (stderr, "user canceled input.\n");
              return 1;
          }
          size_t len = strlen (ans);          /* get string length */
          if (len && ans[len - 1] == '\n')    /* valisate last char is '\n' */
              ans[--len] = 0;                 /* overwrite with nul-character */
          else    /* warn if chars can remain unread (input too long) */
              fprintf (stderr, "unread characters may remain in stdin.\n");
      
          strcpy(dans, str2upper(ans));
      

      现在dans 是正确的大写字母,并且没有'\n' 在其尾部悬空。

      您的比较是最后一个问题领域。您无法使用 == 运算符检查字符串是否相等。 (用于一次比较一个字符,而不是字符串。string.h 中的 strcmp 函数是这里的合适工具。如果字符串比较相等,strcmp 返回 0。考虑到这一点,您可以修正你的比较:

          /*All of these check if the user input matches the actual output and 
          then tells the user if he/she was right.*/
          printf("The upper string is %s.\n", ans);
          if (strcmp (dans, higher) == 0 && (total1 > total))
          {
              printf("You're right, it is higher!\n");
          }
          else if (strcmp (dans, lower) == 0 && (total1 < total))
          {
              printf("You're right, it is lower!\n");
          }
          else if (strcmp (dans, equal) == 0 && (total1 == total))
          {
              printf("You're right. they are equal!\n");
          }
          else
          {
              printf("Your prediction was wrong.\n");
          }
      

      现在总而言之,您的代码应该可以工作,例如

      #include<stdio.h>
      #include<stdlib.h>
      #include<string.h>
      
      /** convert string to uppercase.
       *  returns string with all chars converted to uppercase.
       */
      char *str2upper (char *str)
      {
          if (!str) return NULL;
      
          char *p = str;
      
          for ( ; *p; p++)
              if ('a' <= *p && *p <= 'z')
                  *p += 'A' - 'a';
      
          return str;
      }
      
      int main(void)
      {
          int  dice1, dice2, total, total1= 0;
          char ans[25] = {0}, dans[25] = {0};
          char higher[] = "HIGHER", lower[] = "LOWER", equal[] = "EQUAL";
      
          //the following 3 lines, throws the dice and adds them. 
          dice1 = (rand() % 5) + 1;
          dice2 = (rand() % 5) + 1;
          total = dice1 + dice2;
      
          //the next few ask the question. 
          printf("Will the next number be higher, lower or equal to %d ?\n", total);
          fputs ("Type higher, lower or equal: ", stdout);
      
          if (!fgets (ans, 25, stdin)) {  /* check for user cancle with EOF */
              fprintf (stderr, "user canceled input.\n");
              return 1;
          }
          size_t len = strlen (ans);          /* get string length */
          if (len && ans[len - 1] == '\n')    /* valisate last char is '\n' */
              ans[--len] = 0;                 /* overwrite with nul-character */
          else    /* warn if chars can remain unread (input too long) */
              fprintf (stderr, "unread characters may remain in stdin.\n");
      
          strcpy(dans, str2upper(ans));
      
          //the next few throw the dice two more times
          dice1 = (rand() % 5) + 1;
          dice2 = (rand() % 5) + 1;
          total1 = dice1 + dice2;
      
          /*All of these check if the user input matches the actual output and 
          then tells the user if he/she was right.*/
          printf("The upper string is %s.\n", ans);
          if (strcmp (dans, higher) == 0 && (total1 > total))
          {
              printf("You're right, it is higher!\n");
          }
          else if (strcmp (dans, lower) == 0 && (total1 < total))
          {
              printf("You're right, it is lower!\n");
          }
          else if (strcmp (dans, equal) == 0 && (total1 == total))
          {
              printf("You're right. they are equal!\n");
          }
          else
          {
              printf("Your prediction was wrong.\n");
          }
      }
      

      使用/输出示例

      $ ./bin/rolldice
      Will the next number be higher, lower or equal to 6 ?
      Type higher, lower or equal: lower
      The upper string is LOWER.
      You're right, it is lower!
      

      查看一下,如果您还有其他问题,请告诉我。

      【讨论】:

        猜你喜欢
        • 2021-01-22
        • 2021-06-23
        • 2021-06-09
        • 1970-01-01
        • 2011-03-07
        • 2020-01-31
        • 2011-08-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多