【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※返信付き投稿の削除は禁止!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら


本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.22646

ファイル関連の質問
投稿者---rina(2005/08/15 15:59:15)


ファイルに入力された文字列を読み込んで別のファイルに順番に出力させるプログラム。
(条件) ・入力ファイルはカンマ区切り 例),aaa,bbb,ccc,ddd,
・文字列の左隣に99:までのカウンターを配置 例)00:aaa 01:bbb
    ・処理終了時に出力件数と入力件数を画面に表示
    ・ファイル出力件数が100を超えたときそれ以後は出力せずに
     正常終了させる。
    ・入力件数が0件の時はファイル出力を行わない。


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

//出力カウンター
void count( int *i, int *j, FILE *fpo )
{
    fprintf( fpo, "%d%d:", *j, *i);
    if( *i == 9 ){
        if( *i == 9 && *j == 9){
            exit(1);
        }
        *j = *j + 1;
        *i = *i - 9;
    }else{
        *i = *i + 1;
    }
    return 0;
}

int main()
{
    FILE *fpin;        //ファイルポインタ
    FILE *fpo;
    char fnamein[64];  //ファイル名用配列
    char fnameo[64];   //ファイル名用配列
    char c;
    int i = 0;
    int j = 0;

//読み込みファイルオープン
    printf("読み込むファイル名を入力:");
    scanf( "%s", fnamein);
    if( ( fpin = fopen( fnamein,"r" ) ) == NULL ){
        fprintf( stderr, "\n %s はオープンできませんでした\n", fnamein);
        exit(1);
    }
//出力ファイルオープン    
    printf("出力するファイル名を入力:");
    scanf( "%s", fnameo);
    if( ( fpo = fopen( fnameo,"w" ) ) == NULL ){
        fprintf( stderr, "\n %s はオープンできませんでした\n", fnameo);
        exit(1);
    } 

//一文字づつ処理   
    while( ( c = getc( fpin ) ) != EOF ){
        if( c == ',' ){
            fprintf( fpo, "\n" );
            count( &i, &j, fpo);
            
            
        }else{
            putc( c, fpo );
        }
    }
    
    fclose(fpin);
    fclose(fpo);
    return 0;
    
}


途中まで作って見ましたが、あまりすっきりしません。
よいアドバイスがありましたらよろしくお願いします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:ファイル関連の質問 22647 まきじ 2005/08/15 16:17:34
<子記事> Re:ファイル関連の質問 22649 Blue 2005/08/15 16:33:33
<子記事> Re:ファイル関連の質問 22650 shu 2005/08/15 17:23:35


No.22647

Re:ファイル関連の質問
投稿者---まきじ(2005/08/15 16:17:34)


>(条件) ・入力ファイルはカンマ区切り 例),aaa,bbb,ccc,ddd,
> ・文字列の左隣に99:までのカウンターを配置 例)00:aaa 01:bbb
>    ・処理終了時に出力件数と入力件数を画面に表示
>    ・ファイル出力件数が100を超えたときそれ以後は出力せずに
>     正常終了させる。
>    ・入力件数が0件の時はファイル出力を行わない。

(1) カウント変数の初期化
(2) fgets() で 一行ずつ読み込み、strtok() で カンマで区切る。
(3) それぞれを、fputs() あるいは fprintf() で、カウント変数と共にファイルに出力。
(4) カウント変数が 100 になるか、入力ファイルが EOF になるまで
  (2) (3) を繰り返す。
(5) カウント変数を出力


この投稿にコメントする

削除パスワード

No.22649

Re:ファイル関連の質問
投稿者---Blue(2005/08/15 16:33:33)


カウンタの数値表示ですが、
fprintfの書式指定文字列(第二引数)を使えば、2桁の数値を出すことが可能です。

fprintf( fpout, "%02d:", n );

よって、99を超えたかどうかの判定だけでいいような気がします。

ファイル読み込みのところは、まきじさんがおっしゃっていますが、
簡明さをもとめるならば、fgets,strtokを使ったほうがいいです。



この投稿にコメントする

削除パスワード

No.22651

Re:ファイル関連の質問
投稿者---rina(2005/08/15 17:36:54)


