2015-11-06 3 views
-2

Код предназначен для создания массива указателей на структуру ученика, чтобы использовать массив указателей в других функциях. Я не уверен, как использовать оператор стрелки в двоичной функции. Он не возвращает значение для индекса, где найден идентификатор.Оператор указателя на структуру

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

Напишите функцию 'print_list', которая имеет тот же цикл' for', что и указанный код. Вызовите 'printf' вместо' fscanf' в цикле. Вызовите 'print_list' после вызова' create_class_list'. Если это не поможет, проясните, что вы действительно спрашиваете. – kaylum

+0

@kaylum спасибо. Чтобы уточнить, я прошу помощи в использовании оператора указателя структуры. – tansy

+0

Выглядит в основном нормально. Просто измените '& (list [i] -> IDno)' to 'list [i] -> IDno' – kaylum

ответ

0

В вашей двоичной рутине, ваши, если являются сравнение idNo против list[middle], когда нужно сравнить с list[middle].idNo

Вы могли бы упростить немного, используя массив 1D, который получает realloc'ed, а не 2D массив указателей. Весь код будет проще, и вы не потеряете никаких функций.

UPDATE

Я переключился свой код, чтобы использовать массив структур, а не массив указателей на структуры. Это упрощает вещи, и поиск по двум уровням просто добавляет сложности, которые, вероятно, сбивают вас с толку. Кроме того, убрали больше стиля - извините, но это то, как я смог увидеть достаточно вашей логики, чтобы внести изменения.

Примечание: Я полностью согласен с Дэвидом [и многими другими] в отношении предупреждений о компиляторе. Они твои друзья. Обычно они показывают ошибки, которые сложнее найти в 10 раз с запущенной программой. Я делал C в течение многих лет, я [еще] всегда использование -Wall -Werror

Если вы хотите узнать больше о указателях на структуры, массивы структур, увидеть мой недавний ответ Issue implementing dynamic array of structures Он имеет грунтовку на различные способы переключения между массивами, указатели на массивы, индексирование указателей и т. д., которые могут быть полезны.

Добавлен полный диагностический набор, который доказывает алгоритм binsrch, включая краевые случаи, которые могут не отображаться для заданного набора данных, прежде чем повернуть его на реальные/большие данные. Хорошая техника для запоминания.

Заметьте, что я не уверен, почему вы передали low/high как аргументы, поскольку они не служат цели для двоичного поиска в целом. Они полезны, если вы хотите получить определенное подмножество данных. Если это так, закомментируйте мой дополнительный код, сбросив его.

// 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; 
} 
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;  
} 

Примечание: работает ли он правильно это другой вопрос, действительно, это зависит от ваших данных и ликвидации любые логические ошибки.

Смежные вопросы