2016-10-13 2 views
2

Я пытаюсь читать строки из файла в указатель на массив символов, используя fscanf. При печати я получаю ошибки сегментации. Что я делаю не так? Должен ли я использовать функцию, отличную от fscanf?C fscanf читать указатель на массив символов

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

#define MAXSTACK 100 
#define MAXLENGHT 100 

void main(int argc, char * argv[]){ 

    char *filename; 
    FILE *fp; 
    char *lines[MAXSTACK]; 
    char * command; 
    int top = 0; 
    int numlines = 0; 

    if(argc < 3){ 

    fprintf(stderr,"error: Not enough arguments provided\n"); 
    exit(1); 
    } 

    filename = argv[1]; 
    command = argv[2]; 

    if ((fp = fopen(filename,"r")) == NULL){ 

    fprintf(stderr,"error: Cannot open file %s\n",filename); 
    exit(1); 
    } 
    else{ 

    for(int i = 0; i < 3; i++){ 

     fscanf(fp,"%s",lines[i]); 
    // printf("%s\n",lines[i]); 
    } 

    char **ptr2 = lines; 
    for (int i = 0; i < 2; i++){ 

     printf("%s\n", ptr2[i]); 
    } 

    if (strcmp(command,"pop")==0){ 

     //pop(lines); 
    }else if (strcmp(command,"print_top")==0){ 
     //print_top(); 

    }else if(strcmp(command,"swap_top")==0){ 

    } 
    } 
} 
+0

У вас нет массива символов. У вас есть массив указателей на ничего, в частности. –

ответ

2

Вы можете читать строки с помощью fgets:

/* Read a single line into a temporary buffer */ 
char lineBuffer[MAX_LINE_LENGTH]; 
while (fgets(lineBuffer, sizeof(lineBuffer), fp) != NULL) { 
    /* Process the read line */ 
} 

После прочтения строки во временном буфере, вы можете глубоко скопировать строку для чтения в некоторую память, которую вы выделяемая на кучи с помощью malloc (или вы можете просто использовать strdup), а затем вы можете хранить указатель на эту память в ваш lines массив:

/* Inside the body of the while loop */ 

/* 
    * Deep copy current line into the string pointer array. 
    * strdup = malloc + strcpy 
    * Note that free is required to release memory! 
    */ 
lines[currLineIndex] = strdup(lineBuffer); 

currLineIndex++; 

Обратите внимание, что когда вы пишете код, как это:

char *lines[MAXSTACK]; 

вы направляете на стеке массив MAXSTACK элементов, каждый элемент будучи char* указателем. Но тогда вам нужно дать какое-то значимое значение этим указателям (например: , выделяя некоторую память из кучи и указывая на эту память).

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

Кроме того, хорошая практика кодирования будет четких указателей в массиве, прежде чем использовать его, например:

memset(lines, 0, sizeof(lines)); 
1

fscanf("%s", lines[i]) прочтет последовательность без пробельных символов (обратите внимание, не целую строку) в память, на которую указывает lines[i]. Проблема в том, что вы не установили lines[i], чтобы указать на любую память, и поэтому вы получаете segfault, вы запрашиваете последовательность символов, которые нужно скопировать в какое-то неопределенное местоположение.

Если заменить декларирование массива символов указателей, char *lines[MAXSTACK];, с декларацией массива массивов символов char lines[MAXLENGTH][MAXSTACK] затем lines[i] будет массивом MAXLENGTH символов, которые fscanf("%s", lines[i]), которые смогут копировать без сегментного разломы.

Вопрос остается в силе, что произойдет, если строка fscanf пытается читать больше, чем MAXLENGTH? Ответом будет больше символов, которые будут прочитаны, чем могут помещаться в массив lines[MAXLENGTH], и вы получите так называемое переполнение буфера. Для защиты от этого вы можете ограничить максимальное количество символов fscanf будет читать из строки, например, с помощью fscanf("%100s", lines[i])

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