構造体による処理

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
monsutonton
記事: 29
登録日時: 9年前

構造体による処理

#1

投稿記事 by monsutonton » 9年前

以下の課題がわからなくて困っています。
ファイルを読み込んで、条件に合うようにしたいです。
また、結果は新しいファイルに出力するみたいです。

-条件-
トランザクションのファイルの番号のみ→消す
masterにない番号は、トランザクション(文字列)を丸ごと追加



構造体を使う
1個の関数は、60行まで
scanf禁止(fgets等)


●master.dat
00001,akai fumihito,akai@xxxxx.xx.jp
00002,ando yuki,ando@xxxxx.xx.jp
00003,ishikura toshiyuki,ishikura@xxxxx.xx.jp
00004,inoue miyuki,inoue@xxxxx.xx.jp
00005,iwata tomohiro,iwata@xxxxx.xx.jp
00006,ueda hiroshi,ueda@xxxxx.xx.jp
00007,osada kinya,osada@xxxxx.xx.jp
00008,odagiri daisuke,odagiri@xxxxx.xx.jp
00009,katsumata sakura,katsumata@xxxxx.xx.jp
00010,kumagai yuki,kumagai@xxxxx.xx.jp
00011,kobayashi yuki,yukikoba@xxxxx.xx.jp
00012,kobayashi yuta,yutakoba@xxxxx.xx.jp
00013,saito naoya,saito@xxxxx.xx.jp
00014,saito noritaka,sato@xxxxx.xx.jp
00015,shimura chie,simura@xxxxx.xx.jp
00016,sugihara takashi,sugihara@xxxxx.xx.jp
00017,chino kota,chino@xxxxx.xx.jp
00018,nakajima ayumu,nakajima@xxxxx.xx.jp
00019,natori hisao,natori@xxxxx.xx.jp
00020,nozawa ruriko,nozawa@xxxxx.xx.jp
00022,hihara yoshiyuki,hihara@xxx.xx.jp
00023,fujie mayumi,fujie@xxxxx.xx.jp
00024,fujimaki hiroyuki,fujimaki@xxxxx.xx.jp
00025,miura tsunayuki,miura@xxxxx.xx.jp
00026,mochiduki hideaki,mochiduki@xxxxx.xx.jp
00027,yazawa akihiko,yazawa@xxxxx.xx.jp
00028,yokomori chigusa,yokomori@xxxxx.xx.jp
00029,watanabe akira,awatanabe@xxxxx.xx.jp
00030,watanabe kentaro,kwatanabe@xxxxx.xx.jp

●trasaction.dat
00003
00004,inoue sachi
00007,,nagata@xxxxx.xx.jp
00018,nakadori ayumu,nakadori@xxxxx.xx.jp
00021,hatayama yurika,hatakeyama@xxxxx.xx.jp
00022,hinohara yoshiyuki,hinohara@xxx.xx.jp
00026
00029
00030,watanabe kenjiro
00031,yoshimura yoshikazu,yoshimura@xxxxx.xx.jp


この2つを読み込む

プログラム的には、
1、ファイル読み込み
2、比較(条件含む)する
3、newファイルに書き込む
4、ファイルクローズ

になると考えます。
1は何となくですが、作りました。
2から、比較がどうやるのかなど、わかりません。

コード:

#include<stdio.h>
#define BANGO 50
#define NAME 50
#define ADORESU 50
#define NUM 50

struct file
{
	char bango[BANGO];
	char name[NAME];
	char adoresu[ADORESU];
};

