コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2003年12月19日 >>> 2003年12月19日
link もっと後

2003年12月19日

たかが標準入力から1行読み込む処理、されどハマりました。

固定バッファは溢れるたりして厄介なので、デリミタまでをstringクラスに代入してくれる関数を使おうと思いました。C++にはstd::getlineという、まさにその動きをする関数があるのですが、なぜかEnterを二回押さないと動かないという変な関数で使えません。仕方なく自作することに。

単純にistream::get(char *, int, int)でバッファ長かデリミタまで取ってstringに連結し、デリミタはistream::ignore(1)で消し去ればかんたーん、などと思ったのですよ。しかしgetの動きがイカレてて、何も入力せずにEnterを押すとエラーになります。すると後のistream::peek()が全部EOFを返しますが、ファイル末端というわけではないのでistream::eof()は偽を返し、無限ループに陥ります。な、なんだってー!?

結局istream::get(char *, int, int)にあたる部分もistream::get()を使って自作しなければならず、1行取ってくるだけのプログラムがかなり肥大化しました。これじゃ何のためのC++だかわかりませんよ。お願いだから開発系くらいちゃんと作ってくれよ、M$さん頼むよー(´Д`;)

作ったコードはこんな感じです。あまり洗練されたコードではありませんが、読みやすさ優先主義ってことで許して。

理想

//理想(g++ だとこちらで動く、ていうかそれが当然)
#include <iostream>
#include <string>
using namespace std;

int main(int argc, char *argv[])
{
  string str;

  while (!cin.eof()){
    //1行取得
    std::getline(cin, str, '\n');
    //1行出力
    cout << "out: " << str << endl;
  }
  return 0;
}
現実

//現実(こちらも当然だがg++ で動く)
#include <iostream>
#include <string>
using namespace std;

istream &getBlock(istream &s_in, char *pbuf, int size, char delim);
istream &getLine(istream &s_in, string &str_buf, char delim);

int main(int argc, char *argv[])
{
  string str;

  while (!cin.eof()){
    //1行取得
    getLine(cin, str, '\n');
    //1行出力
    cout << "out: " << str << endl;
  }
  return 0;
}

//終端、区切り文字またはバッファサイズ - 1まで入力を取り出す
istream &getBlock(istream &s_in, char *pbuf, int size, char delim)
{
  int ch, pt;

  for (pt = 0; !s_in.eof(); pt++) {
    ch = s_in.get();
    //区切り文字検出
    if (ch == delim || pt >= size - 1) {
      s_in.putback((char)ch);
      break;
    }
    pbuf[pt] = (char)ch;
  }
  //nul文字付加
  pbuf[pt] = '\0';
  return s_in;
}

//改行までstringクラス変数に入力を取り出す
istream &getLine(istream &s_in, string &str_buf, char delim)
{
  char buf[BUFSIZE];

  //バッファ初期化
  str_buf = "";
  while (!s_in.eof()) {
    //バッファの限界か、区切り文字まで読み込む
    getBlock(s_in, (char *)buf, sizeof(buf), delim);
    //連結
    str_buf += buf;
    //区切り文字にて読み込みが止まった場合
    if (s_in.peek() == delim) {
      s_in.ignore(1);
      break;
    }
  }
  return s_in;
}
編集者:すずき(2014/09/10 11:27)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2003年12月19日 >>> 2003年12月19日
link もっと後

管理用メニュー

link 記事を新規作成

<2003>
<<<12>>>
-123456
78910111213
14151617181920
21222324252627
28293031---

最近のコメント5件

  • link 24年4月22日
    hdkさん (04/24 08:36)
    「うちのHHFZ4310は15年突破しまし...」
  • link 24年4月22日
    すずきさん (04/24 00:37)
    「ちゃんと数えてないですけど蛍光管が10年...」
  • link 24年4月22日
    hdkさん (04/23 20:52)
    「おお... うちのHHFZ4310より後...」
  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」

最近の記事3件

  • link 24年4月25日
    すずき (04/26 16:49)
    「[AVIFの変換] AVIFが読めないアプリケーションがたまにあるので、AVIF(AV1 Image File Format)...」
  • link 24年2月7日
    すずき (04/24 02:52)
    「[複数の音声ファイルのラウドネスを統一したい] PCやデジタル音楽プレーヤーで音楽を聞いていると、曲によって音量の大小が激しく...」
  • link 24年4月22日
    すずき (04/23 20:13)
    「[仕事部屋の照明が壊れた] いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/26 16:49