为什么我的代码给了我非常大的平均值?

时间:2015-07-26 21:13:27

标签: c string

我正在制作一个课程代码,用于计算多达50个家庭成员的平均年龄,并显示居住在德克萨斯州的人的姓名。但每当我在Ideone上使用代码时,它给了我像“1098907648.000000”这样荒谬的数字,并且不显示任何德州人!我似乎无法理解什么是错的。我知道这是一个广泛的问题,但任何帮助将不胜感激!

// C code
// This program will calculate the average age of an inputted Family and display the number of members in texas.
#include <stdio.h>
#include <string.h>

/* Function for average age */
float average(float num1, int num2)
  {
    return num1/num2;
  }

int main ()
{
    const char texans;
    char familymember[50];
    char state, texas;
    float avg, sum; 
    int age, members;
    {
      printf("Enter family member or type end to output data when finished. \n");
       {
         scanf("%s", familymember);
         if (familymember !=  "end")
           {
            members = members + 1;
            printf("Enter age \n");
            scanf("%f", &age);
            sum = sum + age;
            printf("Enter state \n");
            scanf("%s", &state);
            if (state == "Texas")
            {
              strcpy(texans, familymember);
            }
           }
         if (familymember ==  "end");
           {
             // fuction call
             avg = average(sum, members);
             printf("The average age of all family member's is %f and the number of family members currently residing in texas are %s\n", avg, texans);
           }
       }
     }
   return 0;
}

2 个答案:

答案 0 :(得分:5)

