C 如何让我的代码在一行上输入数字,并用空格分隔,然后输出非重复数字的平均值?

C 如何让我的代码在一行上输入数字,并用空格分隔,然后输出非重复数字的平均值?,c,C,我的代码: #include <stdio.h> int main() { int count = 0; int size = 0; float num[size]; int i = 0; float avg = 0; float sum = 0; while (scanf("%f",&num) != EOF) { if ((num[i] != num[i+1]) &&

我的代码:

#include <stdio.h>

int main()
{
    int count = 0;

    int size = 0;
    float num[size];

    int i = 0;

    float avg = 0;
    float sum = 0;


    while (scanf("%f",&num) != EOF)
    {
        if ((num[i] != num[i+1]) && (num[i] != num[i-1]))
        {
            sum = sum + num[i];
            size++;
        }
        }
    avg = sum/size;
    printf("%0.2f", avg);
}
正确的输入和输出:

//input
2
2
1
^Z
//output
1.67
2 2 1
^Z
1.50

我的问题: 1) 如何使代码在一行上提示输入所有数字,并在每个输入之间用空格分隔?现在,我的代码总是在输入一个数字后开始一个新行


2) 如何修复代码,使其只计算非重复数字的平均值?(注意:我的代码的运行速度必须不低于O(nlogn)。)因此我不能使用嵌套循环,因为它的运行时间将为O(n^2)

您的代码中有一些问题:

  • num
  • 在scanf上测试
  • 已经使用的数字的测试

num
当你写作时

int size = 0;
float num[size];
您不分配内存来存储数字

不正确,因为您没有将读取的值存储到浮点中:
gcc
警告:

warning: format ‘%f’ expects argument of type ‘float *’, but argument 2 has type ‘float (*)[(sizetype)(size)]’ [-Wformat=] 
更正确的方法是写:

float num; 
...
while (scanf("%f",&num) != EOF)
在scanf上测试

您测试了
scanf
不会返回
EOF
,但是如果您没有给出一个数字,那么转换失败怎么办

测试用户提供的内容的正确方法是检查您是否有所需的转换次数:

while (scanf("%f",&num) == 1)
已经使用的数字的测试。 书写

