2016-09-03 4 views
-3

Я пишу домашнюю программу на C. Программа должна брать записи из входного файла и записывать их в выходной файл. Кажется, что что-то не так с функцией print_to_file. Я продолжаю получать ошибку сегментации 11. Пожалуйста, помогите. Мой код выглядит следующим образом.сегментация 11 в C

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


typedef struct car {  // create a struct type Car 
     char *license_plate;  
     int parking_spot; 
     int num_tickets; 
     int time_left; 
    } Car; 

    #define LICENSEPLATELENGTH 10 

    Car* import_cars(char *filename, int numCars); 
    void print_to_file(char* filename, Car* garage, int numCars); 

    int main(int argc, char * argv[]) { 
     if(argc != 4) 
      printf("Incorrect input.\n"); 
     else { 
      int number = atoi(argv[1]); 
      Car* parked_car = (Car*)malloc(sizeof(Car) * number); 
      parked_car = import_cars(argv[2], number); 
      print_to_file(argv[3], parked_car, number); 
      free(parked_car); 
     } 
     return 0; 
    } 



    Car* import_cars(char* filename, int numCars) 
{ 
    Car* inCar = (Car*)malloc(sizeof(Car) * numCars); 
    inCar->license_plate = (char*)malloc(sizeof(char) * 8); 
    //Question: How do I do if I the plate length is varied. How to malloc space to it? 

    FILE* inFilePtr; 
     if((inFilePtr = fopen(filename, "r")) == NULL) 
      printf("Error! Unable to open file %s. Check again.\n", *filename); 
     else 
     { 
      int i = 0; 
      fscanf(inFilePtr, "%s", inCar[i].license_plate); 
      fscanf(inFilePtr, "%d%d%d", inCar[i].parking_spot, inCar[i].num_tickets, inCar[i].time_left); 
      printf("%s %d %d %d \n", inCar[i].license_plate, inCar[i].parking_spot, inCar[i].num_tickets, inCar[i].time_left); 
      for(i = 1; i < numCars; i++) 
      { 
       fscanf(inFilePtr, "%s", inCar[i].license_plate); 
       fscanf(inFilePtr, "%d%d%d", inCar[i].parking_spot, inCar[i].num_tickets, inCar[i].time_left); 
       printf("%s %d %d %d \n", inCar[i].license_plate, inCar[i].parking_spot, inCar[i].num_tickets, inCar[i].time_left); 

      } 
     } 
    fclose(inFilePtr); 
    return(inCar); 
    //free(inCar.license_plate); ` 
    //Question: Do I need to free space here would it remove the value 
    //stored in the variable which passed to main? 
} 
    void print_to_file(char* filename, Car* garage, int numCars) { 
     FILE* outFilePtr; 
     if((outFilePtr = fopen(filename, "w+")) == NULL){ 
      printf("Error! Cannot Open File %s!", *filename); 
      printf("here\n"); 
     } else { 
      int i = 0; 
      for(i = 0; i < numCars; i++) { 
       printf("%s\n%d %d %d\n", garage[i].license_plate, garage[i].parking_spot, garage[i].num_tickets, garage[i].time_left); 
       fprintf(outFilePtr, "%s\n%d %d %d\n", garage[i].license_plate, garage[i].parking_spot, garage[i].num_tickets, garage[i].time_left); 
      } 
     } 
     fclose(outFilePtr); 
    } 

Это моя команда ввода.

./a.out 6 garage.txt output.txt 

Вот что печатает в моем терминале.

fi590dz 20 2 25 
57fjgmc 8 0 55 
7dkgjgu 25 1 15 
f9e829d 1 2 60 
4jgfd81 12 2 10 
Segmentation fault: 11 

Кстати, я довольно новичок в программировании и очень плохо с отладкой. Не могли бы вы дать мне несколько советов о том, как отлаживать или отлаживать инструменты? Я использую mac, поэтому gdb не работает.

+0

Как выглядит исходный файл? Можем ли мы иметь образец? – LBes

+0

'parked_car': create by' malloc' => заменить возвращаемым значением 'import_cars'.Это локальная переменная address => 'free'ed it (а не возврат malloc). – BLUEPIXY

+2

На mac, вы можете использовать lldb. –

ответ

0

Для всех, кто столкнулся с проблемой здесь, я нашел проблему в своей программе. Проблема в том, что я не выделял место для каждого из указателей license_plate в структуре. Поэтому мой способ решить эту проблему - добавить строку, как показано ниже, в цикле for функции import_cars.

inCar[i].license_plate = (char*)malloc(sizeof(char) * LICENSEPLATELENGTH); 
0

Проблема заключается в ваших функциях parked_car = import_cars(argv[2], number); и Car* import_cars(char* filename, int numCars);.

Действительно в Car* import_cars(char* filename, int numCars); вы делаете это:

Car inCar; 
inCar.license_plate = (char*)malloc(sizeof(char) * 8); 

Таким образом, вы создаете локальную переменную, которая не доступна за пределами функции (много разных вещей может произойти в памяти после завершения функции) ,

Итак, когда вы делаете: parked_car = import_cars(argv[2], number);, вы назначаете parked_car a free d переменной.

Решение состоит в том, чтобы просто использовать parked_car в качестве аргумента вашей функции import_cars(). Все изменения, внесенные в функцию, будут по-прежнему действительны после их возвращения. Таким образом, вы должны иметь:

void import_cars(char* filename, int numCars, Car* car); 
+0

Благодарим вас за ответ. Проблема заключается в назначении, прототип каждой функции назначается, я не могу изменить прототип. Есть ли другой способ решить проблему? – Renix

+0

Кстати, я также обновил мою пересмотренную функцию. Я использую указатель, чтобы передать значение структуры главной функции, но я все еще получил ошибку сегментации. – Renix

1

Не полный ответ, потому что это проблема домашнего задания, и вы хотите, чтобы понять это самостоятельно, но вот несколько подсказок.

Во-первых, вы действительно хотите научиться запускать свою программу в отладчике и заставить ее рассказать вам, какая строка разбила программу и на каких данных.

Во-вторых, убедитесь, что вы инициализируете указатели для каждого элемента массива, прежде чем пытаться их читать или писать.

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

Поэтому я предлагаю вам привыкнуть к распределению динамических массивов с помощью calloc(), а не malloc().

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