即使使用正确的方法也无法摆脱错误 headers

Unable to get rid of errors even after using the right headers

我刚开始学习如何用 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: error: implicit declaration of function 'strupr' is invalid in C99 [-Werror,-Wimplicit-function-declaration]

   strcpy(dans, strupr(ans));

                 ^

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

   strcpy(dans, strupr(ans));

                 ^~~~~~~~~~~

/usr/include/string.h:129:70: note: passing argument to parameter '__src' here extern char *strcpy (char *__restrict __dest, const char *__restrict __src)

                                                                ^

test.c:33:18: error: array comparison always evaluates to false [-Werror,-Wtautological-compare]

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

           ^

test.c:37:23: error: array comparison always evaluates to false [-Werror,-Wtautological-compare]

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

              ^

test.c:41:23: error: array comparison always evaluates to false [-Werror,-Wtautological-compare]

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

请帮我解决错误。

此外,

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

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

  3. 为什么我无法在 scanf 中使用 %s? (这个我用过)

谢谢。

[回答这个 multi-question 问题的一个问题]

Why am I not able to use %s in scanf?

可以,但实际上你用的是&s

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

%s 不同。

[回答这个 multi-question 问题的另一个问题]

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

上面的消息告诉您编译器在这一行中第一次看到 strupr。所以它“隐含地声明了它。不知道它假设了这个函数 returns int。C 标准要求这样做。

所以下一次编译器看到 strupr() 时会转到 return 和 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;
}

您有许多问题需要解决。您对 strupr 的使用不是标准的 C 函数,可能仅在 windoze 上可用。您的标准替代方法是编写一个短函数,然后使用 header <ctype.h> 中的函数 isupper()islower() 遍历每个字符并调用 toupper() 如果需要从 lower-case 更改为 upper-case。

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

/** 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 填充的缓冲区。作为 line-oriented 输入函数,它将 读取并包括 输入末尾的 '\n',将其作为您在 asn 中的最终角色。现在,无论您如何处理转换,dans 永远不会匹配 higherlowerequal - 您知道为什么了吗?

让我们看看你的“更高”

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

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

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

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

很简单,只需检查 fgets 填充的 ans 中的最后一个字符是 '\n' 并用 nul-terminating 覆盖 '\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' 从其 tail-end 悬垂下来。

您的比较是最后一个问题区域。您不能使用 == 运算符检查字符串是否相等。 (这是一次比较一个字符,而不是一个字符串。string.h 中的 strcmp 函数是这里的合适工具。如果字符串比较相等,strcmp returns 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");
    }
}

例子Use/Output

$ ./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!

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