if ((num[i] != num[i+1]) && (num[i] != num[i-1]))
您根据过去和未来的数字(?)测试最后一个数字(
i

您有一个更简单的方法:使用一个数组来存储已经得到的数字。这意味着有一个函数来测试一个已经得到的数字

警告当前的
实现是\u数组中的\u number\u
它非常幼稚,使您的程序在O(n)中运行。您可以很容易地将其替换为一些二分法搜索,即O(logn)


因此,您的代码的更正版本可能是:

#include <stdio.h>

int is_number_in_array(float num, float *array, int size)
{
    for (int i =0; i < size; ++i)
    {
        if (num == array[i])
            return 1;
    }
    return 0;
}

#define MAX_NUMBER 50

int main(void)
{
    /* number of number read */
    int size = 0;

    /* number already read */
    float array[MAX_NUMBER] = {};

    /* currently read number */
    float num = 0;

    float avg = 0;
    float sum = 0;

    /* get next number, stop when a conversion failed */
    while (scanf("%f",&num) == 1)
    {
        /* test if number is already in array */
        if (! is_number_in_array(num, array, size )) {
            /* not in array: add it */
            array[size ++] = num;
            sum += num;
        }

        /* Add some test here to check that size is not as big as MAX_NUMBER */
    }

    avg = sum/size;
    printf("%0.2f", avg);

    return 0;
}
#包括
int是数组中的数字(float num,float*数组,int size)
{
对于(int i=0;i
这种方法将所有整数保存在一个数组中,只要它们尚未保存,以避免重复

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

int main()
{
    int bytes_read;
    int size = 1000;

    int i = 0;
    int amount = 0;
    int number = 0;
    // boolean flag to detect duplicate numbers.
    int duplicate = 0;

    int sum = 0;
    float unique_avg = 0;

    // Allocate char / int arrays on the heap.
    // These can be resized with realloc() if needed.
    char* string = (char *) malloc (size);
    int* unique_num = (int *) calloc (2 * size, 0);
    // Declare char pointers to be used will splitting the string.
    char* token; 
    char* rest = string;


    printf ("Please enter a string: ");
    bytes_read = getline (&string, &size, stdin);
    // In case getline fails to get the input.
    if (bytes_read == -1) {
        puts ("error!");

    }
    // getline() read input succesfully.
    else {
        // Iterate over all space separated string tokens.
        while ((token = strtok_r(rest, " ", &rest))){
            // Convert string token to number
            number = atoi(token);
            for(i = 0; i < 2 * size; ++i){
                if(number == unique_num[i]){
                    // Duplicate found.
                    duplicate = 1;
                    break;
                }
            }
            if(!duplicate){
                unique_num[amount] = number;
                ++amount;
            }
            // Restore value of duplicate for next iteration
            duplicate = 0;
        }
    }
    // Sum all unique numbers.
    for(i = 0; i < amount; ++i){
        sum += unique_num[i];
    }
    // Calculate the avg of unique numbers.
    // Float casting is required for the fractional part of the division.
    unique_avg = (float) sum / (float) (amount);
    // Print the average.
    printf("%f", unique_avg);
    return 0;
}

首先,将数字读入数组
nums
。设
n
为数组中的数字数。这可以在O(N)中完成。我把这个留给你

其次,使用O(nlogn)算法对数组进行排序。我把这个留给你

最后,我们可以通过简单地咨询邻居来识别重复项。棘手的部分是避免越界。访问
nums[-1]
nums[n]
将导致未定义的行为,因此我们必须避免这种情况

我们不需要向前看和向后看。我们想在第一次遇到数字时使用它,所以我们只需要回顾一下

别忘了确保我们至少有一个数字,因为我们不能被零除

if (!n) {
   fprintf(stderr, "Can't find the average of zero numbers.\n");
   exit(1);
}

float sum = 0;
size_t uniques = 0;

for (size_t i=0; i<n; ++i) {
   if (i > 0 && nums[i] == nums[i-1])
      continue;

   sum += nums[i];
   ++uniques;
}

float avg = sum/uniques;

假设没有重复的数字
是数组中的\u number\u
第一次调用时扫描0个元素,第二次调用时扫描1个元素,第三次调用时扫描2个元素,依此类推。因此我们有O(0+1+2+…+(N-1))=O((N-1)*N/2)=O(N^2)性能。OP应该提供一个O(N logn)算法。@ikegami你是对的,我在我的答案中写了一个注释来说明这一点。在我看来,在全速运行之前,代码必须按照要求执行。只有在那之后,你才能尝试加速它。因为这是一个家庭作业,所以我留下了一个可以实现这个技巧的提示(二分法是O(logn),所以一旦函数改变,整个程序将是O(nlogn)。我的代码中的另一个限制是存储以前的数字的静态数组,但是再次强调,最好从小数组开始。Re“在全速运行之前,代码必须执行要求的操作”。但是在实现代码之前,必须选择正确的算法。我们这里不是在谈论微观优化。整个代码都需要替换。这让我头疼,为什么编码会这样hard@ikegami是的,但这仍然是一个家庭作业。至少现在OP有了正确的结果,需要考虑如何实现第2点。在我看来,仅仅给出完整的答案并不能帮助他理解正在发生的事情,而且我真的希望他的老师在指定具有特定复杂性阈值的问题之前,向他解释算法的各种时间复杂性(或者至少介绍最常见的算法,如各种算法),但是对于这N个标记中的每一个,您都会搜索所有的unique_num。这种方法本质上是不正确的。@ikegami确实,op必须在代码的这一小部分中使用排序方法,以获得更好的复杂性。我认为这对他/她来说是一个很好的学习机会。Re“确实,op必须使用排序方法”,还有其他选择。一个好的哈希表实际上是O(1)插入/查找的摊销,所以你可以得到O(N)@ikegami,我想他/她可以实现他/她自己的哈希表作为练习;)malloc和calloc doComments不用于扩展讨论的内容;此对话已结束。为什么需要对数组进行排序?为什么我不能检查是否存在重复项,然后忽略重复项并添加非重复项并除以count@Patr
Please enter a string: 2 2 1                                                                                                                                                       
1.500000
if (!n) {
   fprintf(stderr, "Can't find the average of zero numbers.\n");
   exit(1);
}

float sum = 0;
size_t uniques = 0;

for (size_t i=0; i<n; ++i) {
   if (i > 0 && nums[i] == nums[i-1])
      continue;

   sum += nums[i];
   ++uniques;
}

float avg = sum/uniques;
@nums
   or die("Can't find the average of zero numbers.\n");

my %seen;      # Hash table.
my $sum = 0;
my $uniques = 0;
for my $num (@nums) {
   next if $seen{$num}++;

   $sum += $num; 
   ++$uniques;
}

my $avg = $sum/$uniques;