C言語において、以下の条件で、ファイルに保存されているテキストデータを構造体に格納する方法を教えて下さい。
例題として、テキストファイルに保存されている社員データを構造体に格納するものとします。
初心者なので、記述内容が充分か分かりませんが、宜しくお願いします。
---以下条件---
・入力ファイルはテキスト形式(.txt)とし、ファイル名は「memberlist」とします。
・ファイル(memberlist)には、社員1人につき、社員番号、名前、名前(ヨミガナ)が、「,」で区切られて存在するものとします。
また、、テキストファイルには一行につき社員1人のデータが存在するものとし、複数の社員データが同一行に存在することはありません。
テキストファイルの例).
10001,山田太郎,ヤマダタロウ,
10002,佐藤一郎,サトウイチロウ,
30010,池田悟,イケダサトル,
………………
………………(続く)
・構造体は以下のように定義されているものとします。
なお、テキストファイルに何件の社員データがあるかは定義しませんが、
構造体の数は充分に確保されているものとします。
struct Person {
int num; /*社員番号*/
char name[10]; /*名前*/
char kana[20]; /*名前(ヨミガナ)*/
};
struct Person List[100];
上記の条件のもとでテキストファイルの内容を構造体に格納したいのです。
そこで以下のようなプログラムを作ってみましたが、エラーが発生してしまいます(後述)。
#include<stdio.h>
/***構造体定義***/
struct Person {
int num; /*社員番号*/
char name[10]; /*名前*/
char kana[20]; /*名前(ヨミガナ)*/
};
struct Person List[100];
main()
/***変数の定義***/
FILE *rfp
char rbuf[256];
char *tp;
int i,size;
/***ファイルオープン***/
rfp = fopen("memberlist.txt","r");
/*エラー処理省略(ファイルオープンは正常に終了したものとします)*/
/***構造体への格納処理***/
while(1){
size = fgets(rbuf,256,rfp); /*テキストデータを一行取得*/
tp = strtok(rbuf,","); /*テキストデータをカンマで区切る*/
sprintf(List[i].num,"%05d",tp); /*文字列を数値に変換し、社員番号を構造体へ*/
tp = strtok(NULL,","); /*テキストデータをカンマで区切る*/
strcpy(List[i].name,tp); /*名前を構造体へ*/
tp = strtok(NULL,","); /*テキストデータをカンマで区切る*/
strcpy(List[i].kana,tp); /*ヨミガナを構造体へ*/
if(size == NULL){
break; /*データを読み終えたら、ループを離脱*/
}
}
上記のプログラムのエラー内容ですが、
まず、社員番号を文字列変換し格納するsprintf文で、
「パラメータ '__buffer' は signed char * 型として定義されているので int は渡せない(関数 main )」
というコンパイルエラーが発生します。
また、実行すると、Windowsからのエラー、「問題が発生したため、”プログラム名”を終了します。~~~」というプログラムが強制終了される時に出現するエラーが発生します。
可能性としてどのような問題が考えられますか?よろしくお願いします。
No.3ベストアンサー
- 回答日時:
gccでは、エラーが連発して、実行させる以前の問題でした。
ファイルは行末の「 , 」を省いて csv ファイル風に処理してあります。
/* Gcc on Mac OSX */
#include <stdio.h>
#include <string.h>/* strtok() */
#include <stdlib.h>/* atoi() */
#define SIZE256
/***構造体定義***/
struct Person {
int num;/*社員番号*/
char name[10];/*名前*/
char kana[20];/*名前(ヨミガナ)*/
};
int main(void) {
/***変数の定義***/
struct Person List[100];
FILE *rfp;
char rbuf[SIZE];
int i = 0;
/***ファイルオープン***/
rfp = fopen("memberlist.txt","r");
/*エラー処理省略(ファイルオープンは正常に終了したものとします)*/
/***構造体への格納処理***/
while(fgets(rbuf,SIZE,rfp) != NULL) {/*テキストデータを一行取得*/
List[i].num = atoi(strtok(rbuf,","));/*文字列を数値に変換し、社員番号を構造体へ*/
strcpy(List[i].name,strtok(NULL,","));/*名前を構造体へ*/
strcpy(List[i++].kana,strtok(NULL,"?n"));/*ヨミガナを構造体へ、i++を追加*/
}
return 0;
}
No.4
- 回答日時:
>>「パラメータ '__buffer' は signed char * 型として定義されているので int は渡せない(関数 main )」
これについては他の方が指摘している通り atoi() を使うことで間違いないのですが、
>>「問題が発生したため、”プログラム名”を終了します。~~~」
これについてはまだ誰も指摘していないのでそれについて解答させていただきます
このエラーが発生する箇所はおそらく
>>tp = strtok(NULL,",");
という部分です。
なぜこのようなエラーが発生するかというと
>>char *tp;
とポインタだけ宣言しといてアドレスを代入していないため、出たら目なシステムなどが使っている大事なところに代入され Windows OS がその本来のデータを守るためです。
もしポインタを使うのであれば
tp = (char*)calloc(256, sizeof(char));
という風にする必要があります。 (これを変数の動的確保といいます)calloc() は第二引数のサイズを第一引数の個数だけ確保したメモリのアドレスを戻り値として返します。
又は、
>>char rbuf[256];
といった具合に配列で宣言するついでに tp も同様に宣言すればよいのではないでしょうか?(こちらを変数の静的確保といいます)
このミスはポインタを理解し切れていない人だと良くやらかすものです(私も良くやらかしました)。ポインタという概念はC言語では非常に重要な概念ですのでまだ理解し切れていないのであれば嫌にならない程度に勉強してください。
参考URL:http://homepage2.nifty.com/c_lang/index_c.html
No.2
- 回答日時:
>sprintf(List[i].num,"%05d",tp); /*文字列を数値に変換し、社員番号を構造体へ*/
これはsprintfの使い方が間違っている。
sprintf()はあくまでも文字列に成形する関数です。
List[i].num=strtol(tp,NULL,10);
とかにするとよいかも。
あとは、構造体のメンバーが固定長になっているので、バッファーオバーフローのチェックをしないと長い名前の人がいたらプログラムがクラッシュします。
No.1
- 回答日時:
sprintfの使い方いろいろおかしいような:
・第1引数にint型変数の値を渡している。
・tpは文字列へのポインタなのに、それを%d(数値用書式文字列)で整形しようとしている。
sprintfのマニュアルを読んでみては。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- Excel(エクセル) 【VBA】指定フォルダに格納中のテキストファイルをエクセルで処理し結果のエクセルを新規フォルダに保存 1 2022/03/25 14:19
- C言語・C++・C# C言語 2 2022/07/21 00:02
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
- Visual Basic(VBA) 【前回の続き続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/24 20:49
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
char*を初期化したいのですが
-
strcat関数を自作したいです
-
C言語にて構造体のメンバがNULL...
-
C言語のintとcharの違いってな...
-
CStringからchar*への型変換に...
-
C言語のプログラムについてです
-
文字列の途中から途中までを抽出
-
2次元配列の文字"列"の初期化方法
-
csvファイルを構造体に格納した...
-
fgetc( )の戻り値はなぜ整数??
-
動的メモリの初期化方法について。
-
char 文字列型 の表現範囲が-12...
-
strcat関数
-
C言語でポインターで詰まってい...
-
char[]をDWORDに格納するには
-
共用体について
-
C言語の文字リテラル中の16進文...
-
szとlpszの違い
-
c言語でポインタ変数を用いた配...
-
文字列の演算
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
C言語のintとcharの違いってな...
-
CStringからchar*への型変換に...
-
C言語にて構造体のメンバがNULL...
-
小数点入りの文字列をfloat型に...
-
C言語のプログラムについてです
-
strcat関数を自作したいです
-
fstream型オブジェクトを関数の...
-
new charとnew char[N]の違いは?
-
DWORDとcharの変換
-
文字列の途中から途中までを抽出
-
char 文字列型 の表現範囲が-12...
-
const char* s1とただのchar s1...
-
wsprintf( ポインタ , "%d" , "...
-
c言語でポインタ変数を用いた配...
-
char型にint型の数値を代入する。
-
C言語で文字列をかえす正しい書...
-
C++17で、unsigned char * 配列...
-
共用体について
-
エクセルのMID関数は、C言語では?
おすすめ情報