C言語関係掲示板

過去ログ

No.35.ファイルのシャッフル


はじめまして。
Cを初めて間もないのですが、HP参考にさせてもらっています。
私のような初心者には、大変ありがたいです。
さて、少しヒントをください。
「ファイルの内容をシャッフルして別ファイルに保存する」というようなプログラムを考えているのですが、シャッフル部がどうやったらいいのかさっぱりなのです。
例えば、ファイルaaa.txtの内容が
abcdef
ghijklmn
opqrstu
vwxyz
とした場合、
vwxyz
ghijklmn
abcdef
opqrstu
というように行単位でシャッフルして別ファイルbbb.txtへ保存したいのです。
だらだらと長く書いてしまいましたが、ヒントだけで良いのでもらえないでしょうか?


大文字MASAさんこんにちは。小文字のmasaです。

まず列を読み込む配列を作ります。
それに一行づつaaa.txtから読み込ませてから、
stdlib.hのrand()を使って適当に選択してbbb.txtへ書き出します。
同じ要素を2回選択しないようにする工夫も必要です。
MASAさんがんばってねー。from masa


大文字MASAさん、小文字のmasaさん今晩は。
小文字のmasaさん、いつも書き込みありがとうございます。

ファイルの大きさがある程度大きい場合は、配列よりmallocの方がいいと
思ったのでプログラム組んでみました。
#課題だったら、ちゃんと自分で考え直してみてくださいね。

中で stat を使っています。ファイル情報を取ってくる関数です。
ANSIの関数ではないので、使えなかったら、自分でサイズを数えてください。

/*** ファイルシャフルプログラム ***/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys\stat.h>
int main(void)
{
        FILE    *fin,*fout;
        struct  stat fileinfo ;
        char    infile[40],outfile[40];
        char    wk[300],*bufp,*pp[1000];
        int     i=0,j,r;

        printf("入力ファイル名=");
        gets(infile);
        printf("出力ファイル名=");
        gets(outfile);
        if( (fin=fopen(infile,"r"))==NULL) {
                printf("入力ファイルがオープンできません\n");
                exit(1);
        }
        if( (fout=fopen(outfile,"w"))==NULL) {
                printf("出力ファイルがオープンできません\n");
                exit(1);
        }
        /* ファイル情報の取得 */
        if( stat( infile, &fileinfo ) == -1 ){
                fprintf( stderr,"%sのファイル情報取得に失敗しました\n",infile ) ;
                exit( 1 ) ;
        }
        /* 読み込みエリアの取得 */
        if ( (bufp = (char *)malloc(fileinfo.st_size))==NULL) {
                fprintf( stderr,"mallocエラー\n");
                fclose(fin);
                fclose(fout);
                exit(1);
        }
        /* ファイルの読み込み */
        i = 0;
        pp[0] = bufp;
        while(fgets(wk,256,fin)!=NULL) {
                strcpy(pp[i],wk);
                i++;
                pp[i] = pp[i-1] + strlen(wk) + 1;
        }
        /* ファイルのシャフル */
        j = 0;
        while(j<i) {
                r = rand()%i;
                if (pp[r]!=NULL) {
                        fputs(pp[r],fout);
                        pp[r] = NULL;
                        j++;
                }
        }
        free(bufp);
        fclose(fin);
        fclose(fout);
        return(0);
}


masaさん、ともじさんこんにちわ。
早速のレスありがとうございます。
別に課題というわけではなく、単に自分でこういうの作ってみようと思っただけです(Cの勉強のために)。
参考にさせてもらいながら、自分でも考えたいと思います。
力不足な面が多いもので、また御願いするかもしれませんが、その時は宜しく御願いします。
完成したら、またカキコしますね。


みなさんこんにちわ。
ともじさんが考えてくれたプログラムですが、大変参考になりました。(statは使えませんでしたが・・・。)
やっぱりプログラミングを勉強するときには色々なプログラムを見て、書いて、実行してみるのが一番だと痛感しました。
有り難う御座います。

さて、今回はちょっと疑問が出てきましたので投稿させて頂きました。
書き込みファイルを出力するときに、
        printf("出力ファイル名=");
        gets(outfile);

        if( (fout=fopen(outfile,"w"))==NULL) {
                printf("出力ファイルがオープンできません\n");
                exit(1);

と書きますが、"w"や"a"モードの時はファイルがない場合新規で作成しますよね?
とすると、「printf〜」が要らないのでわ?と考えてしまったのですが、何故「printf〜」の文が必要なのでしょうか?
ファイルが無いときのフェールセーフだと思っていたもので・・・。


すでに出力ファイルと同名のファイルがある場合”w”だと上書きされます。
”a”だと付け足されます。
さらに、その同名ファイルがすでに他のアプリケーションなどに開かれていると、
開けないよ〜っと悲鳴をあげます。

小文字masa。


こんにちわ、小文字のmasaさん。
なるほど、なるほど、そういうことだったのですか。
今まで慣例的に書いていたので、あまり意味を考えて無かったのですよ。
まぁ、これ以外にも意味わからずに使用しているのがあると思いますが。
これからも、宜しく御願いしますね。

>さらに、その同名ファイルがすでに他のアプリケーションなどに開かれていると、
>開けないよ〜っと悲鳴をあげます。

戻る


「初心者のためのポイント学習C言語」 Last modified:2001.8.8
Copyright(c) 2000-2002 TOMOJI All Rights Reserved