2016-01-17 8 views
-3

Я новичок в программировании на C, и у меня возникают проблемы с пониманием того, как использовать функции fopen, fseek, freopen и как читать/записывать связанный список в файл.Открытие файла дает segfault в программе

Вот код из:

struct data used_servers(){ 
    struct data server_settings; 

    s_type *head; 
    s_type *actual; 
    int r_id; 
    char r_host[16]; 
    char r_port_inc[8]; 
    FILE *f; 
    long size; 
    head = NULL; 

    char select_inc[10]; 
    int select; 
    int count = 0; 

    f=fopen("./config/config.init", "r"); 

    fseek(f, 0, SEEK_END); 
    size = ftell(f); 
    if(size==0){ 
     printf(" There are no servers to choose from. Proceeding to set up a new connection!\n"); 
     server_settings = initialize_server(); 

     head=actual=(s_type*)malloc(sizeof(s_type)); 
     actual->id=1; 
     strcpy(actual->host,server_settings.host); 
     strcpy(actual->port_inc,server_settings.port_inc); 

     f=freopen("./config/config.init", "w", stdout); 
     fprintf(f, "%d\n%s\n%s\n\n",actual->id, actual->host, actual->port_inc); 
     fclose(f); 

     return server_settings; 
    } 

    while(fscanf(f,"%d\n%s\n%s\n\n",&r_id,r_host,r_port_inc)!=EOF){ 
     if(head==NULL) head=actual=(s_type*)malloc(sizeof(s_type)); 
     else actual=actual->next=(s_type*)malloc(sizeof(s_type)); 
     actual->next=NULL; 
     actual->id=r_id; 
     strcpy(actual->host,r_host); 
     strcpy(actual->port_inc,r_port_inc); 
    } 

    printf(" List of available servers: \n"); 
    for(actual=head;actual!=NULL;actual=actual->next){ 
     printf(" #%d - %s:%s\n", actual->id, actual->host, actual->port_inc); 
    } 

    printf("Please choose one of the following servers or set up a new one (ID,New): "); 
    fgets(select_inc, sizeof(select_inc), stdin); 

    if(strncmp(select_inc,"New",3)==0){ 
     printf("Setting up a new connection!\n"); 
     server_settings = initialize_server(); 
     while (actual->next!=NULL){ 
      actual = actual->next; 
     }; 
     actual->next=(s_type*)malloc(sizeof(s_type)); 
     actual=actual->next; 
     actual->id=r_id+1; 
     strcpy(server_settings.host,actual->host); 
     strcpy(server_settings.port_inc,actual->port_inc); 

     actual=head; 
     f=freopen("./config/config.init", "w", stdout); 
     while(actual){ 
      fprintf(f, "%d\n%s\n%s\n\n",actual->id, actual->host, actual->port_inc); 
      actual = actual->next; 
     } 
     printf("New server configuration was saved in config.init!\n"); 
     fclose(f); 

     return server_settings; 
    } 

    const char *tmp=select_inc; 
    while(isdigit(*tmp) && *tmp++); 

    actual=head; 
    while(actual!=NULL){ 
     actual=actual->next; 
     count++; 
    } 

    if (*tmp=='\0'){ 
     select = atoi(select_inc); 
     while (1){ 
      if(select>count){ 
       printf("Not a valid server. Please try again!: "); 
       fgets(select_inc, sizeof(select_inc), stdin); 
      } 
      if(select<=count){ 
       break; 
      } 
     } 

     actual=head; 
     count=0; 

     while (actual != NULL){ 
      if (count == select){ 
       strcpy(server_settings.host,actual->host); 
       strcpy(server_settings.port_inc,actual->port_inc); 
       break; 
      } 
      count++; 
      actual=actual->next; 
     } 
    } 
    fclose(f); 
    return server_settings; 
} 

и вот мои структура декларации

struct data{ 
    char host[16]; 
    char port_inc[8]; 
}; 

typedef struct s_list{ 
    int id; 
    char host[16]; 
    char port_inc[8]; 
    struct s_list *next; 
} s_type; 
+0

Вы пытались отладить? На какой строке он падает? – wimh

+1

Почему вы не пытаетесь использовать отладчик, чтобы выяснить, какая строка вызвала segfault, GDB - достойный отладчик в Linux –

+0

«Ошибка сегмента» - из-за сложных указателей, когда вы отлаживаете контрольные указатели. –

ответ

3

Вы просто неправильно freopen.

Эта линия:

f=freopen("./config/config.init", "w", stdout); 

freopen открывает заново открытый файл в другом режиме.

Вы открываете файл .conconfig/config.init, а затем передаете stdout как открытый файл ???

Вы только что прошли f.

Так что код будет:

f=freopen("./config/config.init", "w", f); 

Это только одна ошибка, которую я видел, вы можете иметь больше ошибок!

Надеюсь, это поможет.

+0

Все помогает: D Спасибо! –

+0

Ваш прием: D –

+0

Именование переменных персонаж - это плохая вещь (вводит в заблуждение). Вы можете назвать «f», например. 'Serverlstfile'. –

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