2015-09-29 5 views
0

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

#include <ctype.h> 
#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 
#define BUFSIZE 1024 

int read_lines(char *filename, char ***array, int size) { 
    char buf_file[BUFSIZE], buf_line[16]; 
    FILE *fp = fopen(filename,"r"); 
    if (fp == NULL) { 
     return -1; 
    }else{ 
     while (fgets(buf_file, BUFSIZE, fp)) 
      if (!(strlen(buf_file) == BUFSIZE-1 && buf_file[BUFSIZE-2] != '\n')) 
       size++; 
     array = malloc(size * sizeof(char*)); 
     rewind(fp); 
     size = 0; 
     while (!feof(fp)) { 
      fscanf(fp, "%s", buf_line); 
      strcpy(*array[size], buf_line); 
      size++; 
     } 
     *array[size] = NULL; 
    } 
    fclose(fp); 
    return size; 
} 

int shortest_string (char **array, int len) 
{ 
    int i = 0; 
    int smallestElement = -1; 
    int smallestElementLength = 0; 
    if(len == 0){ 
     return -1; 
    } 
    for(;i < len; i++){ 
     int elen = strlen(array[i]); 
     if(elen < smallestElementLength){ 
      smallestElementLength = elen; 
      smallestElement = i; 
     } 
    } 
    return smallestElement; 
} 

int find_lexi_first (char **array, int len) 
{ 
    char t[BUFSIZE]; 
    int i = 1, j =1, where = -1; 
    if(len == 0){ 
     return -1; 
    } 
    for (; i < len; i++) { 
     for (; j < 5; j++) { 
     if (strcmp(array[j - 1], array[j]) > 0) { 
      where = j; 
      strcpy(t, array[j - 1]); 
      strcpy(array[j - 1], array[j]); 
      strcpy(array[j], t); 
     } 
     } 
    } 
    return where; 
} 

int main() { 
    char* filename = "textfile.txt"; 
    char **array=NULL; 
    int size = 0; 

    int len = read_lines(filename, &array, size); 
    printf("Read %d lines from file %s\n", len, filename); 

    int index = shortest_string (array, len); 
    printf("Shortest line in row %d is: %s\n", index+1, array[index]); 

    index = find_lexi_first (array, len); 
    printf("Lexicographically first row in pos %d is: %s\n", index+1, array[index]); 
    return 0; 
} 

Вот ошибки сегментации,

==5910== Memcheck, a memory error detector 
==5910== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==5910== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
==5910== Command: ./out 
==5910== 
==5910== Use of uninitialised value of size 4 
==5910== at 0x804878B: read_lines (main.c:24) 
==5910== by 0x8048A30: main (main.c:77) 
==5910== 
==5910== Invalid read of size 4 
==5910== at 0x804878B: read_lines (main.c:24) 
==5910== by 0x8048A30: main (main.c:77) 
==5910== Address 0x0 is not stack'd, malloc'd or (recently) free'd 
==5910== 
==5910== 
==5910== Process terminating with default action of signal 11 (SIGSEGV) 
==5910== Access not within mapped region at address 0x0 
==5910== at 0x804878B: read_lines (main.c:24) 
==5910== by 0x8048A30: main (main.c:77) 
==5910== If you believe this happened as a result of a stack 
==5910== overflow in your program's main thread (unlikely but 
==5910== possible), you can try to increase the size of the 
==5910== main thread stack using the --main-stacksize= flag. 
==5910== The main thread stack size used in this run was 8388608. 
==5910== 
==5910== HEAP SUMMARY: 
==5910==  in use at exit: 400 bytes in 2 blocks 
==5910== total heap usage: 2 allocs, 0 frees, 400 bytes allocated 
==5910== 
==5910== LEAK SUMMARY: 
==5910== definitely lost: 0 bytes in 0 blocks 
==5910== indirectly lost: 0 bytes in 0 blocks 
==5910==  possibly lost: 0 bytes in 0 blocks 
==5910== still reachable: 400 bytes in 2 blocks 
==5910==   suppressed: 0 bytes in 0 blocks 
==5910== Rerun with --leak-check=full to see details of leaked memory 
==5910== 
==5910== For counts of detected and suppressed errors, rerun with: -v 
==5910== Use --track-origins=yes to see where uninitialised values come from 
==5910== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 
Segmentation fault (core dumped) 

Для динамического распределения памяти, я попытался подсчитать число строк из файла, а затем использовать таНос для выделения памяти для каждого линия. Я не смог отладить код. Быстрое примечание. Я только что ввел случайный текст в textfile.txt. Я пытаюсь краснеть в коде.

+3

'while (! Feof (fp))' почти всегда неправильно. –

+4

Вам нужно скомпилировать символы отладки ('g ++ -g'), чтобы valgrind мог печатать номера строк исходного кода. – ypnos

ответ

0

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

Я изменил read_lines без изменения слишком много:

int read_lines(char *filename, char ***array, int size) { 
    char buf_file[BUFSIZE], buf_line[16]; 
    FILE *fp = fopen(filename,"r"); 
    char ** strings; 

    if (fp == NULL) { 
     return -1; 
    }else{ 
     while (fgets(buf_file, BUFSIZE, fp)) 
      if (!(strlen(buf_file) == BUFSIZE-1 && buf_file[BUFSIZE-2] != '\n')) 
       size++; 
     strings = malloc(size * sizeof(char*)); 
     *array = strings; 
     rewind(fp); 
     size = 0; 
     while (!feof(fp)) { 
      fscanf(fp, "%s", buf_line); 
      strings[size] = strdup(buf_line); 
      size++; 
     } 
    } 
    fclose(fp); 
    return size - 1; 
} 

Я использую strdup для выполнения выделения и копирования. Я также считаю, что вы хотели вернуть размер-1, так как это число строк, которые действительно копируются.

+2

Он также может использовать 'strdup()' для выделения и копирования. – Barmar

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