文字列の長さがおかしい?

解決


テクノ  2009-01-08 06:42:28  No: 69400

ソースを貼り付けるため,長文になりますがよろしくお願いします。
Visual C++ 2008,Win32コンソールアプリケーションで作成。

今回質問したいことは,ファイルをオープンし,
配列に挿入したときに文字列の長さが一致しないことなんです。

**************************************************
//RLC.TRN(メモ帳で作成)
R1 1 2 10.0//空白は半角スペース1文字分
!          //'!'がきたら終了
**************************************************

"R1 1 2 10.0"を配列に挿入します。
この配列を char cir_data[][] とします。
文字列の長さは"\0"文字を含めない"11"文字になるはずですよね?

ヘッダファイルは以下の通りです。
**************************************************
//Tran.h
#ifndef TRAN_H
#define TRAN_H

class Tran{
public:
  int lp_cnt;
  char cir_data[100][40];
  void file_r();
};

#endif  //TRAN_H
**************************************************

ファイルに関する関数は以下の通りです。
**************************************************
//file.cpp
#define _CRT_SECURE_NO_DEPRECATE 1 //警告抑制
#include "Tran.h"
#include <string>
#include <fstream>
#include <iostream>
using namespace std;

void Tran::file_r(){
  int i;
  string filename("RLC.TRN");
  FILE* fdi = fopen(filename.c_str(), "r");
  for(i=0; ; ){
    fgets(cir_data[i], 50, fdi);
    if(cir_data[i][0] == '!') break;
    if(cir_data[i][0] != '/') i++;
  }
  fclose(fdi);
  lp_cnt = i;
/*******************************
  確認用  実行結果
*******************************/
  cout << cir_data[0] << endl;
  cout << cir_data[1] << endl;
  
  int len_cir0 = strlen(cir_data[0]);
  int len_cir1 = strlen(cir_data[1]);

  cout << "1行目の長さ = " << len_cir0 << endl;
  cout << "2行目の長さ = " << len_cir1 << endl;

  cout << "1行目の10文字目 = " << cir_data[0][9] << endl;
  cout << "1行目の11文字目 = " << cir_data[0][10] << endl;
  cout << "1行目の12文字目 = " << cir_data[0][11] << endl;
  cout << "1行目の13文字目 = " << cir_data[0][12] << endl;
  cout << "1行目の14文字目 = " << cir_data[0][13] << endl;

  int len;
  char s[] = "R1 1 2 10.0";
  len = strlen(s);
  cout << "本当の1行目の長さ=" << strlen(s) << endl;
}
**************************************************

メイン関数は以下の通りです。
**************************************************
//main.cpp
#include "Tran.h"
#include <iostream>

using namespace std;

void main(){
  Tran RLC;
  RLC.file_r();
}
**************************************************

これらをビルドすると,以下のような出力でした。
**************************************************
R1 1 2 10.0

1行目の長さ = 12
2行目の長さ = 2
1行目の10文字目 = .
1行目の11文字目 = 0
1行目の12文字目 = .

1行目の13文字目 = 
1行目の14文字目 = フ
本当の1行目の長さ=11
続行するには何かキーを・・・
**************************************************

この結果で疑問なのは,なぜ余計な空白の行が入ってしまうのだろうということです。
そこで,文字列の長さを調べてみると,11文字のはずが12文字と出てしまいました。
次に,12文字目を調べてみると,やはりなぜか空白行が挿入されていました。

今後プログラミングを行う際,文字列をコピーしたり連結したりするので,
ここがはっきりしないと先に進めなくて困っています。
ヌル文字は12文字目にあるのか?13文字目にあるのか?
その場合12文字目には何が含まれているんだろう?

ファイルのオープンの仕方がまずいのでしょうか?
ピタっとデータファイルの1行目を11文字+"\0"という風に挿入するにはどうしたらいいのでしょうか。

長文失礼しました。よろしくお願いします。


テクノ  2009-01-08 06:45:49  No: 69401

すいません、訂正です。

出力結果の"1行目の12文字目 = ."
ではなく,"1行目の12文字目 =  "(空白)です。


瀬戸っぷ  2009-01-08 07:48:17  No: 69402

>ヌル文字は12文字目にあるのか?13文字目にあるのか?
>その場合12文字目には何が含まれているんだろう?

改行コードじゃないですか?
Windowsでは改行コードは'\r'と'\n'の2バイトになります。

バイナリエディタでそのファイルを開いてみたり、読み込んだ内容を16進数で表示してみたりしては?


テクノ  2009-01-08 09:54:57  No: 69403

瀬戸っぷさん,回答ありがとうございます。

バイナリエディタで開いてみたら,
0D 0A という改行コードが書きこまれていました。
調べたら,メモ帳で改行する際にOSが勝手に書きこんでしまうらしいとのこと。

ファイルを開いたときに改行コードまで文字列に挿入したくないのですが,
そのような方法がありましたら教えてください。


Blue  2009-01-08 10:20:49  No: 69404

というかfgetsの結果に'\n'が付いているだけなのでは?
(\r\nは関係ない。fopenでテキストモードで開けは\rは勝手に取られる。)

> fgets(cir_data[i], 50, fdi);
の直後に
char* pLF = strchr(cir_data[i], '\n');
if (pLF != NULL) {
    *pLF = '\0';
}
というように'\n'が末尾についていたら'\0'に書き換えるという記述を加えておくとか。


テクノ  2009-01-08 19:13:01  No: 69405

Blueさん,回答ありがとうございます。

上記のプログラムを追加したら,期待通りの動作をしてくれました。
\nに出会うまでと思っていたら,\nも含んでしまっていたんですね。

おかげ様で先に進めます。ありがとうございました。


テクノ  2009-01-08 19:13:58  No: 69406

解決しました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加