Могу ли я изменить значение в моем структурном объекте таким образом?

#c

#c

Вопрос:

Я не знаю, как передать указатель на функции и изменить значения, на которые указывает указатель,

Я сделал это так:

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

struct node{
    struct node* lchild;
    struct node* rchild;
    struct node* p;
    int noChild;
    char* data;
    int height;
};

typedef struct node text_t;

text_t * create_text(){
    text_t * txt = NULL;
    return txt;
}

int length_text(text_t *txt){
    if(txt == NULL)return 0;
    return txt->noChild 1;
}

char * get_line(text_t * txt, int index){
     if(index>txt->noChild 1) return NULL;

     text_t * current = txt;
     while((current->noChild 1)!=index-1){
        if(index-1>current->noChild 1){
           current = current->rchild;
           }else{
             current = current->lchild;
             }                                                     
     }
     return current->data;
}

void append_line(text_t *txt, char * new_line){     
      text_t * temp;

      if (txt == NULL){

       txt = (text_t *)malloc(sizeof(text_t));
       txt->lchild = NULL;
       txt->rchild = NULL;
       txt->noChild = 0;
       txt->p = NULL;
       txt->data = new_line;
       txt->height = 1;
       printf(txt->data);
     }else{
       text_t * current = txt;

       while(current->rchild!=NULL){
       current = current->rchild;
       }

       temp = (text_t *)malloc(sizeof(text_t));
       temp->lchild = NULL;
       temp->rchild = NULL;
       temp->noChild = 0;
       temp->data = new_line;
       temp->height = 1;
       temp->p = current;

}}    







int main()
{  int i, tmp; text_t *txt1, *txt2; char *c;
   printf("starting n");
   txt1 = create_text();//1
   txt2 = create_text();

   append_line(txt1, "line one" );//2
 ...
  

Я хочу создать объект такой структуры на C и использовать его для построения сбалансированного дерева.

Однако после того, как я выполнил функцию append_line(), с txt1 ничего не меняется, оно по-прежнему равно NULL . Почему?

Спасибо

Комментарии:

1. Многие люди (включая меня) предпочитают при использовании C не приводить возвращаемое значение malloc . В частности, вместо type *ptr = (type *)malloc(sizeof(type)); того, чтобы я хотел бы использовать type *ptr = malloc(sizeof *ptr); , потому что, если тип ptr изменяется, первая строка должна быть отредактирована в трех разных местах, иначе это приведет к ошибкам, в то время как вторая должна быть изменена только в одном. Это также помогает для realloc s, который обычно вообще не нужно менять.

Ответ №1:

Это потому, что c передается по значению.

  void append_line(text_t *txt, char * new_line){ 
   // ....

   txt = (text_t *)malloc(sizeof(text_t));

   // .....
 }

 int main() {
   // ...
   append_line(txt1, "line one" );
   // ...
 }
  

txt1 на main не влияет оператор malloc в appen_line to txt . Если вы хотите повлиять на txt1 in main, измените параметр функции text_t на указатель на указатель.

 void append_line(text_t **txt, char * new_line);
  

Теперь передайте адрес txt1 из main —

 append_line(amp;txt1, "line one" );
  

Ответ №2:

В C параметры функции передаются по значению. Это означает, что любые изменения, которые вы вносите в параметр внутри функции, не видны за пределами функции. Вы можете обойти это, передав указатель на данные, которые вы хотите изменить. Это делает изменения в данных, на которые указывает параметр, видимыми вне функции, но поскольку сам указатель передается по значению, любые изменения в нем не будут видны. Чтобы сделать это изменение видимым, вам нужен указатель на указатель.

 void append_line(text_t **txt, char * new_line){     
  if (*txt == NULL){
    *txt = (text_t *)malloc(sizeof(text_t));
    *txt->lchild = NULL;
    ...

// in main
text_t *txt1 = create_text();//1
append_line(amp;txt1, "line one" );//2
  

В качестве альтернативы вы можете вернуть новое значение txt из своей append_line функции.

 text_t* append_line(text_t *txt, char * new_line){     
  if (txt == NULL){
    txt = (text_t *)malloc(sizeof(text_t));
    txt->lchild = NULL;
    ...

  return txt;
}

// in main
text_t *txt1 = create_text();//1
txt1 = append_line(txt1, "line one" );//2
  

Ответ №3:

txt1 является указателем на a node . Думайте о указателе как о не более чем числовом адресе, который передается append_line в. txt Аргумент to append_line получает числовой адрес txt1 удержаний. Если бы вы должны были изменить элементы внутри txt , то вы бы изменили, на что txt1 указывает. Однако, когда вы присваиваете новое значение txt in append_line , вы перезаписываете числовой адрес, который находится в txt переменной. Это абсолютно не влияет на txt1 — вместо этого оно txt указывает на новое значение.

Если вы хотите присвоить новое значение указателю, вам нужно передать на него указатель. Другими словами, вам нужно передать указатель на указатель. Рассмотрим следующую версию:

 void append_line(text_t **h, char *new_line) {
    if (*h == NULL) {
        *h = (text_t*)malloc(sizeof(text_t));
        (*h)->lchild = NULL;
        (*h)->rchild = NULL;
        /* rest of if block */
    } else {
        text_t *temp;
        text_t *current = *h;
        /* rest of else block */
    }
}

int main() {
    int i, tmp; text_t *txt1, *txt2; char *c;
    printf("starting n");
    txt1 = create_text();
    txt2 = create_text();
    /* txt1 is a pointer to text_t
     * amp;txt1 is a pointer to a pointer of text_t
     */
    append_line(amp;txt1, "line one" );
...