将C指针交换到函数内的函数

时间:2018-12-12 10:59:04

标签: c arrays pointers

我创建了一个包含字符串数组的结构,并在其中填充了单词。当我尝试将阵列填满一半以上时,我想创建一个更大的结构,将当前数据复制到那个更大的结构,然后让那个更大的结构“替换”从main调用的旧结构。尽管我已经成功创建了数据并将其复制到了新结构;我可以通过从函数内部打印出数据来证明这一点;我无法替换main中的旧结构。我尝试的下一个book_insert插入旧的较小的结构,而不是新的较大的结构。

我在一个约束内操作,因此无法在main内进行大小调整/复制/替换;必须从main调用的book_insert函数中调用它。另外,我无法编辑void book_insert(dic* s, char* v)(即添加双指针),它必须保持这种格式。

#include <stdio.h>
#include <stdlib.h>

struct book {
   int size;
   int count;
   char** words;
};

typedef struct book book;

/* Create empty book, specifying lenght of strings and how many of them */
book* book_init(int wordlen, int maxwords);
/* Add one element into the book */
void book_insert(book* s, char* v);
/* Creates and returns new, bigger book */
book* resize(book* s, book* new);
/* Prints book */
void prints(book* a);

int main(void) 
{
   book* test;
   test = book_init(60, 10);

   book_insert(test, "dog");
   book_insert(test, "cat");
   book_insert(test, "mouse");
   book_insert(test, "elephant");
   book_insert(test, "snake");

   /*The next insert will cause the resize function to trigger*/
   book_insert(test, "fish");

   /*The resize funtion should cause 'test' to be replaced by a bigger book*/
   /*But doesn't as this next print shows*/     
   printf("But printing from main function means I'm back to %d\n", test->size);
   prints(test);

}


void book_insert(book* s, char* v)
{
   int i = 0;

   while (s->words[i] != NULL ) {
      i++;
   }

   s->words[i] = v;
   s->count++;

   /*If the book is half full resize is triggered, and should pass back new, bigger book*/
   if((s->count * 100 / s->size) > 50) {
      book *new_book;
      new_book = book_init(60, 20);
      s = resize(s, new_book);
      printf("Printing from resize function gives me new length of %d\n", s->size);
      prints(s);
   }
}

book* resize(book* s, book* new)
{
   int i;
   for (i = 0; i < s->size; i++) {
      if (s->words[i] != NULL ) {
         new->words[i] = s->words[i];
      }
   }



   return new;
 }

 book* book_init(int wordlen, int maxwords)
 {
    int i;
    book* new = malloc(sizeof(book));
    new->size = maxwords;
    new->count = 0;
    new->words = (char**) calloc((size_t)new->size, sizeof(char*));

    for (i=0; i<new->size; i++) {
       new->words[i] = (char*) calloc(wordlen, sizeof(char));
       new->words[i] = NULL;
    }

    return new;
 }

 void prints(book* a)
 {
    int i;
    for (i = 0; i < a->size; i++) {
       printf("Index: %d, word: %s\n", i, a->words[i]);
    }
 }

我也尝试过在单独的函数中使用指针交换进行此操作,但这似乎也不起作用。在此版本中,我将book_resize设为无效,而在dic_insert中使用dictionary_swap(&new_book, &s)

void dictionary_swap(book **new, book **old) 
{
   book *temp = *old;
   *old = *new;
   *new = temp;
}

这又使我可以在book_insert函数中打印出较大的新结构,但对main中发生的事情没有影响。

编辑答案 这个问题被标记为重复,这意味着我自己无法回答,但是我找到了答案。我更改了上面的重复交换,以便在以下代码上调用dictionary_swap(new_book, s);(无“&”号):

void dictionary_swap(book *new, book *old) 
{
   book temp;

   temp = *old;
   *old = *new;
   *new = temp;
}

1 个答案:

答案 0 :(得分:2)

为了在函数内部修改指针,您必须将指针的地址传递给该函数,例如:

    void changePtr(char* test) {
        test = "Hello";
    }

上面的方法不起作用,因为无法将测试返回给调用者,但是:

    void changePtr(char** test) {
        if ( test != NULL ) {
            *test = "Hello";
        }
    }

以上操作之所以有效,是因为传递了指针的地址,并且可以取消引用指针以更改其内容。

呼叫示例:

    char* ptr;
    changePtr(&ptr);

这是实现上述技术的代码的重写:

    #include <stdio.h>
    #include <stdlib.h>

    typedef struct _book {
       int size;
       int count;
       char** words;  //Must allocate space for each pointer before copying to.
    } book;

    //No need for below, see above:
    //typedef struct book book;

    /* Create empty book, specifying lenght of strings and how many of them */
    book* book_init(int wordlen, int maxwords);
    /* Add one element into the book */
    void book_insert(book** s, char* v);
    /* Creates and returns new, bigger book */
    book* resize(book* s, book* new);
    /* Prints book */
    void prints(book* a);

    int main(void) {
       book* test = book_init(60, 10);        
       book_insert(&test, "dog");
       book_insert(&test, "cat");
       book_insert(&test, "mouse");
       book_insert(&test, "elephant");
       book_insert(&test, "snake");      
       /*The next insert will cause the resize function to trigger*/
       book_insert(&test, "fish");        
       /*The resize funtion should cause 'test' to be replaced by a bigger book*/
       /*But doesn't as this next print shows*/     
       printf("But printing from main function means I'm back to %d\n", test->size);
       prints(test);
    }


    void book_insert(book** s, char* v) {
       if ( s == NULL || v == NULL ) {
         return;
       }
       (*s)->words = realloc((*s)->words, sizeof(char*) * (++(*s)->count));
       (*s)->words[(*s)->count - 1] = v;
       /*If the book is half full resize is triggered, and should pass back new, bigger book*/
       if((((*s)->count * 100) / s->size) > 50) {
          book *new_book;
          new_book = book_init(60, 20);
          *s = resize(*s, new_book);
       }
    }

    book* resize(book* s, book* new) {
       int i;
       for (i = 0; i < s->size; i++) {
          if (s->words[i] != NULL ) {
             new->words[i] = s->words[i];
          }
       }        
       printf("Printing from resize function gives me new length of %d\n", new->size);
       prints(new);
       return new;
     }

     book* book_init(int wordlen, int maxwords) {
        int i;
        book* new = calloc(1, sizeof(book));
        new->size = maxwords;
        return new;
     }

     void prints(book* a) {
        int i;
        for (i = 0; i < a->size; i++) {
           printf("Index: %d, word: %s\n", i, a->words[i]);
        }
     }