CRの削除について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
chibago

CRの削除について

#1

投稿記事 by chibago » 11年前

お世話になっております。
chibagoです。

windowsの改行文字CR+LFからUNIXのLFへ変更するプログラムを
http://www1.cts.ne.jp/~clab/hsample/Fil ... ile03.html
を参考に作っております。

環境はfedora16 gcc4.6.3です。

書いたコードは以下のようなものです。

コード:

  bool FileUtil::remove_cr(const std::string path1,
                           const std::string path2){

    FILE *fp;
    FILE *fp2;
    char string[256];

    if ((fp = fopen(path1.c_str(), "rb")) == NULL) {
      std::cout<<"Can not open "+path1<<std::endl;
      return false;
    }

    if ((fp2 = fopen(path2.c_str(), "wb")) == NULL) {
      std::cout<<"Can not open "+path2<<std::endl;
      return false;
    }

     while ((fgets(string, 256 - 1, fp)) != NULL) {
   /// ここから変更 
       string[strlen(string) - 1] = '\0';        
  ///ここまで変更  
      fputs(string, fp2);                         
    }
    fclose(fp);
    fclose(fp2);
   return true;
  }
これがうまく動かなくて困っております。
考え方としては、binaryモードで読み書きすることにより、
fgets,fputsでは改行文字は変更されないものと理解しております。

上記のプログラムでは、viで開くと^Mが残り、改行がなくなっております。末尾にCR+LFがあり、LFを削除しCR(^M)だけが残ったと考えると納得がいきます。

そこで、以下のように変更しました。

コード:

       string[strlen(string) - 1] = '\0';        
       string[strlen(string) - 2] = '\n';        
これで、初めのCRがLFに置き換わり、後のLFはヌル文字となり無効
になるかと期待したのですが、viで開くとなぜか^Mが残り、次の行の先頭に移っております。

挙動が理解できずどうして良いものかわかりません。

ご教授いただけると幸いです。

トントン
記事: 100
登録日時: 15年前

Re: CRの削除について

#2

投稿記事 by トントン » 11年前

> 挙動が理解できずどうして良いものかわかりません。
確認自体は、

コード:

string[strlen(string) - 1] = '\0';        
string[strlen(string) - 2] = '\n';
の前中後で「strlen(string)」の値を見てみるのと
バイナリエディタで中身を見てみると良いかも知れません。

chibago

Re: CRの削除について

#3

投稿記事 by chibago » 11年前

トントン様、コメントありがとうございました。
結局、考え方を変えて、解決しました。

コード:

       char out[256];
       int j =0;
       for (int i=0; i < strlen(string); i++){
	 if (string[i] != '\r') out[j++] = string[i]; 
       }
       fwrite(out, sizeof(char), strlen(out), fp2);
としました。試行錯誤したため、結局なにが悪かったのか
わかりませんが、一応解決したことをご報告いたします。

上記のルーチンは力技ですし、fputsからfwriteにも変えましたが、
ここら辺にも何かあるのかもしれません。

もしかしたら、コンパイラによって微妙に挙動が異なる部分
かもしれないと感じました。

解決とさせていただきますが、技術的なご示唆をいただくことは
大歓迎です。

きゃりーわんわん
記事: 34
登録日時: 12年前

Re: CRの削除について

#4

投稿記事 by きゃりーわんわん » 11年前

検索するとfgetsはテキストモードでしか使用できないという記載がありました。
http://hitorilife.com/fgets.php

もし上記リンクの記載が正しいのであれば
意図しない動作になるかもしれません。

chibago

Re: CRの削除について

#5

投稿記事 by chibago » 11年前

きゃりーわんわん 様、
ありがとうございました。

fputsもテキストモードで動いており、
誤作動していたのかもしれません。

ありがとうございました。

かずま

Re: CRの削除について

#6

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

chibago さんが書きました:解決とさせていただきますが、技術的なご示唆をいただくことは
大歓迎です。

コード:

    char string[256];
    while ((fgets(string, 256 - 1, fp)) != NULL) {
        char out[256];
        int j =0;
        for (int i=0; i < strlen(string); i++){
            if (string[i] != '\r') out[j++] = string[i]; 
        }
        fwrite(out, sizeof(char), strlen(out), fp2);
    }
fputs() の 256 - 1 の - 1 が無意味です。
for の中で strlen() を何度も何度も何度も呼び出して文字列の長さを
計算し直しているのが非常にに無駄です。
char out[256] にコピーというのも、ちょっと、.....。

次のように書き直すことを強くお勧めします。

コード:

    int c;
    while ((c = fgetc(fp)) != EOF)
        if (c != '\r') fputc(c, fp2);

かずま

Re: CRの削除について

#7

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

chibago さんが書きました:

コード:

       char out[256];
       int j =0;
       for (int i=0; i < strlen(string); i++){
	 if (string[i] != '\r') out[j++] = string[i]; 
       }
       fwrite(out, sizeof(char), strlen(out), fp2);
としました。試行錯誤したため、結局なにが悪かったのか
わかりませんが、一応解決したことをご報告いたします。
解決していません。
out には、'\r' をコピーせず、'\n' はコピーします。
ところが、そのあと '\0' がないので、
strlen(out) がとんでもない値を返します。

きゃりーわんわん
記事: 34
登録日時: 12年前

Re: CRの削除について

#8

投稿記事 by きゃりーわんわん » 11年前

きゃりーわんわん さんが書きました: 検索するとfgetsはテキストモードでしか使用できないという記載がありました。
http://hitorilife.com/fgets.php

すみません、上記リンクを確認すると
テキストモードでしか使用できないという記載ではなく
テキストファイルにしか使用できないという記載でした。
なので、バイナリモードでも使用できます。

ではなぜ一番初めのコードで意図した動作をしないか?ですが、
以下の1行目と2行目とでstrlen()で取得される文字数が変わるからです。
1行目を実行することにより、文字数が変わるため意図する動作となりません。

コード:

       string[strlen(string) - 1] = '\0';        
       string[strlen(string) - 2] = '\n';
chibago さんが書きました: 解決とさせていただきますが、技術的なご示唆をいただくことは
大歓迎です。
では一点だけ。
fp2のopenに失敗した場合returnしていますが、
fpのcloseをしていないため、この場合リークします。

閉鎖

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