以下の部分を変更したんですが、

int count( int *cnt )
{   
    if( *cnt == 100 ){
        exit(1);
    }else{
        return ( *cnt + 1 ); 
    }
 
}

---------------------------------------------------------

while(fgets(str, 256, fpin ) != NULL ){
        count( &cnt );
        fprintf( fpo, "%02d:", count( &cnt ) );
        fputs( str, fpo );
    }


strtokを使わないで、if文か何かでできないのでしょうか?


この投稿にコメントする

削除パスワード

No.22652

Re:ファイル関連の質問
投稿者---まきじ(2005/08/15 17:45:40)


>strtokを使わないで、if文か何かでできないのでしょうか?

22646 で遣られてる様に、1 文字ずつ、カンマか否かを調べていくしか
ないです。

あと、fscanf() とか。


この投稿にコメントする

削除パスワード

No.22653

Re:ファイル関連の質問
投稿者---rina(2005/08/15 17:50:59)


shuさんのソースを使わせていただいて、

while (fgets( str, sizeof str, fpin )){
            for (p = strtok( str, "," ); 
             p != NULL; p = strtok( NULL, "," ) )
                printf( "%02d: %s\n", count( cnt ), p );
        }


こう変更しました。
カウンターが増加しないのですが、カウンタ関数が変ですか?


この投稿にコメントする

削除パスワード

No.22655

Re:ファイル関連の質問
投稿者---まきじ(2005/08/15 18:14:45)


>カウンターが増加しないのですが、カウンタ関数が変ですか?
>printf( "%02d: %s\n", count( cnt ), p );

count( cnt ) は count( &cnt ) ですね。

ポインタなら、return する必要はない、
逆に return するなら ポインタにする必要はないかと。

あと、strtok() は使わないのでは?


この投稿にコメントする

削除パスワード

No.22656

Re:ファイル関連の質問
投稿者---rina(2005/08/15 18:27:03)


ありがとうございます。
カウンタが正常になりました。

>あと、strtok() は使わないのでは?
使わずにできるならその方がいいのですが…




この投稿にコメントする

削除パスワード

No.22650

Re:ファイル関連の質問
投稿者---shu(2005/08/15 17:23:35)


細かいところまでは、作っていません。
使えるところがあれば、利用してみてください。

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

//
#define FILE_IN "test.dat"

//
int main( void )
{
    //
    FILE *fp = NULL;
    char buf[BUFSIZ] = "", *p;
    int i = 0;
    
    //
    if ((fp = fopen( FILE_IN, "r" )) == NULL)
        exit( 1 );
    
    //
    while (fgets( buf, sizeof buf, fp ))
        //
        for (p = strtok( buf, "," ); p != NULL; p = strtok( NULL, "," ))
            printf( "%2d: %s\n", i, p );
    
    //
    fclose( fp );
    
    return 0;
}



この投稿にコメントする

削除パスワード

No.22654

Re:ファイル関連の質問
投稿者---rina(2005/08/15 17:56:40)


for文のところってどういう処理をしてるんですか?


この投稿にコメントする

削除パスワード

No.22658

Re:ファイル関連の質問
投稿者---Blue(2005/08/15 18:52:10)


>        for (p = strtok( buf, "," ); p != NULL; p = strtok( NULL, "," ))
>            printf( "%2d: %s\n", i, p );
p = strtok( buf, "," );
while( p != NULL )
{
    printf( "%2d: %s\n", i, p );    // i=0のままだと思うのですが。。。
    p = strtok( NULL, "," );
}

ならわかりますか?

for文は

for (初期化式; 継続条件式; 再初期化式)
ですから、それから while文にしてみるとわかりやすいかと。



この投稿にコメントする

削除パスワード

No.22662

Re:ファイル関連の質問
投稿者---rina(2005/08/16 10:52:13)


Blueさん、shuさんありがとうございます。
理解できました。

//出力カウンター
int count( int *cnt )
{   
    if( *cnt == 99 ){
        printf("出力件数:%02d\n", *cnt);
        exit(1);
    }else{
         return (*cnt = *cnt + 1); 
    }
 
}
------------------------------------------
while( fgets( str, 256, fpin) ){
        p = strtok( str, "," );      
        while( p != NULL )
        {
            printf( "%02d: %s\n", count(&cnt), p );
      p = strtok( NULL, "," );
        }
    }
    printf( "\n出力件数:%02d\n", count( &cnt )-1 );

        