int main(void)
{

	char str[NUM];
	int i;
	FILE *fp,*fp2,*fp3;
	
	fp = fopen("master.dat","r");
	
	if(fp == NULL)
	{
		return 1;
	}
	printf("ファイルをオープンしました");
	
	fp2 = fopen("transaction","r");
	
	if(fp2 == NULL)
	{
		return 1;
	}
	printf("ファイルをオープンしました");
	
	fp3 == fopen("result.dat","r");
	
	if(fp == NULL)
	{
		return 1;
	}
	printf("ファイルをオープンしました")
	
	while(fgets(str,NUM-1,fp)
	{
		printf("%s\n",fp);
	}
	return 0;
}

resultが新しいファイルです。指摘お願いします。

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#2

投稿記事 by monsutonton » 9年前

比較は構造体に入れてからですよね?
消去、追加も関数ですよね?

色々とわからなくてすみません。
また、質問内容も理解しがたいと思います。

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#3

投稿記事 by monsutonton » 9年前

すみません。まとめてみました。

1.ファイル読み込み
2.ファイルを構造体に入れる
3.構造体で比較
-条件-
トランザクションのファイルの番号のみ→消す
masterにない番号は、トランザクション(文字列)を丸ごと追加

4.新しいファイルに結果を入れる
5.ファイルを閉じる

なお、実行は標準出力されずに新しいファイルに書き込む
カンマ区切りで処理したいです。
よろしくお願いします。

かずま

Re: 構造体による処理

#4

投稿記事 by かずま » 9年前

monsutonton さんが書きました:また、質問内容も理解しがたいと思います。
いえ、質問内容は理解したつもりです。
次のプログラムと同じ結果が得られればいいんですよね。

コード:

#include <stdio.h>   // fopen, fclose, fget, fputs
#include <string.h>  // strncmp

int main(void)
{
    char s1[256], s2[256], *p1, *p2;  FILE *f1, *f2, *f3;  int d;

    f1 = fopen("master.dat", "r");      if (!f1) return 1;
    f2 = fopen("transaction.dat", "r"); if (!f2) return 2;
    f3 = fopen("result.dat", "w");      if (!f3) return 3;
    p1 = fgets(s1, sizeof s1, f1);
    p2 = fgets(s2, sizeof s2, f2);
    while (p1 && p2)
        if ((d = strncmp(p1, p2, 5)) < 0)
            fputs(p1, f3), p1 = fgets(s1, sizeof s1, f1);
        else if (d > 0)
            fputs(p2, f3), p2 = fgets(s2, sizeof s2, f2);
        else
            (p2[5] == ',') && fputs(p2, f3),
            p1 = fgets(s1, sizeof s1, f1),
            p2 = fgets(s2, sizeof s2, f2);
    while (p1) fputs(p1, f3), p1 = fgets(s1, sizeof s1, f1);
    while (p2) fputs(p2, f3), p2 = fgets(s2, sizeof s2, f2);
    fclose(f3), fclose(f2), fclose(f1);
    return 0;
}
このプログラムは、構造体を使っていないので、解答ではありません。
レコード番号が 5桁で、かつ昇順になっていることを仮定していますので、
そうでなければ、解答ではありません。参考になるのは、出力ファイルの
fopen は "r" ではなく "w" だということぐらいかな。

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#5

投稿記事 by monsutonton » 9年前

プログラムが複雑で難しいですね。
やはり配列のが簡単ですかね!!

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#6

投稿記事 by monsutonton » 9年前

すみません。
質問内容が悪いのかもしれないですが、
何かヒント頂けますか?全体の。

手がつけられていません。やりたいことは分かるんですが、プログラム化できません。

お願いします。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 構造体による処理

#7

投稿記事 by みけCAT » 9年前

monsutonton さんが書きました:やりたいことは分かるんですが、プログラム化できません。
作業の手順を自然言語で詳しく説明できますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#8

投稿記事 by monsutonton » 9年前

3つ目の質問では厳しいですか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 構造体による処理

#9

投稿記事 by みけCAT » 9年前

monsutonton さんが書きました:-条件-
トランザクションのファイルの番号のみ→消す
masterにない番号は、トランザクション(文字列)を丸ごと追加
masterにある番号で、トランザクションのファイルで番号のみでないデータの処理が未定義ですね。
monsutonton さんが書きました:何かヒント頂けますか?全体の。
C言語ではプリプロセッサ以外は1行で書けるので、「1個の関数は、60行まで」という条件はあまり考えなくてもいいですね。
データの件数の上限がわからないし、削除の操作があるので、配列より線形リストを使う方が良さそうな気がします。
線形リストのノードとして構造体を使えば、行を構造体に分割する比較的複雑で無駄な処理をする必要もなくなるでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#10

投稿記事 by monsutonton » 9年前

ありがとうございます。

一つのファイル処理ならなんとかなりそうです。

ただ、2つを比較し、新しいファイルに入れる処理が分かりません。

かずま

Re: 構造体による処理

#11

投稿記事 by かずま » 9年前

monsutonton さんが書きました:ただ、2つを比較し、新しいファイルに入れる処理が分かりません。
では、まず次のプログラムを書いてください。
  1. master.dat, transcation.dat, result.dat をオープンする。
  2. master.dat から読み込んだデータは、そのまま result.dat に書き込む。
  3. transaction.dat から読み込んだデータは、標準出力に書き込む。
  4. すべてのファイルをクローズする。

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#12

投稿記事 by monsutonton » 9年前

よろしくお願します。

コード:

#include<stdio.h>
#include<string.h>
#define BANGO 50
#define NAME 50
#define ADORESU 50
#define NUM 100

struct File
{
	char bango[BANGO];
	char name[NAME];
	char adoresu[ADORESU];
};

int main(void)
{

	char str[NUM];
	int i;
	FILE *fp,*fp2,*fp3;
	
	fp = fopen("master.dat","r");
	
	if(fp == NULL)
	{
		return 1;
	}
	printf("ファイルをオープンしました\n");
	
	fp2 = fopen("transaction","r");
	
	if(fp2 == NULL)
	{
		return 1;
	}
	printf("ファイルをオープンしました");
	
	fp3 == fopen("result.dat","w");
	
	if(fp == NULL)
	{
		return 1;
	}
	printf("ファイルをオープンしました");
	
	while((fgets(str,NUM,fp))!=NULL)
	{
		printf("%s",str);
		fputs(str,fp3); 
	}
	
	fclose(fp);
	fclose(fp2);
	fclose(fp3);
	
	return 0;
}	

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#13

投稿記事 by monsutonton » 9年前

40行目をfp3に修正します。

かずま

Re: 構造体による処理

#14

投稿記事 by かずま » 9年前

monsutonton さんが書きました:よろしくお願します。
コンパイルして、実行してから質問してください。
コンパイルして、エラーメッセージが出て、意味が分からなければ、
エラーメッセージをそのままコピペしてください。
自分で勝手に解釈して、こんな感じのエラーが出ましたとは言わないでください。
また、実行した結果についても詳細に報告してください。

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#15

投稿記事 by monsutonton » 9年前

コンパイルは通り、標準出力はされていません。

かずま

Re: 構造体による処理

#16

投稿記事 by かずま » 9年前

monsutonton さんが書きました:コンパイルは通り、標準出力はされていません。
コンパイルできたとは。コンパイラは何ですか?
Visual C++ なら、警告が出ますし、
gcc なら -Wall オプションをつけてコンパイルしていますか?

30行目 "tansaction.dat" では?
38行目 == を = に。

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#17

投稿記事 by monsutonton » 9年前

コード:

#include<stdio.h>
#include<string.h>
#define BANGO 50
#define NAME 50
#define ADORESU 50
#define NUM 100

struct File
{
	char bango[BANGO];
	char name[NAME];
	char adoresu[ADORESU];
};

int main(void)
{

	char str[NUM];
	int i;
	FILE *fp,*fp2,*fp3;
	
	fp = fopen("master.dat","r");
	
	if(fp == NULL)
	{
		return 1;
	}
	printf("ファイルをオープンしました\n");
	
	fp2 = fopen("transaction.dat","r");
	
	if(fp2 == NULL)
	{
		return 2;
	}
	printf("ファイルをオープンしました");
	
	fp3 = fopen("result.dat","w");
	
	if(fp3 == NULL)
	{
		return 3;
	}
	printf("ファイルをオープンしました");
	
	while((fgets(str,NUM,fp))!=NULL)
	{
		printf("%s",str);
		fputs(str,fp3); 
	}
	
	fclose(fp);
	fclose(fp2);
	fclose(fp3);
	
	return 0;
}	
実行結果は、ファイルをオープンしました。ファイルをオープンしました。ファイルをオープンしました。00001,akai fumihito,akai@xxxxx.xx.jp 以降
が実行しました。ターミナルで実行しました。

         

かずま

Re: 構造体による処理

#18

投稿記事 by かずま » 9年前

monsutonton さんが書きました: 実行結果は、ファイルをオープンしました。ファイルをオープンしました。ファイルをオープンしました。00001,akai fumihito,akai@xxxxx.xx.jp 以降
が実行しました。ターミナルで実行しました。
本当ですか?
私が実行すると、実行結果は

コード:

ファイルをオープンしました
ファイルをオープンしましたファイルをオープンしました00001,akai fumihito,akai@xxxxx.xx.jp
00002,ando yuki,ando@xxxxx.xx.jp
00003,ishikura toshiyuki,ishikura@xxxxx.xx.jp
00004,inoue miyuki,inoue@xxxxx.xx.jp
00005,iwata tomohiro,iwata@xxxxx.xx.jp
00006,ueda hiroshi,ueda@xxxxx.xx.jp
00007,osada kinya,osada@xxxxx.xx.jp
00008,odagiri daisuke,odagiri@xxxxx.xx.jp
00009,katsumata sakura,katsumata@xxxxx.xx.jp
00010,kumagai yuki,kumagai@xxxxx.xx.jp
00011,kobayashi yuki,yukikoba@xxxxx.xx.jp
00012,kobayashi yuta,yutakoba@xxxxx.xx.jp
00013,saito naoya,saito@xxxxx.xx.jp
00014,saito noritaka,sato@xxxxx.xx.jp
00015,shimura chie,simura@xxxxx.xx.jp
00016,sugihara takashi,sugihara@xxxxx.xx.jp
00017,chino kota,chino@xxxxx.xx.jp
00018,nakajima ayumu,nakajima@xxxxx.xx.jp
00019,natori hisao,natori@xxxxx.xx.jp
00020,nozawa ruriko,nozawa@xxxxx.xx.jp
00022,hihara yoshiyuki,hihara@xxx.xx.jp
00023,fujie mayumi,fujie@xxxxx.xx.jp
00024,fujimaki hiroyuki,fujimaki@xxxxx.xx.jp
00025,miura tsunayuki,miura@xxxxx.xx.jp
00026,mochiduki hideaki,mochiduki@xxxxx.xx.jp
00027,yazawa akihiko,yazawa@xxxxx.xx.jp
00028,yokomori chigusa,yokomori@xxxxx.xx.jp
00029,watanabe akira,awatanabe@xxxxx.xx.jp
00030,watanabe kentaro,kwatanabe@xxxxx.xx.jp
transaction.dat の内容と同じかどうか確認しましたか?
result.dat の内容が master.dat の内容と同じかどうか確認しましたか?

なぜ、コンパイラが何かを尋ねているのに答えてくれないのですか?

では、次は構造体です。
str の内容を構造体 data に移し、data の中身を表示するプログラムは書けますか?

コード:

#include<stdio.h>
#include<string.h>
#define BANGO 50
#define NAME 50
#define ADORESU 50
#define NUM 100
 
struct File
{
    char bango[BANGO];
    char name[NAME];
    char adoresu[ADORESU];
};
 
int main(void)
{
    char str[] = "00001,akai fumihito,akai@xxxxx.xx.jp";
    struct File data;
    // ここにコードを書く
    return 0;
}
ところで、構造体 struct File のメンバ bango は int ではなく
char [50] でいいんですか?

かずま

Re: 構造体による処理

#19

投稿記事 by かずま » 9年前

構造体の前にやることがありました。

あなたは、まだ、与えられた課題のプログラムを書くことはできないでいます。

でも、プログラムを書かずに自分の手で result.dat を書くことはできるでしょう。
それを書いてください。

そして、そのとき、どういう手順でそれを書いたのか教えてください。
実は、その手順こそがプログラムなのです。

かずま

Re: 構造体による処理

#20

投稿記事 by かずま » 9年前

かずま さんが書きました: では、次は構造体です。
str の内容を構造体 data に移し、data の中身を表示するプログラムは書けますか?
17行目の文字列の最後に \n を追加してください。

コード:

    char str[] = "00001,akai fumihito,akai@xxxxx.xx.jp\n";

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#21

投稿記事 by monsutonton » 9年前

ファイルを読み取り、配列に入れる。
2つ目のファイルを配列に入れる。
その配列を比べる。

構造体は、変更、追加、消去

が良いとは思うのですが。。。

かずま

Re: 構造体による処理

#22

投稿記事 by かずま » 9年前

monsutonton さんが書きました:ファイルを読み取り、配列に入れる。
そんなことを聞いているのではありません。
あなたが期待する result.dat の内容を書いてみてください。
それが書けないということは、あなたは問題を理解していないことになるので
プログラムの書きようがありません。
result.dat の 1行目を書くとき、あなたは何をしますか?
次の行を書くとき何をしますか?
その細かな手順が知りたいのです。

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#23

投稿記事 by monsutonton » 9年前

すみません。わからないです。

かずま

Re: 構造体による処理

#24

投稿記事 by かずま » 9年前

期待する result.dat

コード:

00001,akai fumihito,akai@xxxxx.xx.jp
00002,ando yuki,ando@xxxxx.xx.jp
00004,inoue sachi
00005,iwata tomohiro,iwata@xxxxx.xx.jp
00006,ueda hiroshi,ueda@xxxxx.xx.jp
00007,,nagata@xxxxx.xx.jp
00008,odagiri daisuke,odagiri@xxxxx.xx.jp
00009,katsumata sakura,katsumata@xxxxx.xx.jp
00010,kumagai yuki,kumagai@xxxxx.xx.jp
00011,kobayashi yuki,yukikoba@xxxxx.xx.jp
00012,kobayashi yuta,yutakoba@xxxxx.xx.jp
00013,saito naoya,saito@xxxxx.xx.jp
00014,saito noritaka,sato@xxxxx.xx.jp
00015,shimura chie,simura@xxxxx.xx.jp
00016,sugihara takashi,sugihara@xxxxx.xx.jp
00017,chino kota,chino@xxxxx.xx.jp
00018,nakadori ayumu,nakadori@xxxxx.xx.jp
00019,natori hisao,natori@xxxxx.xx.jp
00020,nozawa ruriko,nozawa@xxxxx.xx.jp
00021,hatayama yurika,hatakeyama@xxxxx.xx.jp
00022,hinohara yoshiyuki,hinohara@xxx.xx.jp
00023,fujie mayumi,fujie@xxxxx.xx.jp
00024,fujimaki hiroyuki,fujimaki@xxxxx.xx.jp
00025,miura tsunayuki,miura@xxxxx.xx.jp
00027,yazawa akihiko,yazawa@xxxxx.xx.jp
00028,yokomori chigusa,yokomori@xxxxx.xx.jp
00030,watanabe kenjiro
00031,yoshimura yoshikazu,yoshimura@xxxxx.xx.jp
master.dat も transaction.dat も行頭 5文字の番号が昇順に書かれています。
そこで、私は次のように考えました。

コード:

1. master.dat の 1行目を見る。 00001,akai ...
2. transaction.dat の 1行を見る。 00003
3. 00001 と 00003 を比較する。
     00001 のほうが小さいから、00001 の行への更新処理は不要と判断し、
     00001 の行を result.dat に書く。
     master.dat の次の行を見る。00002 ando .... 
4. 00002 と 00003 を比較する。
     00002 のほうが小さいから、00002 の行への更新処理は不要と判断し、
     00002 の行を result.dat に書く。
     master.dat の次の行を見る。00003 ishikura ...
5. 00003 と 00003 を比較する。
     等しいので、更新処理を行う。
     番号単独なので、削除処理と判断し、00003 ishikura ... は出力しない。
     master.dat の次の行を見る。00004.inoue miyuki,inoue@.....
     transaction.dat の次の行を見る。00004,inoue sachi
6. 00004 と 00004 を比較する。
     等しいので、更新処理を行う。
     番号単独ではないので、00004,inoue sachi のほうを result.dat に書く。
     master.dat の次の行を見る。00005,iwata ....
     transaction.dat の次の行を見る。00007,,nagata@.....
7. 00005 と 00007 を比較する。
     00005 のほうが小さいから、00005 の行への更新処理は不要と判断し、
     00005 の行を result.dat に書く。
     master.dat の次の行を見る。00006 ueda .... 

このようにして、次のような場合の処理が分かりました。

1. 更新なしで master.dat の行をそのまま result.dat に書く
2. 削除なので master.dat の行を result.dat に書かない
3. 更新なので transaction.dat の行を result.dat に書く

さらに見ていくと、
master.dat の 00020,nozawa ....
transaction.dat の 00021,hatayama ... を処理した後
master.dat の 00022,hihara ... を見る。
  00022 のほうが大きいので、00020 の行は追加処理と判断し、
  00020 の行を result.dat に書く。

最後に
master.dat の 00030,watanabe ...
transaction.dat の 00030,watanabe .... を処理した後
master.dat には次の行がない
あとは、transaction.dat の行をすべて result.dat に書く。

もしも、transaction.dat のほうが先に最後に達していたら、
あとは、master.dat の行をすべて result.dat に書くことになる。
こんな風に書くと、すごく大変なように思えますが、
書かずに考えるだけだと 1分もかからないでしょう。

手順をまとめると、

コード:

master.dat から s1 に 1行読み込む
transaction.dat から s2 に 1行読み込む
両方の読み込みに成功している間
    s1の番号と s2の番号を比較する
    s1の番号が小さい場合
        s1 を result.dat に出力
        master.dat から s1 に 1行読み込む
    s2の番号が小さい場合
        s2 を result.dat に出力
        transaction.dat から s2 に 1行読み込む
    番号が等しい場合
        s2 の番号の後に ',' がある場合
            s2 を result.dat に出力
        master.dat から s1 に 1行読み込む
        transaction.dat から s2 に 1行読み込む
master.dat に残りがある間
    s1 を出力し、master.dat から s1 に次の 1行を読み込む
transaction.dat に残りがある間
    s2 を出力し、master.dat から s2 に次の 1行を読み込む
あとはこれを、プログラミング言語に書き直すだけです。

また、これは私の考えであって、
人それぞれによって、異なる手順も考えられます。

かずま

Re: 構造体による処理

#25

投稿記事 by かずま » 9年前

かずま さんが書きました: そこで、私は次のように考えました。

コード:

さらに見ていくと、
master.dat の 00020,nozawa ....
transaction.dat の 00021,hatayama ... を処理した後
master.dat の 00022,hihara ... を見る。
  00022 のほうが大きいので、00020 の行は追加処理と判断し、
  00020 の行を result.dat に書く。
5,6行目を次のように訂正します。

コード:

  00022 のほうが大きいので、00021の行は追加処理と判断し、
  00021の行を result.dat に書く。
[/quote]

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#26

投稿記事 by monsutonton » 9年前

配列に格納しますか?
あと、比較処理はstrcmp(fp1,fp2);ですか?

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#27

投稿記事 by monsutonton » 9年前

すみません。期限がまじかで困っています。
解答までとは言いませんが、似ているものがあれば教えてください。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 構造体による処理

#28

投稿記事 by みけCAT » 9年前

かずま様のNo: 4のコードを構造体を使ったものに修正してみました。

コード:

#include <stdio.h>   // fopen, fclose, fget, fputs
#include <string.h>  // strncmp

int main(void)
{
    struct data_t {
        char s1[256], s2[256], *p1, *p2;  FILE *f1, *f2, *f3;  int d;
    } data;

    data.f1 = fopen("master.dat", "r");      if (!data.f1) return 1;
    data.f2 = fopen("transaction.dat", "r"); if (!data.f2) return 2;
    data.f3 = fopen("result.dat", "w");      if (!data.f3) return 3;
    data.p1 = fgets(data.s1, sizeof data.s1, data.f1);
    data.p2 = fgets(data.s2, sizeof data.s2, data.f2);
    while (data.p1 && data.p2)
        if ((data.d = strncmp(data.p1, data.p2, 5)) < 0)
            fputs(data.p1, data.f3), data.p1 = fgets(data.s1, sizeof data.s1, data.f1);
        else if (data.d > 0)
            fputs(data.p2, data.f3), data.p2 = fgets(data.s2, sizeof data.s2, data.f2);
        else
            (data.p2[5] == ',') && fputs(data.p2, data.f3),
            data.p1 = fgets(data.s1, sizeof data.s1, data.f1),
            data.p2 = fgets(data.s2, sizeof data.s2, data.f2);
    while (data.p1) fputs(data.p1, data.f3), data.p1 = fgets(data.s1, sizeof data.s1, data.f1);
    while (data.p2) fputs(data.p2, data.f3), data.p2 = fgets(data.s2, sizeof data.s2, data.f2);
    fclose(data.f3), fclose(data.f2), fclose(data.f1);
    return 0;
}
monsutonton さんが書きました: 構造体を使う
1個の関数は、60行まで
scanf禁止(fgets等)
という条件をきちんと満たしていますね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 構造体による処理

#29

投稿記事 by みけCAT » 9年前

monsutonton さんが書きました:配列に格納しますか?
読み込んだ文字列は配列または線形リストに格納するのがいいでしょう。
monsutonton さんが書きました:あと、比較処理はstrcmp(fp1,fp2);ですか?
fp1、fp2が何を表しているかがわかりませんが、ファイルポインタを標準ライブラリのstrcmp関数に渡してはいけません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#30

投稿記事 by monsutonton » 9年前

私的には、番号、名前、アドレスをそれぞれ格納。
構造体は変更、追加、消去。
を考えたいです。
みけCATさんお願いします。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 構造体による処理

#31

投稿記事 by みけCAT » 9年前

monsutonton さんが書きました:私的には、番号、名前、アドレスをそれぞれ格納。
構造体は変更、追加、消去。
を考えたいです。
みけCATさんお願いします。
何をお願いするのですか?
考えたいなら自分で考えればいいのではないですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#32

投稿記事 by monsutonton » 9年前

すみません。
考え方ややり方は把握していますが、それをプログラム化できない状況です。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 構造体による処理

#33

投稿記事 by みけCAT » 9年前

monsutonton さんが書きました:考え方ややり方は把握していますが、それをプログラム化できない状況です。
本当に把握しているなら、それをここに書いてください。
もちろん
monsutonton さんが書きました:ファイルを読み取り、配列に入れる。
2つ目のファイルを配列に入れる。
その配列を比べる。

構造体は、変更、追加、消去

が良いとは思うのですが。。。
こんな漠然とした内容ではなく、具体的な内容をお願いします。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#34

投稿記事 by monsutonton » 9年前

追加はこれでできてますか?
またあっていたとしても、ifの中身がわかりません。

コード:

#include<stdio.h>
#include<string.h>
#define NUM 30

int main(void)
{

	char str1[NUM],str2[NUM];
	
	FILE *fp,*fp2,*fp3,*p1,*p2;
	
	fp = fopen("master.dat","r");
	
	if(fp == NULL)
	{
		return 1;
	}
	printf("ファイルをオープンしました\n");
	
	fp2 = fopen("transaction.dat","r");
	
	if(fp2 == NULL)
	{
		return 2;
	}
	printf("ファイルをオープンしました");
	
	fp3 = fopen("result.dat","w");
	
	if(fp3 == NULL)
	{
		return 3;
	}
	printf("ファイルをオープンしました");
	
	while((fgets(str1,NUM,fp))!=NULL)
	{
		printf("%s",str1);
		fputs(str1,fp3);
    }
	
	fgets(str1, NUM-1, fp2);
    fgets(str2, NUM-1, fp3);
	
	if(strstr(str1,str2)!=NULL);
	{
		
	}
	
	fclose(fp);
	fclose(fp2);
	fclose(fp3);
	
	return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 構造体による処理

#35

投稿記事 by みけCAT » 9年前

monsutonton さんが書きました:追加はこれでできてますか?
できてません。
これは追加ではなく、ただのコピーですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

monsutonton
記事: 29
登録日時: 9年前

Re: 構造体による処理

#36

投稿記事 by monsutonton » 9年前

今回の課題は諦めた方が良いですよね。
あまりにも理解していなさすぎ、
皆さんに迷惑をかけている。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 構造体による処理

#37

投稿記事 by みけCAT » 9年前

とりあえず、ファイルからデータを1行読む処理を書いてみました。
バッファオーバーラン対策はしていません。

コード:

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

#define LINE_MAX 256

#define BANGO 50
#define NAME 50
#define ADORESU 50

struct file
{
	char bango[BANGO];
	char name[NAME];
	char adoresu[ADORESU];
};

/* fpから空行を無視して1行読み、struct file型のデータとして格納する。
 * 読めたら読み込んだ列数、読めなかったら-1を返す。
 */
int read_record(struct file *f, FILE* fp)
{
	char data[LINE_MAX];
	char *lf;
	char *target[4] = {f->bango, f->name, f->adoresu, NULL};
	int i, j, k;
	/* 次の空行でない行を読み込む */
	do {
		if (fgets(data, sizeof(data), fp) == NULL) return -1;
	} while (data[0] == '\0' || data[0] == '\n');
	/* 改行文字があれば削除する */
	lf = strchr(data, '\n');
	if (lf != NULL) *lf = '\0';
	/* データを分割して構造体に入れる */
	for(i = j = k = 0;; i++)
	{
		if(data[i] == ',' || data[i] == '\0')
		{
			/* 区切りまたは終わり */
			target[j][k] = '\0';
			j++; /* 次の要素の入力に移る */
			k = 0; /* 最初から保存させる */
			if (target[j] == NULL || data[i] == '\0') break; /* データまたは格納先が無くなったら終わり */
		}
		else
		{
			/* データが連続している */
			target[j][k++] = data[i];
		}
	}
	return j;
}

int main(void) {
	struct file f;
	int num;
	while ((num = read_record(&f, stdin)) >= 0) { /* 読む */
		/* 読んだ結果を出力する */
		printf("num = %d, bango = %s, name = %s, adoresu = %s\n", num, f.bango, f.name, f.adoresu);
		/* 次に備えて読んだデータを「消す」 */
		f.bango[0] = f.name[0] = f.adoresu[0] = '\0';
	}
	return 0;
}
補足:「00007,,nagata@xxxxx.xx.jp」みたいなデータに対応できないので、strtokは使えません。
最後に編集したユーザー みけCAT on 2015年11月08日(日) 20:23 [ 編集 1 回目 ]
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

hoge

Re: 構造体による処理

#38

投稿記事 by hoge » 9年前

まず、課題文を理解するところから始めましょう。

かずま

Re: 構造体による処理

#39

投稿記事 by かずま » 9年前

構造体を使うと、

コード:

#include <stdio.h>   // fopen, fclose, fgets, fprintf
#include <string.h>  // strcmp
 
struct Record {
    char no[10], name[50], address[50];
};

const char *get_field(char *f, const char *p)
{
    while (*p != '\0' && *p != ',' && *p != '\n') *f++ = *p++;
    *f = '\0';
    return (*p != '\0') ? p + 1 : p;
}

int get_record(struct Record *r, FILE *fp)
{
    char s[256];
    if (!fgets(s, sizeof s, fp)) return 0;
    get_field(r->address, get_field(r->name, get_field(r->no, s)));
    return 1;
}

void put_record(const struct Record *r, FILE *fp)
{
    fprintf(fp, "%s,%s", r->no, r->name);
    if (*r->address) fprintf(fp, ",%s", r->address);
    fprintf(fp, "\n");
}

int main(void)
{
    FILE *f1, *f2, *f3;  struct Record r1, r2;  int b1, b2, d;
 
    f1 = fopen("master.dat", "r");      if (!f1) return 1;
    f2 = fopen("transaction.dat", "r"); if (!f2) return 2;
    f3 = fopen("result.dat", "w");      if (!f3) return 3;
    b1 = get_record(&r1, f1), b2 = get_record(&r2, f2);
    while (b1 && b2)
        if ((d = strcmp(r1.no, r2.no)) < 0)
            put_record(&r1, f3), b1 = get_record(&r1, f1);
        else if (d > 0)
            put_record(&r2, f3), b2 = get_record(&r2, f2);
        else {
            if (*r2.name || *r2.address) put_record(&r2, f3);
            b1 = get_record(&r1, f1), b2 = get_record(&r2, f2);
        }
    while (b1) put_record(&r1, f3), b1 = get_record(&r1, f1);
    while (b2) put_record(&r2, f3), b2 = get_record(&r2, f2);
    fclose(f3), fclose(f2), fclose(f1), remove("result.dat");
    return 0;
}

かずま

Re: 構造体による処理

#40

投稿記事 by かずま » 9年前

かずま さんが書きました:構造体を使うと、
get_field() と get_record() を少し変更しました。

コード:

const char *get_field(const char *p, char *f, int n)
{
    char *e = f + n - 1;
    for (; *p && *p != ',' && *p != '\n'; p++)
        if (f < e) *f++ = *p;
    *f = '\0';
    return *p ? p + 1 : p;
}
 
int get_record(struct Record *r, FILE *fp)
{
    char s[256];
    if (!fgets(s, sizeof s, fp)) return 0;
    get_field(get_field(get_field(s, r->no, 10), r->name, 50), r->address, 50);
    return 1;
}

閉鎖

“C言語何でも質問掲示板” へ戻る