空白を含む文を10文字ずつ読み出そうとしています。でも
文1:I am a poor programmer.
文2:2nd Sentence
結果:2nd Sentenr programmer.
となります。"I am a poo"が欲しいのですが。
800文字以内にするためにmainだけにしました。後で補足できます。
int main()
{
sentence sntc;
fstream file;
file.open("SENTENCE.TXT", ios::app | ios::out | ios::in | ios::binary );
sntc.getData();
file.write( reinterpret_cast<char*>(&sntc), sizeof(sntc) );
file.seekg(0, ios::end);
int endposition = file.tellg();
int n = endposition / sizeof(sentence);
cout << "\nThere are " << n << " sentences in file";
cout << "\nEnter sentence number: ";
cin >> n;
int position = (n-1) * sizeof(sentence);
file.seekg(position);
file.read( reinterpret_cast<char*>(&sntc), sizeof(sntc) );
sntc.showData();
cout << endl;
file.seekg(position, ios::cur);
file.read( reinterpret_cast<char*>(&sntc), 10);
sntc.showData();
cout << endl;
return 0;
}
No.3ベストアンサー
- 回答日時:
ひさしぶりにストラウストラップ本を見返してみました。
やはり、readでは\0が付加されないようです。
(『プログラミング言語C++第3版』§21.3.4)
seekgの前でちゃんと表示されたのは、ファイルからではなく、
getData()によって入力されたからでしょう。
この場合、自動的にヌルが付加されます。
ファイル読み込みに、read()ではなく、
getline()を使うと良いと思います。
ただ、やっぱりこのキャストはおかしい。
こうやって入力すると、たまたまsentence内のstrに
データが入るかもしれませんが、
オブジェクトの使い方としてはいただけません。
代案として、
(1)strをpublicにして、
file.getline(sntc.str, 11);
のようにする。
(2)バッファを使い、sentenceにsetStr, getStrメソッドを付加して、
char buf[80];
file.getline(buf, 11);
sntc.setStr(buf);
のようにする。
これ以上はわからないので、
C++に詳しい人の登場を待ちます。
解決しました!
一つ目の問題は私の「テストで表示」がいけなかったみたいです。
あの行のお陰で「本番の表示」のときには既に駒が一つ進んでました。
二つ目の問題はどうも
//file.seekg(position, ios::cur);
の行が邪魔をしていたようです。
下の通りに修正しました。
int main()
{
sentence sntc;
fstream file;
file.open("SENTENCE.TXT", ios::app | ios::out | ios::in | ios::binary );
sntc.getData();
file.write( reinterpret_cast<char*>(&sntc), sizeof(sntc) );
file.seekg(0, ios::end);
int endposition = file.tellg();
int n = endposition / sizeof(sentence);
cout << "\nThere are " << n << " sentences in file";
cout << "\nEnter sentence number: ";
cin >> n;
int position = (n-1) * sizeof(sentence);
file.seekg(position);
for(int i=0; i<5; i++)
{
position = file.tellg();
cout << position;
//file.seekg(position, ios::cur);
file.read( reinterpret_cast<char*>(&sntc), 10);
sntc.showData();
cout << endl;
}
return 0;
}
オリジナルの文は
"I am on my way to becoming a great C++ programmer."で
結果はこんな風です。
0
Sentence: I am on myB
10
Sentence: way to beB
20
Sentence: coming a gB
30
Sentence: reat C++ pB
40
Sentence: rogrammer.B
Press any key to continue
(Bがついていますが…気にしないでください(~o~))
結局、readとreinterpret_cast<char*>はそのままなのですが
getlineの発想から何がおかしいか発見できました。
liar_adanさんの回答がなかったらここまで辿り着けなかったと思います。
なるべく自分で解くように努力しますが、躓くだろうことは必至ですから
これからもどうかよろしくお願いします。m(__)m
ありがとうございました。
No.2
- 回答日時:
う~~ なんてこったい。
せっかく朝、新規の質問2つに解答を書いて、その後を楽しみにして覗いてみたら、2つとも消えてるではないですか。(これは質問者に言っているのではないですよ。
あくまでも管理人さんのほうです)
C++については良く分かりませんが、
1.コード1行づつに何をやってるのか書いてもらえればどこがおかしいか分かると思いますよ。
2.>結果:2nd Sentenr programmer.
>となります
推測ですが、1回目の読み込みのデータが残っているわけだから、それがあなたの期待に反するC++の仕様なら、自分で1回目のデータを消してから、2回目のデータを読み込めば良いのではないでしょうか?
答えてくださってたんですね。
どうやら、私の目に留まる前に消えたみたいですね。(>_<)
1. もともとのプログラムには一行一行丁寧に説明がありましたが、800字以内に収めないとここに載せられないので割愛しました(これが#1で述べている連続した質問をした理由です)。
2. それは確かに気付きませんでした。それで早速やろうと思ったのですが…クリアする方法が分かりませんでした。もうこの教科書、駄目です。5cmくらいの厚さがあるんですが、例題も目録も使えません。それ以前に私が駄目駄目ちゃんなんですが(爆)
ありがとうございました。
No.1
- 回答日時:
新しい質問が削除されてしまったようですね。
最近、規則が厳しくなって、
連続している質問は禁止されたんですよ。
で、私はCはちょっと自信がありますが、
C++はよく知りません。
見当で書きますが的はずれだったらごめんなさい。
問題は、file.read()で、10文字読み込んだところで
ヌル文字が書き込まれないことではないでしょうか。
char *による文字列は終端に\0が付かないとそのまま続いてしまいます。
10文字読み込んだ後に、11文字目に'\0'を書き込む作業が必要になります。
ところで、sentenceというのはどうもクラスのようですが、
これにreinterpret_castを使って文字列を書き込むのは、
どう考えてもおかしいような気がします。
クラスのメンバとしてchar txt[100];のようにして、
file.read(sentence.txt, 100);
とか
file.read(sentence.txt, 10);
とかする方が普通ではないでしょうか。
もう一度言いますが、私はC++は詳しくないので、
間違ったことを言ってるかもしれません。
お許しください。
はい、連続している質問は禁止されたのは知っていましたが、そうでもしないとC++のプログラムなんかは全部載らないんですよね。かといって削ると「質問が分からない」と過去に何度かケチつけられましたし…。それならば800文字の制限をなんとかしてもらいたいですよね、OKWebさん...。
でもliar_adanさんが回答下さったお陰でmain以外のパートもやっと公開できます。感謝します!
#include <fstream>
#include <iostream>
using namespace std;
class sentence
{
protected:
char str[80];
public:
void getData()
{
cout << "\n Enter a sentence: ";
cin.get(str, 80, '\n');
}
void showData()
{
cout << "\n Sentence: " << str;
}
};
問題は大きく分けて二つです。
・一つ目は"2nd Senten"ではなくて"I am a poo"の10文字を表示させたいこと。
positionの設定がおかしいと思うのですが(n-1)にした時点で0になってるはずですよね…。
なぜ最初からにならないのでしょうか?
・二つ目は10文字で終わらずに表示されてしまうこと。
そうですね、ヌルがいるかもしれませんね。
ただ、seekgの前のラインでテストのために文1を表示しているのですが、
ここではヌルがなくてもちゃんと文の終わりで終わってるんですよね…。
どうしても駄目なら自分でヌルを入れることにします。
実はこのプログラムは教科書に載っている例題をいろんなところから切り貼りして名前を変えて作りました。reinterpret_castは一度変えたらエラー(char *に変換できません、とかいう)を食らったので変えるのをやめました。本当に必要であれば変えてみます。
ありがとうございました。
…引き続き、回答をお待ちしております。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
MySQLにバイナリデータを正常に...
-
XML::Parserの parsefileの結果...
-
JSP URLに表示される拡張子 .jsp
-
Perlで特定行から特定行までを...
-
VBAで巨大なファイルの途中から...
-
ifstream/ofstream について
-
chdirがうまくできない
-
VBAでCSVファイルの特定行を書...
-
ファイル名を複数個配列で確保...
-
fopenでディレクトリ内の全ファ...
-
ReadLineでの読み出し行を指定する
-
C言語で特定の行を抽出する方法...
-
パスから最後のディレクトリだ...
-
Perl 特定のフォルダ以外削除
-
大容量テキストファイルから任...
-
Perl で syntax error
-
ExcelをCSV書き出す場合のシー...
-
空白文字 \\f と\\v の違いに...
-
perlのエディタでおすすめを教...
-
excel→txtファイル作成時、セル...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
python renameについて
-
window.open でのファイル指定方法
-
MATLABのm-fileについて
-
fgets で値が取得できない
-
csvファイルの横方向への改行に...
-
巨大なテキストの最終行を取得...
-
Firefox で file:// で始まる U...
-
JSP URLに表示される拡張子 .jsp
-
重複ファイル名ある場合ファイ...
-
ファイルの存在の有無を確かめ...
-
ファイル全てを .xlsm に変更し...
-
PerlでのUseless use...
-
行を指定して削除する方法PERL
-
VBA テキストファイルを読み取...
-
HTMLのフォームで画像と文...
-
perl ファイルが開かない
-
並び方、
-
read() on unopened filehandle...
-
drtファイルはどうしたら開...
-
VBAコードを張り付け後のエクセ...
おすすめ情報