2016-10-21 2 views
-2

У меня возникли проблемы с удалением всех записей в определенную структуру. Вот код функции для одного удаления входа и моя попытка в функции «удалить все»Удаление всех записей структуры в C Программирование

typedef struct person    //Structure Set up 
{ 
    char fname[20]; 
    char lname[20]; 
    char number[20]; 
} person; 

void delInfo(int num_entries,person*contacts) 
{ 
    char delfirst[20];  //Setting up Arrays to match entry 
    char dellast[20]; 
    printf("\n First Name: "); 
    scanf("%s",delfirst); 
    printf(" Last Name: "); 
    scanf("%s",dellast); 
    int i=0; 
    for (i=0; i<num_entries; i++)  //Going through contacts 
    { 
     if (strcmp(delfirst,contacts[i].fname)==0 && strcmp(dellast,contacts[i].lname)==0)  //Testing for match between entry and contacts 
     { 
      for (i=i; i<num_entries-1; i++)   //Shifting every contact AFTER match down one 
      { 
       contacts[i]=contacts[i+1]; 
      } 
      if(num_entries !=0) 
       contacts=(person*)realloc(contacts,sizeof(person)*(num_entries-1)); //Freeing memory at end by way of realloc 
      printf("\n %s %s deleted from contacts\n\n",delfirst,dellast); 
      break; 
     } 
    } 
    if(i == num_entries) 
    { 
     printf("\n Entry Not Found\n"); 
    } 
    system("pause"); 
} 

void deleteall(int num_entries,person*contacts)   //deleting all function 
{ 
int i,j; 
    for(i=0;i<num_entries;i++){ 
     contacts[i].fname=NULL; 
    contacts[i].lname=NULL; 
     contacts[i].number=NULL; 
    } 
free(contacts); 

    printf("\n All contacts deleted\n\n"); 
    system("pause"); 
} 

Проблема в том, что они являются несовместимыми типами (пытается присвоить массив из пустоты). Могу ли я использовать какой-то цикл и использовать realloc, чтобы сократить массив до 0? Я не уверен, как просто удалить все записи.

ответ

1

Членов struct person фиксируются в размерах, и не выделяются отдельно от экземпляра struct - короткий ответ, что вы не можете изменить размер массивов, ни вы можете освободить их хранение без deallocating всего struct экземпляра. Абсолютное лучшее, что можно сделать в этом случае, чтобы написать пустую строку каждому члену, чтобы указать, что это не используется:

strcpy(contacts[i].fname, ""); 

Это не изменяет размер массива, хотя.

Для того, чтобы изменить и/или удалить элементы struct person, вы должны выделить их отдельно от самого экземпляра struct. Чтобы сделать это, вам нужно объявить их как указатели к char, в отличие от массивов char:

struct person 
{ 
    char *fname; 
    char *lname; 
    char *number; 
}; 

При создании нового экземпляра struct person, вам нужно будет выделить память для каждого члена в отдельности :

#define SIZE 20 // for this example, both number of contacts and size 
       // of each struct member 

struct person contacts[size]; 
for (size_t i = 0; i < j; i++) 
{ 
    contacts[i].fname = malloc(sizeof *contacts[i].fname * SIZE); 
    contacts[i].lname = malloc(sizeof *contacts[i].lname * SIZE); 
    contacts[i].number= malloc(sizeof *contacts[i].number * SIZE); 
} 

Чтобы изменить какой-либо из членов, использовать realloc:

char *tmp = realloc(contacts[i].fname, sizeof *contacts[i].fname * SIZE * 2); 
if (tmp) contacts[i].fname = tmp; 

Так как realloc может потенциально вернуться NULL, рекомендуется сохранить результат во временную переменную указателя, а не сразу переустанавливать его обратно на исходный указатель; в противном случае вы рискуете потерять память ранее выделенной памяти, что приведет к утечке памяти.

Вы также захотите отслеживать, сколько памяти выделено для каждого члена, чтобы вы защищали от переполнения буфера.

Чтобы удалить какой-либо из членов, использовать free:

free(contacts[i].fname); 

Обратите внимание, что если вы динамически выделять экземпляр struct person, вам все равно необходимо динамически выделять каждый элемент:

struct person *p = malloc(sizeof *p); 
p->fname = malloc(sizeof *p->fname * SIZE); 
... 

Это также означает, что вы должны освободить каждого члена до, вы освободите сам экземпляр структуры:

free(p->fname); 
free(p->lname); 
free(p->number); 
free(p); 

Просто освободив p не освободит память, выделенную для p->fname, p->lname и p->number.

+0

Можете ли вы уточнить, почему я должен использовать указатель на ' char' вместо массива 'char' для освобождения/удаления? – NLhere

+0

@NLhere: поскольку мы динамически выделяем память с помощью 'malloc', которая всегда возвращает значение указателя. –

0

Вам не нужно удалять три поля структуры, поскольку они все статически распределены по 20 байт каждый. Вам нужно только освободить память в трех полях, если они динамически распределены с помощью malloc.

Вы все же должны освобождать все динамически распределенные контакты.

void deleteall(int num_entries,person*contacts)   //deleting all function 
{ 
    for(int i=0;i<num_entries;i++){ 
     free(contacts++) 
    } 

    printf("\n All contacts deleted\n\n"); 
    system("pause"); 
} 
+0

это приводит к несовместимости типа [Error] для аргумента 1 из 'free' и [Note] expected 'void *', но аргумент имеет тип 'person' – NLhere

+0

Изменено для использования вместо этого итерации указателя –

+0

, когда я пытаюсь запустить эту функцию он теперь «перестает работать» и возвращает большое количество – NLhere

0

Вы не можете присвоить NULL к контактам [я] .fname или контактов [я] .lname, потому что они являются массивами и NULL является значение указателя. Либо используйте что-то вроде memset() или просто ничего не делайте со структурой перед освобождением.

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