此代码存在许多问题。

  1. 在C中,必须在使用其值之前初始化变量。与其他一些语言不同,变量 默认为零或任何此类值 - 它们以未定义状态开头。

  2. 在C中,将字符串与==进行比较可能无法达到预期效果。这将检查两个字符指针是否指向同一位置。相反,您可能希望使用strcmp,它接受​​两个字符串,如果相等则返回0

  3. 如果您希望后续;开始)的正文,请不要在if {之后加if。如果包含分号,将始终执行'body',因为;取代了正文。

  4. 您将scanf字符串放入固定大小的缓冲区中。你没有防止溢出缓冲区的保护措​​施。这是一个安全漏洞,可能导致远程执行代码。

  5. 目前还不清楚你对strcpy(texans, familymember)的意图,但几乎肯定是不对的。您可能打算将texans int初始化为0并且当前有strcpy,您可能需要使用++texans;行。

  6. ......还有其他问题,正如其他人在评论中指出的那样。帮自己一个忙,自己编译代码。对于GCC-like,我推荐这些编译选项:

    -std=c99 -Werror -Wall -Wextra -pedantic
    

    这样做,我收到了这些错误:

    /tmp/31642023.c:23:27: error: result of comparison against a string literal is
          unspecified (use strncmp instead) [-Werror,-Wstring-compare]
             if (familymember !=  "end")
                              ^   ~~~~~
    /tmp/31642023.c:27:25: error: format specifies type 'float *' but the argument
          has type 'int *' [-Werror,-Wformat]
                scanf("%f", &age);
                       ~~   ^~~~
                       %d
    /tmp/31642023.c:31:23: error: result of comparison against a string literal is
          unspecified (use strncmp instead) [-Werror,-Wstring-compare]
                if (state == "Texas")
                          ^  ~~~~~~~
    /tmp/31642023.c:31:23: error: comparison between pointer and integer
          ('int' and 'char *') [-Werror]
                if (state == "Texas")
                    ~~~~~ ^  ~~~~~~~
    /tmp/31642023.c:33:22: error: incompatible integer to pointer conversion passing
          'const char' to parameter of type 'const void *'
          [-Werror,-Wint-conversion]
                  strcpy(texans, familymember);
                         ^~~~~~
    /tmp/31642023.c:33:22: error: incompatible integer to pointer conversion passing
          'const char' to parameter of type 'const void *'
          [-Werror,-Wint-conversion]
                  strcpy(texans, familymember);
                         ^~~~~~
    /tmp/31642023.c:33:22: error: incompatible integer to pointer conversion passing
          'const char' to parameter of type 'char *' [-Werror,-Wint-conversion]
                  strcpy(texans, familymember);
                         ^~~~~~
    /tmp/31642023.c:33:22: error: incompatible integer to pointer conversion passing
          'const char' to parameter of type 'char *' [-Werror,-Wint-conversion]
                  strcpy(texans, familymember);
                         ^~~~~~
    /tmp/31642023.c:36:27: error: result of comparison against a string literal is
          unspecified (use strncmp instead) [-Werror,-Wstring-compare]
             if (familymember ==  "end");
                              ^   ~~~~~
    /tmp/31642023.c:36:37: error: if statement has empty body [-Werror,-Wempty-body]
             if (familymember ==  "end");
                                        ^
    /tmp/31642023.c:36:37: note: put the semicolon on a separate line to silence
          this warning
    /tmp/31642023.c:40:144: error: format specifies type 'char *' but the argument
          has type 'char' [-Werror,-Wformat]
      ...of family members currently residing in texas are %s\n", avg, texans);
                                                           ~~          ^~~~~~
                                                           %c
    /tmp/31642023.c:16:17: error: unused variable 'texas'
          [-Werror,-Wunused-variable]
        char state, texas;
                    ^
    /tmp/31642023.c:28:19: error: variable 'sum' is uninitialized when used here
          [-Werror,-Wuninitialized]
                sum = sum + age;
                      ^~~
    /tmp/31642023.c:17:19: note: initialize the variable 'sum' to silence this
          warning
        float avg, sum; 
                      ^
                       = 0.0
    /tmp/31642023.c:25:23: error: variable 'members' is uninitialized when used here
          [-Werror,-Wuninitialized]
                members = members + 1;
                          ^~~~~~~
    /tmp/31642023.c:18:21: note: initialize the variable 'members' to silence this
          warning
        int age, members;
                        ^
                         = 0
    /tmp/31642023.c:40:144: error: variable 'texans' is uninitialized when used here
          [-Werror,-Wuninitialized]
      ...of family members currently residing in texas are %s\n", avg, texans);
                                                                       ^~~~~~
    /tmp/31642023.c:14:22: note: initialize the variable 'texans' to silence this
          warning
        const char texans;
                         ^
                          = '\0'
    15 errors generated.
    

    至少,修复其中的每一个。

答案 1 :(得分:2)

    int age, members;
    {
      printf("Enter family member or type end to output data when finished. \n");
       {

你不需要那些内部块。您可以简单地删除这两个大括号({)。或者你忘记在这里写一个循环?它看起来好像你希望内部代码多次运行。

         if (familymember !=  "end")

您无法在C中将字符串与!=进行比较。此行将比较内存地址,这不是您想要的。请改用strcmp(familymember, "end") != 0

            members = members + 1;
此时

members未初始化。您应该将其定义更改为int members = 0

            scanf("%f", &age);

ageintscanf %f需要float。您可能需要scanf("%d", &age)

            sum = sum + age;

您尚未初始化sum。您应该将其定义更改为float sum = 0.0

            scanf("%s", &state);

scanf %s将字符串读入char个数组。在这里,您可以指向单个char。这会破坏随机存储器。您应该将state数组设为familymember(然后删除&)。

            if (state == "Texas")

你的编译器应该抱怨这个。您正在尝试将state(这是一个整数)与"Texas"(评估为指针)进行比较。将state更改为数组后,您应该再次使用strcmp

              strcpy(texans, familymember);

与上述相同的问题:您将texans(整数)视为指针。看起来您打算将texans作为一个计数,在这种情况下,它应该是int(绝对不是const)。

         if (familymember ==  "end");

与上述问题相同:使用strcmp比较字符串。此外,尾随;是错误的,应该删除。有了它,您可以有效地创建一个空体的if语句:

         if (familymember ==  "end")
             ;
         ...

此外,这个条件可以简单地用else替换。

             printf("The average age of all family member's is %f and the number of family members currently residing in texas are %s\n", avg, texans);

texans更改为int后,%s应变为%d。此外,member's错误,应为members

如果这应该是一个循环,你应该在此时停止它(如"end"暗示的那样)。你可能想要break;