🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

4521閲覧

C言語でファイルの大量のデータを読み込みたい

stuokneo01

総合スコア7

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/01/20 02:27

編集2021/01/20 03:10

前提・実現したいこと

C言語でファイル内の10万件のデータを読み込むプログラムを作成したいです。
データの例はソースコードの下に記載しています。
元々defineで定義していたのですが、全くプログラムが実行されないのでmallocを使用しました。しかしながらファイル名入力後にプログラムが終了してしまいます。他の方法がありましたら、ご教示お願いします。

ここで示したポインタ(配列)はこれらを使ったプログラムを作成するために二次元のままで解決したいです。

発生している問題・エラーメッセージ

エラーメッセージは出ませんでした。

//実行中の流れを記載します FILE NAME : /*入力(例Name.txt)*/ OK //終了 //ファイルの件数が50件や120件ではOKが出力されるのですが、件数が10万件となるとOKが出力されずに終了します。 //defineで定義したときはファイル名の入力もできず終了してしまいます

該当のソースコード

c

1#include <stdio.h> 2#include <stdlib.h> 3#define N 1000 4 5int scanfile(char **n, char **p){ 6 FILE *fp = NULL; 7 char file[FILENAME_MAX]; 8 9 printf("FILE NAME : "); scanf("%s", file); 10 11 if((fp = fopen(file, "r")) == NULL){ 12 printf("ファイルをオープンできません。\n"); 13 return -1; 14 } 15 int i; 16 for(i = 0; fscanf(fp, "%s %s\n", n[i], p[i]) != EOF; i++); 17 fclose(fp); 18 19 return i; 20} 21 22int main(void){ 23 int i, m; 24 char **name = malloc(sizeof(char*) * N * 100); 25 for(i = 0; i < N; i++){ 26 name[i] = malloc(sizeof(char) * 20); 27 } 28 char **phone = malloc(sizeof(char*) * N * 100); 29 for(i = 0; i < N; i++){ 30 phone[i] = malloc(sizeof(char) * 20); 31 } 32 33 if(name == NULL){ 34 printf("nameメモリ確保エラー\n"); 35 return -1; 36 } 37 38 if(phone == NULL){ 39 printf("phoneメモリ確保エラー\n"); 40 return -1; 41 } 42 43 44 m = scanfile(name, phone); 45 printf("OK\n"); 46 47 for(i = 0; i < m; i++){ 48 free(name[i]); 49 free(phone[i]); 50 } 51 free(name); 52 free(phone); 53 54 return 0; 55} 56

試したこと

defineによる定義、mallocで領域の確保

補足情報(FW/ツールのバージョンなど)

入力するファイルの例です。

//この形式で10万件あります Goto 090-4414-1644 Kaji 178-3725-1591 Nozawa 759-3857-4789 Murakami 028-0204-2740 Kobayashi 937-9204-2948 Suzuki 930-8394-8621 . . . . . .

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Nが1000だから1000行までしか対応していないのではないでしょうか?

しかしながらファイル名入力後にプログラムが終了してしまいます。

エラーメッセージが出ているならそれを書きましょう。

あと一般論として malloc が成功したか戻り値を見てチェックするようにしましょう。

投稿2021/01/20 02:59

68user

総合スコア2022

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

stuokneo01

2021/01/20 03:12

回答ありがとうございます。 エラーメッセージはでませんでした。 if文を使いmallocでNULLを返しているときのメッセージを出力するコードを書きましたが、メッセージは出力されませんでした。(この場合も同じくエラーメッセージはでませんでした)
guest

0

ベストアンサー

char **name = malloc(sizeof(char) * N * 100);

足りないのではないでしょうか.(phone側も同様)

Nの値は1000なので,sizeof(char)が1だと仮定すれば,このサイズは 10万[byte] になりますが,
nameが指す領域のサイズとしては sizeof(char*)*10万[byte] ほど欲しいのではありませんか?

で,

name[i] = malloc(sizeof(char) * N);

逆にこっちは無意味に大きすぎるように思います.
(入力例を見る限り,1000[byte]とかなくてもよさそう.10とか20くらいで事足りるのでは?)

追記:

for(i = 0; i < N; i++)

となっているので,name[i]の確保自体,1000行分しか行ってないですね.

投稿2021/01/20 02:51

編集2021/01/20 03:05
fana

総合スコア11985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

stuokneo01

2021/01/20 03:03

回答ありがとうございます。 それぞれ char **name = malloc(sizeof(char*) * N * 100); char **phone = malloc(sizeof(char) * 20); と修正してみました。 しかし同じようにうまく実行できません...
fana

2021/01/20 03:12

まずもって N(=1000) というのが何の値を意味しているのかが謎です. なので, N*100 みたいなのもやはり何の計算をしているのか謎です. (「10万行」だと決まっているならば,「100000」で書けばよくないですかね?) 「文字列1個の先頭を示すために char* 型が1個必要であって,それを10万個分だけ並べた配列が必要である」 ならば,配列nameのサイズは sizeof(char*)*100000. phoneについても全く同じことが言えるので,やはりサイズは sizeof(char*)*100000. で,char*型のポインタである name[0]~name[99999](phone[0]~phone[99999]も同様)それぞれが,文字列を格納するのに十分なサイズの領域を指し示すようにしたいのだから, for( i=0; i<100000; ++i )name[i] = malloc( 文字列1個を格納するに十分なサイズ ); という形にすべきでは.
episteme

2021/01/20 03:12

mallocの結果を確認しましたか? NULLが返ってきてるなら失敗、多くの場合メモリの枯渇を意味します。
stuokneo01

2021/01/20 03:23

元々別のプログラムを作成していたものを質問用に切り取ったコードですので、Nの値がそのままになっていました。確認不足です。申し訳ございません。 それと、name[i]の領域の確保が1000行分しかできていなかったところを10万桁に修正したら若干遅いですがうまく実行できました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問