即使在使用正确的标题后也无法消除错误

时间:2018-02-22 06:01:41

标签: c c-strings

我刚开始学习如何用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:错误:隐含的函数声明&#39; strupr&#39;在C99中无效[-Werror,-Wimplicit-function-declaration]

   strcpy(dans, strupr(ans));

                 ^
     

test.c:25:22:错误:不兼容的整数到指针转换传递&#39; int&#39;参数类型&#39; const char *&#39; [-Werror,-Wint转换]

   strcpy(dans, strupr(ans));

                 ^~~~~~~~~~~
     

/usr/include/string.h:129:70:注意:将参数传递给参数&#39; __ src&#39;这里   extern char * strcpy(char * __ restrict __dest,const char * __ restrict __src)

                                                                ^
     

test.c:33:18:错误:数组比较总是计算为false [-Werror,-Wetutological-compare]

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

           ^
     

test.c:37:23:错误:数组比较总是计算为false [-Werror,-Wetutological-compare]

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

              ^
     

test.c:41:23:错误:数组比较总是计算为false [-Werror,-Wetutological-compare]

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

请帮我解决错误。

另外,

  1. strupr应该在stdlib中存在,我为什么还会收到错误?

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

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

  4. 谢谢。

3 个答案:

答案 0 :(得分:3)

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

  

为什么我无法在scanf中使用%s?

你可以,但事实上你使用&s

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

%s不一样。

答案 1 :(得分:2)

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

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

以上消息告诉您编译器在此行中第一次看到strupr。所以它&#34;隐含地声明它。不知道更好,它假设此函数返回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;
}

答案 2 :(得分:2)

您需要解决许多问题。您对strupr的使用不是标准的C函数,只能在windoze上使用。标准的替代方法是编写一个简短的函数,并使用标题isupper()中的函数islower()<ctype.h>循环遍历每个字符,如果更改则调用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的最终字符。 {1}}。现在,无论您如何处理转化,dans都永远不会与higherlowerequal匹配 - 您还能找出原因吗?

让我们看看你的'更高&#39;

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

现在让我们看看dans,如果它包含相同的单词(但'\n'字符仍悬而未决):

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

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

很简单,只需检查ans填充的fgets中的最后一个字符是否为'\n',并覆盖'\n'并删除nul-terminating字符。 (此外,您应该通过生成手动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'悬挂在它的尾端。

您的比较是最后一个问题区域。您无法使用==运算符检查字符串相等性。 (用于一次比较一个字符,而不是字符串。strcmp中的string.h函数是适当的工具。如果字符串比较相同,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!

仔细看看,如果您有其他问题,请告诉我。