Что не так при копировании моей вложенной структуры? - PullRequest
0 голосов
/ 02 мая 2018

Я пишу код C, чтобы стать лучше в программировании и учебе ... и имею программу, которая должна генерировать статическую веб-страницу. Он также сохраняет проект в виде текстового файла. У меня есть отдельные функции для создания объекта (realloc и размещения новой структуры ...), и я выделил код задачи в короткую программу для этого случая ... Это просто для чтения «проекта». Когда я бегу, он говорит:

Ошибка сегментации (ядро сброшено)

в середине print_1_content

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

Текстовый файл для чтения (all_items.txt) выглядит следующим образом, заканчивается новой строкой для двух типов контента: "sell-item" и "абзац-элемент":

S-I:Shirt of cotton|image1.jpg;image2.jpg;image3.jpg
P-I:A paragraph, as they are called.
S-I:Trousers, loose style|image4.jpg

1 Ответ

0 голосов
/ 03 мая 2018

Итак, проблема, которую вы обнаружили, находится в этой строке:

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

Это из-за приоритета работы, потому что *content[(*number_of_content)-1] - это не то же самое, что (*content)[(*number_of_content)-1], на самом деле это *(content[(*number_of_content)-1]). Итак, ваш код выполняет индексацию массива, а затем разыменовывает ссылки, указывающие на какое-то случайное место в памяти. Замените эту строку на эту, и это исправит текущую проблему.

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