为什么会这样?

问题描述 投票:0回答:4

这是我写的代码:

#include<stdio.h>

#define STARHEAD "*******************************************************\n"
#define SHOWHEAD "           Show information for all students           \n"
#define SORTHEAD "      Output from high to low according to grades      \n"
#define WRAPHEAD "\n"

struct Student {
    int number;
    char name[15];
    int score;
};

struct Student student[10] = {
    {8, "imz", 84},
    {30, "pzh", 30},
    {28, "xhx", 88},
    {51, "vbi", 81},
    {35, "spe", 91},
    {14, "apm", 77},
    {7, "lyv", 71},
    {9, "fey", 87},
    {16, "uvv", 100},
    {42, "aap", 67}
};

void show();
void sort();

void show()
{
    int n;
    printf(STARHEAD);
    printf(SHOWHEAD);
    printf(STARHEAD);
    for (n = 0; n < 10; n++) {
        printf("number:%2d name:%s score:%d\n", student[n].number, student[n].name, student[n].score);
    }
    printf(WRAPHEAD);
}

void sort()
{
    int i, j, h, k;
    struct Student temp;
    printf(STARHEAD);
    printf(SORTHEAD);
    printf(STARHEAD);
    for (i = 0; i < 9; i++) {
        k = i;
        for (j = i + 1; j < 10; j++) {
            if (student[k].score < student[j].score) {
                k = j;
                temp = student[i];
                student[k] = temp;
                student[i] = student[k];
            }
        }
    }
    for (h = 9; h >= 0; h--) {
        printf("number:%d name:%s score:%d\n", student[h].number, student[h].name, student[h].score);
    }
}

int main()
{
    show();
    sort();
    return 0;
}

本以为程序的输出是根据成绩来的,结果和我预想的不一样。这段代码我想了很久。很明显,逻辑上没有错误,和书上的源码差不多,但是结果并不能像我预想的那样输出

c windows structure dev-c++
4个回答
1
投票

首先,交换的算法是错误的。你的算法

temp = student[i];
student[k] = temp;
student[i] = student[k];

相当于

student[k] = student[i];

你应该做的:

temp = student[i];
student[i] = student[k];
student[k] = temp;

其次,排序的算法是错误的。您可以执行排序,例如,通过固定一个位置来比较和存储最大(或最小)元素。

可以这样实现:

for (i = 0; i < 9; i++) {
    for (j = i + 1; j < 10; j++) {
        // move largest element to the front of current range
        if (student[i].score < student[j].score) {
            temp = student[i];
            student[i] = student[j];
            student[j] = temp;
        }
    }
}
// print from high score to low score
for (h = 0; h < 10; h++) {
    printf("number:%d name:%s score:%d\n", student[h].number, student[h].name, student[h].score);
}

1
投票

快速浏览一下您的代码,这些行让我印象深刻:

temp = student[i];
student[k] = temp;
student[i] = student[k];

看来您正在将

temp
设置为
student[i]
。然后,以下行将
student[k]
设置为
temp
,等于
student[i]
。最后,您将
student[i]
设置为
student[k]
,等于
student[i]

有效地你这样做:

student[i] = student[i]

我相信你想要的是这个:

temp = student[i];
student[i] = student[k];
student[k] = temp;

这将有效地交换

student[k]
student[i]
的值。至少这是我最好的猜测,我不知道你得到的输出到底是什么,或者你期望的输出是什么。


1
投票

让我们看看你交换学生的三行:

            temp = student[i];
            student[k] = temp;
            student[i] = student[k];

您首先指定

temp
与学生
i
相同,因此
temp
i
相同而
k
不同。然后你将学生
k
设置为与
temp
相同。在这一点上,他们三个都是一样的。

尝试交换两行:

            student[k] = temp;
            student[i] = student[k];

致:

            student[i] = student[k];
            student[k] = temp;

接下来在交换上方的检查中,您使用

k
作为其中一名学生的索引,并且该
k
值已设置为
i
的值,但
k
在检查中重新分配,以供使用为了不同的东西。使用
i
代替,所以来自:

for (i = 0; i < 9; i++) {
    k = i;
    for (j = i + 1; j < 10; j++) {
        if (student[k].score < student[j].score) {

致:

for (i = 0; i < 9; i++) {
    for (j = i + 1; j < 10; j++) {
        if (student[i].score < student[j].score) {

通过这些更改,结果变为:

在这里运行:https://ideone.com/GDJzTu

*******************************************************
           Show information for all students           
*******************************************************
number: 8 name:imz score:84
number:30 name:pzh score:30
number:28 name:xhx score:88
number:51 name:vbi score:81
number:35 name:spe score:91
number:14 name:apm score:77
number: 7 name:lyv score:71
number: 9 name:fey score:87
number:16 name:uvv score:100
number:42 name:aap score:67

*******************************************************
      Output from high to low according to grades      
*******************************************************
number:30 name:pzh score:30
number:42 name:aap score:67
number:7 name:lyv score:71
number:14 name:apm score:77
number:51 name:vbi score:81
number:8 name:imz score:84
number:9 name:fey score:87
number:28 name:xhx score:88
number:35 name:spe score:91
number:16 name:uvv score:100

0
投票

在嵌套的 for 循环中使用变量

k
是多余和错误的。

在这个 if 语句中

        if (student[k].score < student[j].score) {
            k = j;
            temp = student[i];
            student[k] = temp;
            student[i] = student[k];
        }

变量

k
总是指向元素的值与元素的初始值
student[i]
.

另外交换操作也不正确。在这两个声明之后

            temp = student[i];
            student[k] = temp;

student[k]
student[i]
彼此相等。所以这个声明

            student[i] = student[k];

实际上等同于

            student[i] = student[i];

相反你可以写

for (i = 0; i < 9; i++) {
    for (j = i + 1; j < 10; j++) {
        if (student[i].score < student[j].score) {
            temp = student[i];
            student[i] = student[j];
            student[j] = temp;
        }
    }
}

注意函数依赖全局变量是不好的设计

数组

student
应该在main中声明。

此外,由于函数 sort 是一个通用函数,它还应该有一个参数来指定传递的数组中元素的数量,并且应该在函数中使用此参数而不是幻数 9。

如果只交换一次数组的元素,函数会更有效率。

此外,该函数只做一件事:对数组进行排序。要输出排序数组,您应该使用另一个函数。

函数可以看成下面的样子

void sort( struct Student student, size_t n )
{
    for ( size_t i = 0; i < n; i++ ) 
    {
        size_t pos = i;

        for ( size_t j = i + 1; j < n; j++ ) 
        {
            if ( student[pos].score < student[j].score ) 
            {
                pos = j;
            }
        }

        if ( i != pos )
        {
            struct Student temp = student[i];
            student[i] = student[pos];
            student[pos] = temp;
        }
    }
}

函数在主函数中被调用

sort( student, 10 );
© www.soinside.com 2019 - 2024. All rights reserved.