C言語関係掲示板

過去ログ

No.1133 ファイル操作

[戻る] [ホームページ]
No.2035

ファイル
投稿者---中村(2004/06/15 16:33:43)


すいません。
掲示板http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200406/04060035.txtに投稿した内容なのですが、
初心者ゆえ、全く進展がないのが現状です。
しかし、このお話には興味があり、向上心はあります。ぜひともこの方法を習得したいと思います。
参考図書、インターネットを調べましたが、それにそった内容のものに縁がなく悩んでいます。
どうか、皆さんのお力を貸していただけないでしょうか。
教えてください。お願いします。


入力用のファイルをオープンする。
1行読み込んで何列あるか数える。
列数分、ファイルポインタ型の配列を確保する。

列数分繰り返し・ここから
  出力用ファイル名を生成する。
  出力用ファイルをオープンする。
列数分繰り返し・ここまで

行数分繰り返し・ここから
  入力用ファイルから1行読み込む。
  列数分繰り返し・ここから
    空白文字をデリミタにして、1トークン切り出す。
    切り出したトークンを、然るべき出力用ファイルに出力する。
  列数分繰り返し・ここまで
行数分繰り返し・ここまで


入力用ファイルをクローズする。
列数分繰り返し・ここから
  出力用ファイルをクローズする。
列数分繰り返し・ここまで




No.2038

Re:ファイル
投稿者---えとな(2004/06/15 17:19:09)


マルチポストはやめましょう。
向こうで教えてもらった内容をコピペして張り付けるなんて
教えてくれている方に失礼だとは思わないんですか?
向こうで教えてもらったことを一つずつやってみれば
少しはわかってくると思いますよ。
それとも、まさか解となるソースを載せてほしいわけじゃ
ないですよね?


No.2039

ファイル
投稿者---中村(2004/06/15 17:26:20)


マルチはわかっていて投稿しました。
回答を前の掲示板に反映します。


No.2041

Re:ファイル
投稿者---かずま(2004/06/15 19:23:40)


> しかし、このお話には興味があり、向上心はあります。ぜひともこの方法を
> 習得したいと思います。

その方法でなくても申し訳ありませんが、別の方法を提示します。

----------------------------------------------------------------------
    入力用のファイルをオープンする(標準入力を使ってもよい)。

    1行読み込んで、文字列を切り出し、charポインタの配列に複写する。
    使用した配列の要素の個数が、列の個数である。

    ファイルの最後まで
        文字列を charポインタの配列に読み込む。

    列数分繰り返し・ここから
      出力用ファイル名を列番号から生成する。
      出力用ファイルをオープンする。
        その列の文字列をすべて出力する。
      出力用ファイルをクローズする。
    列数分繰り返し・ここまで
----------------------------------------------------------------------

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

#define N  10000

int main(void)
{
    char *str[N], buf[1024], *p;
    int n = 0, i, j, col;
    FILE *fp;

    if (fgets(buf, sizeof buf, stdin) == NULL) puts("no data"), exit(1);

    for (p = buf; p = strtok(p, " \t\n"); p = NULL)
        str[n++] = strdup(p);
    col = n;

    while (scanf("%s", buf) == 1) {
        if (n == N) puts("too many data"), exit(1);
        str[n++] = strdup(buf);
    }

    for (i = 0; i < col; i++) {
        sprintf(buf, "file%02d.txt", i+1);
        fp = fopen(buf, "w");
        if (fp == NULL) puts("can't create output file"), exit(1);
        for (j = i; j < n-col; j += col)
            fprintf(fp, "%s ", str[j]);
        fprintf(fp, "%s\n", str[j]);
        fclose(fp);
    }
    return 0;
}

質問の方法と共通する部分がどこだか分かりますか?



No.2214

ファイル操作
投稿者---中村(2004/07/02 20:28:53)


前回は本当にお世話になりました。有難うございました。
あれから、自分でソースを完成させてここに提示したかったのですが、以下のままでつまづき、進むことが出来ません。考えてはいるのですが、かずまさんに教えていただいた

列数分繰り返し・ここから
  出力用ファイル名を列番号から生成する。
  出力用ファイルをオープンする。
その列の文字列をすべて出力する。
  出力用ファイルをクローズする。
列数分繰り返し・ここまで
の部分で出力することが出来ません。
もしよろしければ、ご教授していただきたいです。
お手数お掛けいたしますが、宜しくお願いいたします。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N  1000

