代码用于创建指向学生结构的指针数组,以便在其他函数中使用指针数组。我不确定如何在二进制函数中使用箭头运算符。它不会返回找到id的索引的值。
typedef struct{
int IDno;
char name[20];
int project;
int exam;
double final;
} student;
student **create_class_list(char*filename, int *sizePtr);
void print_list(student**list,int *sizePtr);
int find_binsrch(int idNo, student **list, int size,int low, int high);
int main(void){
int i, n;
student **listPtr;
listPtr = create_class_list("student.txt", &n);
print_list(listPtr,&n);
index2 = find_binsrch(searchID, listPtr, n, 1200, 4580);
}
student **create_class_list(char *filename, int *sizeptr){
int n,i;
FILE *fptr;
fptr=fopen(filename,"r");
if(fptr==NULL)
printf("The file could not be opened.\n");
else
fscanf(fptr, "%d",sizeptr);
n=*sizeptr;
student **list;
list = (student**)calloc(1, sizeof(student*));
for(i=0;i<n;i++){
list[i]=(student*)calloc(n,sizeof(student));
fscanf(fptr,"%d %[^\n]s", &(list[i]->IDno),(list[i]->name));
}
return list;
}
void print_list(student**list,int *sizePtr){
int i;
for(i=0; i<*sizePtr; i++){
printf("%d %s\n",&(list[i]->IDno),(list[i]->name));
}
}
int find_binsrch(int idNo, student **list, int size, int low, int high){
int middle, i;
while(low<=high){
middle =(low+high)/2;
printf("%d\n", middle);
if(idNo==list[middle]->IDno)
return list[i]->IDno;
if(idNo<list[middle]->IDno)
high = middle -1;
else
low = middle +1;
return -1;
}
}
答案 0 :(得分:1)
每次编译时,您必须学会做的是启用警告。这允许编译器识别代码中需要注意的许多区域。您不应接受编译警告的代码。只有非常非常罕见的情况,依赖编译警告的代码是可以接受的(在编程的第一年你可能不会遇到这种情况)所以总是启用-Wall -Wextra
作为编译字符串的一部分。 (您也可以启用-pedantic
查看其他警告以及一些特定的警告请求,但对于一般用途-Wall -Wextra
会这样做)
如果您编辑了警告,您会看到:
students3.c: In function ‘main’:
students3.c:23:5: error: ‘index2’ undeclared (first use in this function)
index2 = find_binsrch(searchID, listPtr, n, 1200, 4580);
^
students3.c:23:5: note: each undeclared identifier is reported only once for each function it appears in
students3.c:23:27: error: ‘searchID’ undeclared (first use in this function)
index2 = find_binsrch(searchID, listPtr, n, 1200, 4580);
^
students3.c:19:9: warning: unused variable ‘i’ [-Wunused-variable]
int i, n;
^
students3.c: In function ‘print_list’:
students3.c:53:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("%d %s\n",&(list[i]->IDno),(list[i]->name));
^
students3.c: In function ‘find_binsrch’:
students3.c:57:48: warning: unused parameter ‘size’ [-Wunused-parameter]
int find_binsrch(int idNo, student **list, int size, int low, int high){
^
students3.c: In function ‘main’:
students3.c:24:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
students3.c: In function ‘find_binsrch’:
students3.c:74:1: warning: control reaches end of non-void function [-Wreturn-type]
}
<snip>
简单地解决警告/错误并重新编译(以及解决修复第一个列表时发现的新警告/错误)将允许您系统地更正代码。采取这些基本步骤将允许您将代码更正为编译而无需警告:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int IDno;
char name[20];
int project;
int exam;
double final;
} student;
student **create_class_list(char*filename, int *sizePtr);
void print_list(student**list,int *sizePtr);
int find_binsrch(int idNo, student **list, int size,int low, int high);
int main(void){
int n, index2, searchID = 2;
student **listPtr = NULL;
listPtr = create_class_list("student.txt", &n);
if (!listPtr) {
fprintf (stderr, "error: create_class_list failed.\n");
return 1;
}
print_list(listPtr,&n);
index2 = find_binsrch(searchID, listPtr, n, 1200, 4580);
if (index2) {} /* stub to eliminate unused warning */
return 0;
}
student **create_class_list(char *filename, int *sizeptr){
int n,i;
FILE *fptr;
fptr=fopen(filename,"r");
if(fptr==NULL)
printf("The file could not be opened.\n");
else
fscanf(fptr, "%d",sizeptr);
n=*sizeptr;
student **list;
list = (student**)calloc(n, sizeof(student*));
for(i=0;i<n;i++){
list[i]=(student*)calloc(n,sizeof(student));
fscanf(fptr,"%d %[^\n]s", &(list[i]->IDno),(list[i]->name));
}
return list;
}
void print_list(student**list,int *sizePtr){
int i;
for(i=0; i<*sizePtr; i++){
printf("%d %s\n",list[i]->IDno, list[i]->name);
}
}
int find_binsrch(int idNo, student **list, int size, int low, int high)
{
int middle;
if (size) {} /* stub to eliminate unused warning */
while(low<=high){
middle =(low+high)/2;
printf("%d\n", middle);
if(idNo==list[middle]->IDno)
return list[middle]->IDno;
if(idNo<list[middle]->IDno)
high = middle -1;
else
low = middle +1;
}
return -1;
}
注意:它是否正确运行确实是一个不同的问题,这取决于您的数据和消除任何逻辑错误。
答案 1 :(得分:0)
在您的二进制搜索例程中,当您需要与idNo
进行比较时,您的if list[middle]
与list[middle].idNo
进行比较
您可以通过使用获取重新分配的1D数组而不是2D指针数组来简化一点。整个代码将更简单,您将不会失去任何功能。
<强>更新强>
我已经将代码切换为使用结构数组而不是指向结构的指针数组。它简化了事情,两级查找只是增加了可能使你绊倒的复杂性。此外,清理更多的风格 - 对此抱歉,但它是如何我能够看到足够的逻辑,以进行更改。
注意:我完全同意David [和许多其他人]关于编译器警告的内容。他们是你的朋友。他们通常会显示使用正在运行的程序难以找到的错误。我已经做了很多年的C,我[仍] 总是使用-Wall -Werror
如果您想了解更多有关结构,结构数组的指针,请参阅我最近的回答Issue implementing dynamic array of structures它介绍了在数组之间切换的各种方法,指向数组的指针,索引可能有用的指针等。
添加了一个完整的诊断套件,用于证明binsrch算法,包括在对实际/大数据进行松散之前可能不会出现给定数据集的边缘情况。一个很好的记忆技巧。
请注意,我不确定为什么你传递低/高作为参数,因为它们通常不用于二进制搜索。如果您想要特定的数据子集,它们将非常有用。如果是这样,请注释掉我的额外代码重置它们。
// binsrch -- program to do binary search
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int IDno;
char name[20];
int project;
int exam;
double final;
} student;
student *
create_class_list(char *filename,int *sizeptr)
{
int n;
int i;
FILE *fptr;
student *cur;
student *list;
fptr = fopen(filename,"r");
if (fptr == NULL)
printf("The file could not be opened.\n");
else
fscanf(fptr,"%d",sizeptr);
n = *sizeptr;
list = calloc(n,sizeof(student));
for (i = 0; i < n; i++) {
cur = &list[i];
fscanf(fptr,"%d %[^\n]s",&cur->IDno,cur->name);
}
fclose(fptr);
return list;
}
void
print_list(student *list,int count)
{
int i;
student *cur;
for (i = 0; i < count; i++) {
cur = &list[i];
printf("%d %s\n",cur->IDno,cur->name);
}
}
student *
find_binsrch(int idNo,student *list,int count,int low,int high)
{
student *cur;
int middle;
student *match;
match = NULL;
// what is the purpose of the limited range? -- ignore for now
low = 0;
high = count - 1;
while (low <= high) {
middle = (low + high) / 2;
cur = &list[middle];
//printf("find_binsrch: TRACE middle=%d\n",middle);
if (idNo == cur->IDno) {
match = cur;
break;
}
if (idNo < cur->IDno)
high = middle - 1;
else
low = middle + 1;
}
return match;
}
#define RAND0(_lim) \
(rand() % _lim)
#define RAND1(_lim) \
(RAND0(_lim) + 1)
// diag_binsrch -- run diagnostic on single array size
void
diag_binsrch(int count)
{
student *list;
student *cur;
int searchidx;
student *match;
int err;
list = calloc(count,sizeof(student));
searchidx = 0;
cur = &list[searchidx];
cur->IDno = RAND1(30);
// create interesting data
++searchidx;
for (; searchidx < count; ++searchidx)
list[searchidx].IDno = list[searchidx - 1].IDno + RAND1(137);
err = 0;
// search for something lower that the lowest -- we _want_ it to fail
searchidx = 0;
cur = &list[searchidx];
match = find_binsrch(cur->IDno - 1,list,count,1200,4580);
if (match != NULL) {
printf("DIAG: expected failure -- searchidx=%d cur=%d match=%d\n",
searchidx,cur->IDno - 1,match->IDno);
++err;
}
// search for something higher that the highest -- we _want_ it to fail
searchidx = count - 1;
cur = &list[searchidx];
match = find_binsrch(cur->IDno + 1,list,count,0,count - 1);
if (match != NULL) {
printf("DIAG: expected failure -- searchidx=%d cur=%d match=%d\n",
searchidx,cur->IDno + 1,match->IDno);
++err;
}
// search for all remaining entries -- they should all match
cur = list;
for (searchidx = 0; searchidx < count; ++searchidx, ++cur) {
match = find_binsrch(cur->IDno,list,count,0,count - 1);
if (match == NULL) {
printf("DIAG: null return -- searchidx=%d IDno=%d\n",
searchidx,cur->IDno);
++err;
continue;
}
if (match->IDno != cur->IDno) {
printf("DIAG: mismatch -- searchidx=%d cur=%d match=%d\n",
searchidx,cur->IDno,match->IDno);
++err;
continue;
}
}
free(list);
if (err)
exit(1);
}
// diag_binsrch_full -- run full diagnostic
void
diag_binsrch_full(void)
{
int count;
printf("diag_binsrch_full: start ...\n");
for (count = 1; count < 1000; ++count)
diag_binsrch(count);
for (count = 1000; count <= 10000000; count *= 10)
diag_binsrch(count);
printf("diag_binsrch_full: complete\n");
}
int
main(void)
{
int listCount;
student *listPtr;
//student *cur;
//student *match;
// run diagnostic
diag_binsrch_full();
exit(0);
listPtr = create_class_list("student.txt",&listCount);
print_list(listPtr,listCount);
#if 0
match = find_binsrch(searchID,listPtr,n,1200,4580);
if (match != NULL)
printf("main: MATCH IDno=%d name='%s'\n",match->IDno,match->name);
#endif
return 0;
}