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;