簡體   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