int main(void)
{
    char *str[N], buf[1024], *p,*q;
    int n = 0, i, j, col;
    FILE *fp;
  
/* ファイルのオープン */
/* ここで、ファイルポインタを取得する */
if ((fp = fopen("test.txt", "r")) == NULL) {
printf("file open error!!\n");
exit(1); /* エラーの場合は,異常終了する */
}

//

//if (fgets(buf, sizeof buf, fp) == NULL) puts("no data"), exit(1);

while (fgets(buf, sizeof buf, fp) != NULL) {
if (fp == NULL) return 1;

/* ここではfgets()により1行単位で読み出し */
printf("%s", buf);

}
  
    for (p = buf; (q = strtok(p," \t\n")) != NULL; p = NULL)
  {
        str[n++] = strdup(q);
  
    //n++;

    col = n;
  }
  printf("%d\n",col);
 printf("%s\n",*str); 

    while (scanf("%s", buf) == 1) {
        if (n == N) puts("too many data"), exit(1);
        str[n++] = strdup(buf);
   
  }
printf("%s\n", *str); 


    for (i = 0; i < col; i++) {
        sprintf(buf, "file%02d.txt", i+1);
        fp = fopen(buf, "w");
        if (fp == NULL) puts("can't create output file"), exit(1);
        for (j = i; j < n-col; j += col)
      fprintf(fp, "%s ", str[j]);
        printf( "%s\n", str[j]);
            printf( "%s ", str[j]);
        fprintf(fp, "%s\n", str[j]);
        fclose(fp);
    }
    return 0;
}



No.2217

Re:ファイル操作
投稿者---RAPT(2004/07/03 09:43:14)


col は初期化しないとまずいですね。
最初に読み込んだ行が無効な行だった場合、未初期化の変数を
参照することになってしまいます。
while (fgets(buf, sizeof buf, fp) != NULL) {
  if (fp == NULL) return 1;

  
/* ここではfgets()により1行単位で読み出し */
  printf(
"%s"
, buf);
}
なんでここで (fp == NULL)のチェックが必要なのでしょうか?

それから、whileループがここで完結していますが、当該処理は
最終行を抽出するのが目的でしょうか?
コメントでは、読み出した1行ごとに処理を行なうような印象を
受けたのですが。
printf(
"%d\n"
,col);
printf(
"%s\n"
,*str);
これは、1つ目のデータを参照しようとしていますが、データ
個数が0のとき、アクセス違反となります。

while文直後の
printf(
"%s\n"
, *str);
これではwhile文直前のデータと同じモノを表示しようとして
いますが、意図した処理でしょうか?
fp = fopen(buf, 
"w"
);
この文が実行される前に、読み出しファイルのクローズが行わ
れていません。このままでは読み出しファイルが壊れる可能性
があります。
for (j = i; j < n-col; j += col)
  fprintf(fp, 
"%s "
, str[j]);
このfor文は、(j < n-col) の評価結果は常に偽なので、直後の
fprintf()文は実行されることはありません。

for文の前に、
fprintf(stderr, "i = %d, j = %d, n = %d, col = %d, j < n-col = %s\n",
  i, j, n, col, (j < n-col) ? "true" : "false");
とでも記載し、値の変化を確認するといいでしょう。

以上、脳内トレース結果でした。ご確認ください。



No.2218

Re:ファイル操作
投稿者---中村(2004/07/03 13:24:36)


ご返信有難うございました。
PARTさんのご助言を下に現在考えております。
><pre>col は初期化しました。
for文の前に、
fprintf(stderr, <font color="#0000ff">"i = %d, j = %d, n = %d, col = %d, j < n-col = %s\n"</font>,
i, j, n, col, (j < n-col) ? <font color="#0000ff">"true" : "false"</font>);
とでも記載し、値の変化を確認しようとしているのですが、出力できません。
なぜでしょうか。



No.2223

Re:ファイル操作
投稿者---RAPT(2004/07/04 14:31:05)


そうか、ファイル読み込み後にデータが何かしら入力されたらfor文内が
実行されうるな。ってことでサンプルソース。
# 相変わらず何がやりたいのかわからなかったから、ファイル出力だけは
# 元のソースと同じものを出力するようにした。
Windows2000sp4/VC++6.0sp6/Console-App


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

#define N  1000

int main(void)
{
  char *str[N] = {0}, buf[1024] = {0}, *p = NULL, *q = NULL;
  int n = 0, i = 0, j = 0, col = 0;
  FILE *fp = NULL;

  fp = fopen("test.txt", "r");
  if (fp == NULL){
    printf("file open error!!\n");
    exit(1);
  } 

  while (fgets(buf, sizeof buf, fp) != NULL){
    printf("%s", buf); 
  }
  fclose(fp);
  
  for (p = buf; (q = strtok(p," \t\n")) != NULL; p = NULL){
    str[n++] = strdup(q);
  }
  col = n;
  while(n < N && scanf("%s", buf) == 1){
    str[n++] = strdup(buf);  
  }

  for (i = 0; i < col; i++) {
    sprintf(buf, "file%02d.txt", i+1);
    printf("FILE = %s\n", buf); // check

    fp = fopen(buf, "w");
    if (fp == NULL){
      puts("can't create output file");
      goto END;
    }
    for (j = i; j < n - col; j += col){
      printf("---for---:[%s]\n", str[j]); // check

      fprintf(fp, "%s ", str[j]);
    }
    printf("%s\n", str[j]); // check

    fprintf(fp, "%s\n", str[j]);
    fclose(fp);
  }

END:
  for(i = 0; i < n; i++){
    free(str[i]);
  }
  return 0;
}