Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 复制嵌套结构时有什么问题?_C_Struct_Malloc_Free_Unions - Fatal编程技术网

C 复制嵌套结构时有什么问题?

C 复制嵌套结构时有什么问题?,c,struct,malloc,free,unions,C,Struct,Malloc,Free,Unions,我编写C代码是为了更好地编程和学习。。。并且有一个生成静态网页的程序。它还将项目另存为文本文件。我有单独的函数来生成对象(realloc和put一个新的struct…),并将问题代码提取到一个简短的程序中,以备不时之需。。。这只是为了阅读“项目”。当我运行时,它会说: 分段故障(堆芯转储) 在打印内容的中间 #include <stdio.h> #include <string.h> #include <stdlib.h> #define SELL_ITEM

我编写C代码是为了更好地编程和学习。。。并且有一个生成静态网页的程序。它还将项目另存为文本文件。我有单独的函数来生成对象(realloc和put一个新的struct…),并将问题代码提取到一个简短的程序中,以备不时之需。。。这只是为了阅读“项目”。当我运行时,它会说:

分段故障(堆芯转储)

在打印内容的中间

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

#define SELL_ITEM 1
#define PARAGRAPH_ITEM 2

struct SellItem {
  char  title[50];
  int nr_of_img;
  char ** image_files;//array of strings
};

struct ParagraphItem{
  char * text;
};

union ContentItem{//one of the following only
  struct SellItem s_item;
  struct ParagraphItem p_item;
};

struct Content{
  int type;//1=sellitem 2=paragraph
  union ContentItem c_item;
};

int open_items_file(struct Content **, int *, char *);
int free_1_item(struct Content *);
struct Content import_1_content(char *);
void increase(struct Content**, int *);
void print_1_content(struct Content *);
struct Content import_1_content(char *);
int free_1_item(struct Content *);

int main (void)
{
  struct Content * content;
  int content_count=0;

  open_items_file(&content, &content_count, "all_items.txt");   
  return 0;
}

int open_items_file(struct Content ** content, int * number_of_content, char * filename){
  printf("open_items_file %s\n", filename);

  FILE *fp = fopen(filename, "r");
  char * line = NULL;

  size_t len = 0;
  ssize_t read;
  int counter=0;

  if(fp==NULL){
    return 0;
  }
  //for each row
  while ((read = getline(&line, &len, fp)) != -1) {

  if((line[0]=='S' || line[0]=='P') && line[1]=='-'){
    if(line[3]==':'){
      if(line[2]=='I'){
        increase(content, number_of_content);
        *content[(*number_of_content)-1] = import_1_content(line);
      }
      else{
        //not sell/paragraph item
      }
    }//end if line[3]==':'
  }//end if line[0] =='S' eller 'P'

  counter++;
}
free(line);
fclose(fp);
return counter;
}

void increase(struct Content** content, int *nr_of_content){

  if((*nr_of_content)==0){
    *content = malloc(sizeof(struct Content));
  }
  else{
    *content = realloc(*content, (*nr_of_content+1) * sizeof(struct Content));
  }

  (*nr_of_content)++;
}

void print_1_content(struct Content * content){
  //Print info
}

struct Content import_1_content(char * text_line){
  struct Content temp_content_item;
  char * line_pointer = text_line;
  char c;
  line_pointer += 4;
  if(text_line[0]=='S'){

    temp_content_item.type = SELL_ITEM;
    temp_content_item.c_item.s_item.nr_of_img=0;
    int i=0;
    char * temp_text;

    while(*line_pointer != '|' && *line_pointer != '\n' && i < sizeof(temp_content_item.c_item.s_item.title)-1){
      temp_content_item.c_item.s_item.title[i] = *line_pointer;
      i++;//target index
      line_pointer++;
    }
  temp_content_item.c_item.s_item.title[i]='\0';

  i=0;

  //maybe images?
  short read_img_counter=0;
  if(*line_pointer == '|'){
    line_pointer++; //jump over '|'
    //img-file-name separ. by ';', row ends by '\n'
    while(*line_pointer != '\n'){//outer image filename -loop
      i=0;
      while(*line_pointer != ';' && *line_pointer != '\n'){//steps thr lett
        c = *line_pointer;      
        if(i==0){//first letter
          temp_text = malloc(2);
        }
        else if(i>0){
          temp_text = realloc(temp_text, i+2);//extra for '\0'
        }
        temp_text[i] = c;
        line_pointer++;
        i++;
      }
      if(*line_pointer==';'){//another image
        line_pointer++;//jump over ';'
      }
      else{
      }
      temp_text[i]='\0';
      //allocate
      if(read_img_counter==0){//create array
        temp_content_item.c_item.s_item.image_files = malloc(sizeof(char*));
      }
      else{//extend array
        temp_content_item.c_item.s_item.image_files = realloc(temp_content_item.c_item.s_item.image_files, sizeof(char*) * (read_img_counter+1));
      } 
      //allocate
      temp_content_item.c_item.s_item.image_files[read_img_counter] = calloc(i+1, 1);
      //copy
      strncpy(temp_content_item.c_item.s_item.image_files[read_img_counter], temp_text, strlen(temp_text));
      read_img_counter++;
      temp_content_item.c_item.s_item.nr_of_img = read_img_counter;
    }
  }
  else{
    printf("Item had no img-files\n");
  }
}
else{ // text_line[0]=='P'
  temp_content_item.type = PARAGRAPH_ITEM;
  temp_content_item.c_item.p_item.text = calloc(strlen(text_line)-4,1);


  int i=0;
  while(*line_pointer != '\0' && *line_pointer != '\n'){
    temp_content_item.c_item.p_item.text[i] = *line_pointer;
    i++;
    line_pointer++;
  }
}
print_1_content(&temp_content_item);
return temp_content_item;
}

int free_1_item(struct Content * item){
  if(item->type==SELL_ITEM){
    if(item->c_item.s_item.nr_of_img > 0){
    //Freeing img-names
    for(int i=0; i<item->c_item.s_item.nr_of_img; i++){
      free(item->c_item.s_item.image_files[i]);
    }
  }
return 1;
}
else if(item->type==PARAGRAPH_ITEM){
  //freeing p_item
  free(item->c_item.p_item.text);
  return 1;
}
else{
  printf("error: unknown item\n");
}
return 0;
}

因此,您发现的问题是:

*content[(*number_of_content)-1] = temp_content_item2;
这是因为操作优先级,因为
*内容[(*内容的数量)-1]
(*内容)[(*内容的数量)-1]
不同,它实际上在做
*(内容[(*内容的数量)-1])
。因此,您的代码正在进行数组索引,然后反引用,这是指向内存中某个随机位置的。将该行替换为该行,即可解决当前问题

(*content)[(*number_of_content)-1] = temp_content_item2;

你的问题是什么?不相关,但你在哪里发现这些有趣的
TRUE
FALSE
定义?只需使用
1
0
(或包含
stdbool.h
即可获得
bool
类型和常量
true
false
),但实际上,您应该描述实际问题。并将代码缩短到复制代码所需的最小值。这都在中解释过了。它到底在哪一行崩溃?一个主要问题是动态分配对象,但
print\u 1
按值获取对象。您应该通过指针来传递它。您可以按值传递结构,但速度很慢,这也意味着它们包含的任何指针都将指向从结构指针复制的指针指向的任何对象,因此它不是一个干净的副本。谢谢。。。你知道我为什么会在这里落选吗?Greetings@ValterEkholm不知道(你在近3年前问过这个问题),但通常是因为人们认为这个问题质量很差
(*content)[(*number_of_content)-1] = temp_content_item2;