c结构数组上的气泡排序未正确排序
我有下面的books record程序,我想对book的c结构数组上的气泡排序未正确排序,c,pointers,structure,C,Pointers,Structure,我有下面的books record程序,我想对book的name上的记录进行排序。代码没有显示任何错误,但没有对所有记录进行排序 #include "stdio.h" #include "string.h" #define SIZE 5 struct books{ //define struct char name[100],author[100]; int year,copies;
name
上的记录进行排序。代码没有显示任何错误,但没有对所有记录进行排序
#include "stdio.h"
#include "string.h"
#define SIZE 5
struct books{ //define struct
char name[100],author[100];
int year,copies;
};
struct books book1[SIZE],book2[SIZE],*pointer; //define struct vars
void sort(struct books *,int); //define sort func
main()
{
int i;
char c;
for(i=0;i<SIZE;i++) //scanning values
{
gets(book1[i].name);
gets(book1[i].author);
scanf("%d%d",&book1[i].year,&book1[i].copies);
while((c = getchar()) != '\n' && c != EOF);
}
pointer=book1;
sort(pointer,SIZE); //sort call
i=0; //printing values
while(i<SIZE)
{
printf("##########################################################################\n");
printf("Book: %s\nAuthor: %s\nYear of Publication: %d\nNo of Copies: %d\n",book1[i].name,book1[i].author,book1[i].year,book1[i].copies);
printf("##########################################################################\n");
i++;
}
}
void sort(struct books *pointer,int n)
{
int i,j,sorted=0;
struct books temp;
for(i=0;(i<n-1)&&(sorted==0);i++) //bubble sort on the book name
{
sorted=1;
for(j=0;j<n-i-1;j++)
{
if(strcmp((*pointer).name,(*(pointer+1)).name)>0)
{
//copy to temp val
strcpy(temp.name,(*pointer).name);
strcpy(temp.author,(*pointer).author);
temp.year=(*pointer).year;
temp.copies=(*pointer).copies;
//copy next val
strcpy((*pointer).name,(*(pointer+1)).name);
strcpy((*pointer).author,(*(pointer+1)).author);
(*pointer).year=(*(pointer+1)).year;
(*pointer).copies=(*(pointer+1)).copies;
//copy back temp val
strcpy((*(pointer+1)).name,temp.name);
strcpy((*(pointer+1)).author,temp.author);
(*(pointer+1)).year=temp.year;
(*(pointer+1)).copies=temp.copies;
sorted=0;
}
*pointer++;
}
}
}
和输出
The C Programming Language
X Y Z
1934
56
Inferno
Dan Brown
1993
453
harry Potter and the soccers stone
J K Rowling
2012
150
Ruby On Rails
jim aurther nil
2004
130
Learn Python Easy Way
gmaps4rails
1967
100
##########################################################################
Book: Inferno
Author: Dan Brown
Year of Publication: 1993
No of Copies: 453
##########################################################################
##########################################################################
Book: The C Programming Language
Author: X Y Z
Year of Publication: 1934
No of Copies: 56
##########################################################################
##########################################################################
Book: Ruby On Rails
Author: jim aurther nil
Year of Publication: 2004
No of Copies: 130
##########################################################################
##########################################################################
Book: Learn Python Easy Way
Author: gmaps4rails
Year of Publication: 1967
No of Copies: 100
##########################################################################
##########################################################################
Book:
Author:
Year of Publication: 0
No of Copies: 0
##########################################################################
我们可以看出上面的排序是错误的吗?我做错了什么?代码有很多问题。最明显的语义错误是弄乱了指针(在内部循环中增加指针,但从未重新设置),因此代码将在第二次迭代时通过读取和写入未分配的内存来调用未定义的行为 第二个问题是冒泡排序算法有误——如果要执行冒泡排序,则必须将外部循环从
n-1
向下运行到0
,否则第一次迭代将没有机会将第一个(可能是最大的)元素移动到位。外部循环的后续迭代将继承相同的行为
其余的问题与可读性、风格、设计和安全性有关。一个是你写了(*pointer)。member
,看在上帝的份上,它应该写为pointer->member
。另一个类似的是(*(指针+索引)).member
。。。那可能只是指针[index].member
。第三个问题是缺乏正确的格式、缩进和空白,第四个问题是使用标准库标题的#include”“
而不是#include
使用gets()
也是一个坏主意,因为它不允许您指定导致潜在缓冲区溢出的缓冲区大小<代码>fgets()应始终是首选
代码重复和冗余是不好的——您应该始终尝试通过将重复任务(例如复制书籍
结构)拉到自己的函数中来进行过程分解(这几乎是亵渎神明的“重构”事情…)。命名变量是设计的另一个重要部分。不要将某个对象称为指针,这对读者没有帮助(在阅读代码时,我一直想知道该指针指向的是什么…)
如果可能的话,还应该避免使用全局变量。在您的情况下,绝对不需要任何全局变量,因此没有任何东西可以真正证明它们的使用。另一个好的实践是将私有助手函数声明为静态
,这样可以减少名称冲突的风险
最后一个要点是:不要滥用评论。像这样的行
sort(books, SIZE); // call sort function
这是没有帮助的。除了对书籍
数组进行排序,排序(书籍,大小)
可能意味着什么(无论如何,在设计良好的代码库中)
总而言之,这就是我编写代码的方式:
#include <stdio.h>
#include <string.h>
#define SIZE 5
struct book {
char title[100];
char author[100];
int year;
int copies;
};
static void sort(struct book *books, int n);
int main()
{
int i;
int c; // EOF is out-of-range for `char`, this MUST be an int
struct book books[SIZE];
for (i = 0; i < SIZE; i++) {
fgets(books[i].title, sizeof books[i].title, stdin);
fgets(books[i].author, sizeof books[i].author, stdin);
scanf("%d%d", &books[i].year, &books[i].copies);
while ((c = getchar()) != '\n' && c != EOF);
}
sort(books, SIZE);
for (i = 0; i < SIZE; i++) {
printf("##########################################################################\n");
printf("Book: %s\nAuthor: %s\nYear of Publication: %d\nNo of Copies: %d\n", books[i].title, books[i].author, books[i].year, books[i].copies);
printf("##########################################################################\n");
}
}
static void swap(struct book *a, struct book *b)
{
struct book tmp = *a;
*a = *b;
*b = tmp;
}
static void sort(struct book *books, int n)
{
int i, j;
for (i = n - 1; i >= 0; i--) {
for (j = 0; j < i; j++) {
if (strcmp(books[j].title, books[j + 1].title) > 0) {
swap(&books[j], &books[j + 1]);
}
}
}
}
#包括
#包括
#定义尺寸5
结构书{
字符标题[100];
char作者[100];
国际年;
整版;
};
静态无效排序(结构书*books,int n);
int main()
{
int i;
int c;//EOF超出了“char”的范围,必须是int
结构书[尺寸];
对于(i=0;i=0;i--){
对于(j=0;j0){
掉期(&books[j],&books[j+1]);
}
}
}
}
您应该向后运行外部循环,即。E从n-1到0。@H2CO3向后?为什么会这样?顺便说一句,*(指针+1)
和(*指针)。名称非常可怕,请不要使用它们。更具可读性的等效替代方法是指针[1]
和指针->名称
。此外,适当的间距和缩进将大大提高感知能力。此外,main()
返回int
,并且在启用警告的情况下进行编译会发现*指针+
不会执行您认为它会执行的操作。除此之外,使用gets()
是一个非常糟糕的主意,因为它会带来安全问题——应该完全避免,而且fgets()
应该始终优先于它。@xmpirate另外,不要包含“stdio.h”
和其他库头。惯例(更安全)是将
包括在内。另外(英语中有多少个链接词?)使用fgets()
而不是scanf()
,因为scanf()
是邪恶的,它违反直觉,不按你认为的方式工作,而且不安全。@H2CO3不,你打对了。正如您所描述的,它可以通过递减外循环来完成。外循环i
应从(n-1)向下运行到1,内循环j
从0向下运行到(i-1)。我更喜欢气泡下降,其中外循环从0开始运行(n-1),内循环((I+1)…(n-I-1)。使用指针对其进行编码使后者更易于想象(至少对我而言).+1,注意,如前所述,如果给外部循环一个长度为零的列表,那么外部循环将不会很好地发挥作用,并且大小和局部索引通常是:unsigned