2

ファイルを読み取り、各行をcharの配列に書き込みたい。行数がわからないので、charポインタの2D配列を使うのが一番効率的な方法だと思いました。ただし、セグメンテーション違反が発生します。

私の質問はこれと重複している可能性があります: charポインタの2D配列->セグメンテーション違反?

しかし、Cの正しい構文を理解できなかったため、試すことができませんでした。

これが私のコードです:

   FILE *file = fopen ( filename, "r" );
   if ( file != NULL )
   {
        char line [ 128 ]; /* or other suitable maximum line size */
        char **new_line;
        int i = 0;
    while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
    {
        strcpy(new_line[i], line);
        i++;
    }
4

5 に答える 5

2

new_lineセグメンテーション違反の原因となるメモリが割り当てられていません。

行数がわかっている場合は、それをローカル配列自体として宣言できます。その場合、アクセス方法は正常に機能します。

#define MAX_LINES 20
#define MAX_CHARS 128
...
char new_line[MAX_LINES][MAX_CHARS] = {0};
...

ここでの問題は、最大行数がわからないことです。したがって、ダブルポインタを選択しました。その場合、最初mallocにいくつかの行を使用する必要があり、次にバッファサイズを増やすnために使用し続ける必要があります。realloc

#define MAX_CHARS 128
#define N_NO_OF_LINES 10
...
char line[MAX_CHARS] = {0};
char **new_line = NULL;
int noOfLines = 0;
int lineCount = 0;

new_line = malloc(sizeof(char*) * N_NO_OF_LINES);
noOfLines = N_NO_OF_LINES;

while (fgets (line, sizeof line, file) != NULL) /* read a line */
{
    if (lineCount >= noOfLines)
    {
        new_line = realloc(new_line, (sizeof(char*)*(noOfLines+N_NO_OF_LINES)));
        noOfLines += N_NO_OF_LINES;
    }

    new_line[lineCount] = strdup(line);
    lineCount++;
}

注:mallocおよびのヌルチェックに注意してくださいrealloc

于 2013-01-16T05:16:04.450 に答える
1

new_lineは有効なメモリチャンクに初期化されていません。

だいたい:

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

int main() {
    FILE *file = fopen ( "test.txt", "r" );
    if ( file != NULL )
    {
#define MAXLINES 128
#define MAXLINELEN 100
       char line [ MAXLINELEN ]; /* or other suitable maximum line size */
       char **new_line = (char **)malloc(sizeof(char *) * MAXLINES);
       int i = 0;

        if (!new_line) exit(-1);

        while ( i < MAXLINES && (fgets ( line, sizeof line, file ) != NULL )) /* read a line */
        {
            new_line[i] = strdup(line);
            i++;
        }
        printf("read %d lines\n", i);
    }
    exit(0);
}
于 2013-01-16T00:19:04.497 に答える
0

new_lineアレイにメモリを割り当てていません。次のようなものが必要です。

char **new_line = malloc(sizeof(char *) * MAX_LINES);

そして、各行に、を使用しないでくださいstrcpy。これは、ガベージポインタ(初期化されていないnew_line配列)にコピーされます。あなたはおそらく欲しいですstrdup(3)

new_line[i] = strdup(line);
于 2013-01-16T00:12:47.343 に答える
0

new_lineへのポインタとして宣言しますがchar *、初期化されないため、無効なメモリアドレスを指します。そのアドレスに書き込むとエラーが発生します。

おそらく、メモリを割り当ててに割り当ててからnew_line、文字列をコピーすることができます。

于 2013-01-16T00:13:43.557 に答える
0

文字列にスペースを割り当てる必要があります。Mallocは、必要なサイズのメモリスロットを返しますが、メモリの再割り当ては許可しません。そのためには、reallocがあります。

mallocを使用すると、テーブルのサイズが固定になります。これは、静的であると宣言しただけで、後で初期化した場合と同じです(mallocはそれよりもはるかに大きいため、この文に少し反対しますが、これについては目的それを言うのは安全です)。

Reallocはそれを行い、メモリを再割り当てしますが、iを正しく使用しないとかなり危険な場合があります。そして、私の意見では、それを行うための最も正しい方法ではありません。

サイズがわからないものを保存したい場合は、動的構造が最適です。'データ構造のような'リンクリストを使用できるので、必要な数の単語を使用して、そのリストを配列に変換できます。

私はこのようなもので行きます:

typedef struct _words{ //Structure to the dynamic insertion of words
  char *word;
  struct _words *next;
}words;

words *last;          //Easier implementation for this case. Not always the best solution

words *init(){        //Is good practice to start with an empty structure for reference passing 
  words *new = malloc(sizeof(words));
  if(new == NULL) exit(0);
  new->next = NULL;   //A good end/next reference
  return new;
}

void insertWord(char *word){
  words *new = malloc (sizeof(words));
  if(new == NULL) exit(0);
  new->word = malloc(strlen(word)*sizeof(char));
  if(new->word == NULL) exit(0);
  new->next = NULL;   //Or new->next = last->next; wich is also null. 
  last->next = new;
  last = new;
}

int main(){           //Or the name of your function
 FILE *file = fopen ( filename, "r" );
 words *list = init();
 last = list;
   if ( file != NULL )
   {
        char line [ 128 ]; /* or other suitable maximum line size */
        int i = 0;
    while ( fgets ( line, sizeof line, file ) != NULL ) /* read a line */
    {
        insertWord(line);
        i++;
    }

    //Here, you already have all the words in your dynamic structure. You can now save them into an array

    char **array = malloc(i*sizeof(char*));   //i is the number of words.
    if(array == NULL) exit(0);
    word *aux = list->next;
    if(aux != NULL){
     for(int j=0;j<i && aux != NULL;j++){
         array[j] = malloc(strlen(aux->word)*sizeof(char));
         if(array[j] == NULL) exit(0);
         strcpy(array[j], aux->word);
         aux = aux->next;                     // jump to the next word
     }
    }
  ...
}

これはうまくいくかもしれないと思いますが、私はそれを試しませんでした。動的構造を実装する方法についてのアイデアを提供するだけです。

それはフリーを逃し、たとえ近くにあるとしても、実際のスタックではありません。

お役に立てれば。

于 2013-01-16T01:19:26.127 に答える