return 0;
    
}


このように変更しました。
count関数の中で、99をカウントしたら終了し、出力件数を表示させるようにしましたが、入力件数を表示させる場合、もし入力件数120件だとしたら、(出力件数:99件 入力件数:120件)とさせる場合どうしたらいいのでしょうか?


この投稿にコメントする

削除パスワード

No.22664

Re:ファイル関連の質問
投稿者---まきじ(2005/08/16 11:26:55)


>もし入力件数120件だとしたら、(出力件数:99件 入力件数:120件)とさせる場合どうしたらいいのでしょうか?
if(count(&cnt) < 100){
    printf( "%02d: %s\n", cnt, p );
    out_cnt = cnt;
}



この投稿にコメントする

削除パスワード

No.22668

Re:ファイル関連の質問
投稿者---rina(2005/08/16 14:55:37)


ファイルから読み込んだカンマ区切りの文字列を構造体に格納して表示させるってできるのでしょうか?
例えば、aaa,bbb,ccc,dddを読み込んで、構造体の中の変数に割り振るって可能ですか?初期化みたいな感じで…


この投稿にコメントする

削除パスワード

No.22669

Re:ファイル関連の質問
投稿者---まきじ(2005/08/16 15:17:37)


>例えば、aaa,bbb,ccc,dddを読み込んで、構造体の中の変数に割り振るって可能ですか?

構造体のメンバ 1 つずつへの代入で良ければできます。
メンバが 10 個あれば、10 個の代入文。


この投稿にコメントする

削除パスワード

No.22670

Re:ファイル関連の質問
投稿者---rina(2005/08/16 15:32:58)


>構造体のメンバ 1 つずつへの代入で良ければできます。
>メンバが 10 個あれば、10 個の代入文。

そうなんですか。では構造体を
struct{
   char a[100];
   char b[100];
   char c[100];
};

こうした場合前のプログラムだとwhile文の中に代入文が3個必要に
なるわけですね?


この投稿にコメントする

削除パスワード

No.22671

Re:ファイル関連の質問
投稿者---まきじ(2005/08/16 15:37:48)


>こうした場合前のプログラムだとwhile文の中に代入文が3個必要に
>なるわけですね?

そうです。

1 つ、1 つ 質問して確認するんではなくて
実際コーディングしてみてはいかがでしょうか?

それで、できなかったら質問して下さい。


この投稿にコメントする

削除パスワード

No.22672

Re:ファイル関連の質問
投稿者---rina(2005/08/16 17:00:00)


>構造体のメンバ 1 つずつへの代入で良ければできます。
>メンバが 10 個あれば、10 個の代入文。

typedef struct{
    char name[30];
    int  yubin[7];
    char add1[16];
    char add2[100];
    char add3[100];
    char tel[14];
    char sex[1];
    int  age[3];
}CARD;

void shori( FILE *infp ){

    CARD mem[100];
    char str[256];
    char *p;
    int cnt = 0;

     while( fgets( str, 256, infp ) ){
        p = strtok( str, "," );      
        while( p != NULL )
        {
            printf( "%02d: %s\n", count(&cnt), p );
            p = mem->name;
            p = mem->yubin;
            p = mem->add1;
            p = mem->add2;
            p = mem->add3;
            p = mem->tel;
            p = mem->sex;
            p = mem->age;
            p = strtok( NULL, "," );
        }
    }
    printf( "\n出力件数:%02d  入力件数:%02d\n", count( &cnt )-2, count( &cnt )-1 ); 
    
    
    
    printf("名前: %s\n", mem -> name);
    printf("郵便: %s\n", mem -> yubin);
    printf("住所: %s%s%s\n", mem -> add1, mem -> add2, mem -> add3);
    printf("電話: %s\n", mem -> tel);
    printf("性別: %s\n", mem -> sex);
    printf("年齢: %s\n", mem -> age);
}

変更してみましたが、うまく格納できません。
代入文が間違ってますか?


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