繁体   English   中英

结构指针运算符

[英]Structure pointer operator

代码旨在创建一个指向学生结构的指针数组,以便在其他函数中使用该指针数组。 我不确定如何在二元函数中使用箭头运算符。 它不会为找到 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;    
    }
}

你必须学会​​做的是每次编译时启用警告 这允许编译器识别代码中需要注意的许多区域。 您不应接受编译时带有警告的代码。 只有在非常非常罕见的情况下,依赖编译时带有警告的代码是可以接受的(您在编程的第一年可能不会遇到这种情况)所以始终启用-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;    
}

注意:它是否正确运行确实是一个不同的问题,这取决于您的数据和任何逻辑错误的消除。

在您的二进制搜索例程中,当您需要与list[middle].idNo进行比较时,您的 if idNolist[middle]进行比较

您可以通过使用重新分配的一维数组而不是二维指针数组来简化一些。 整个代码会更简单,并且不会丢失任何功能。

更新

我已将您的代码切换为使用结构数组而不是指向结构的指针数组。 它简化了事情,而两级查找只是增加了复杂性,这可能会让您感到困惑。 另外,在风格上进行了更多的清理 - 很抱歉,但这是我如何能够看到足够的逻辑以进行更改。

注意:我完全同意 David [和许多其他人] 关于编译器警告的看法。 他们是你的朋友。 它们通常会显示在运行程序中很难找到 10 倍的错误。 我已经做 C 很多年了,我 [仍然]总是使用-Wall -Werror

如果您想了解有关结构指针、结构数组的更多信息,请参阅我最近的回答问题实现动态结构数组它介绍了在数组、数组指针、指针索引等之间切换的各种方法。这可能有用。

添加了一个完整的诊断套件来证明 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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM