ある日のこと。
日々の疲れと二日酔いからくる頭痛に見舞われた自営業の働くオクサマは頭にアイスノンを巻きながら、
それでもせっせと仕事をしていましたとさ。
そこに相方。苦しむオクサマにひとこといったとさ。
”おなすみたい”
そうそう。真っ青な顔で下膨れで毛がはみ出てて・・・コラ~っ!!!!
異常気象に老後の不安。景気は悪くなる一方。親もお客も患者もみんなモンスターに成り果てた。
そりゃぁ、青くなる。怒りで赤くなりもする。
あわせりゃそうそう、いつのまに・・・。ムラサキの顔になっていた。
この世はおなすなことばかり。
久しぶりのC++/STLネタということで、CSVファイルの読み込みです。
もともと、Apacheが出力するアクセスログの読み込みの為に作ったのですが、せっかくなので、Excelが出力するCSVにも対応しました。
CSVファイルの読み込みは他の言語ならsplit一発でお茶を濁すのですが、カンマ(,)やダブルクオート(")、改行があるデータにも対応してます。
/**********************************************************************
CSVファイルの読み込みサンプル
試したコンパイル環境
VC++ .NET 2003 / WINDOWS XP Professional 64 bit edition.
GCC C++ 3.3.6 / glibc 2.3.4 / Vine Linux 4.2
**********************************************************************/
#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
/**********************************************************************
クオート文字の定義構造体
**********************************************************************/
struct quote{
char start; // 開始文字
char end; // 終了文字
char escape; // エスケープ文字
quote( char start_, char end_, char escape_) :
start(start_), end(end_), escape(escape_) {}
};
struct cmpStartQuote : public std::binary_function<quote,char,bool> {
bool operator()(const quote &l_s1, const char &l_s2) const {
return l_s1.start == l_s2;
}
};
/**********************************************************************
CSVの読取
**********************************************************************/
bool readCSV(
std::vector< std::string > &result, // 結果格納ベクター
std::istreambuf_iterator<char> &i, // 入力文字イテレータ
std::string &separator, // 区切り文字
std::vector<quote> "es) // クオート文字ベクター
{
bool retval = false;
result.clear();
std::string item;
char bc = '\0';
bool first = true;
std::vector<quote>::iterator ff = quotes.end();
while ( i != std::istreambuf_iterator<char>() &&
(ff != quotes.end() || *i != '\n') ) {
if ( ff == quotes.end() &&
strchr( separator.c_str(), *i) != 0 ) {
result.push_back(item);
item.clear();
first = true;
retval = true;
} else {
if ( first &&
(ff = find_if( quotes.begin(),
quotes.end(),
bind2nd( cmpStartQuote(), *i)))
!= quotes.end() ) {
first = false;
} else if ( ff != quotes.end() && ff->end == *i ) {
if ( ff->end == ff->escape ) {
bc = *i++;
if ( i == std::istreambuf_iterator<char>() )
break;
if ( *i == ff->end ) {
item.push_back(*i);
} else {
ff = quotes.end();
continue;
}
} else {
if ( bc == ff->escape ) {
item.push_back(*i);
} else {
ff = quotes.end();
}
}
} else {
item.push_back(*i);
first = false;
}
}
bc = *i++;
}
result.push_back(item);
if ( i != std::istreambuf_iterator<char>() ) {
retval = true;
i++;
}
return retval;
}
using namespace std;
int main(int argc, char* argv[])
{
basic_ifstream<char> inputFile("access_log");
istreambuf_iterator<char> sin(inputFile);
vector< string > rec;
// APACHEのアクセスログ
string separator(" ");
vector< quote > quotes;
// クオート文字(")の設定("を表示したいときは\"になる)
quotes.push_back( quote( '"', '"', '\\') );
// 時間部分のクオート文字([]で括る)
quotes.push_back( quote( '[', ']', 0 ) );
while ( readCSV( rec, sin, separator, quotes) ) {
vector< string >::iterator i;
for ( i = rec.begin(); i < rec.end(); i++ ) {
cout << i - rec.begin() << ":" << *i << endl;
}
cout << endl;
}
return 0;
}
上記コードは、Apacheのログを読み込むサンプルで、CSVファイルの読み込みの場合は、
separatorとquotesの部分が、
string separator(",");
vector< quote > quotes;
quotes.push_back( quote( '"', '"', '"') );
になります。
何で使用するのか不明だが、最近購入したグラフィックカード(玄人志向のRH2400PRO-LE256H、ATI RadeonHD2400PRO)にAudioデバイスがあり、こいつのインストールではまったのでメモします。
で、このHD2400PROのドライバページには何故かAudioデバイスドライバが無い。
結局、現時点(2008/08/01)では、
このページのXP Professional/Homeから ATI All-in-Wonder™ HD Drivers for Windows XP Professional/Home Editionのリンクをたどりドライバを入手した。
(ちなみに2003 Server 64Bit Editionもこのドライバでいけた)
何時もは技術的な話題を中心にしていますが、最近あまり技術ネタがないので違ったネタを
こんな記事を見つけました。
意識調査:“モンスター”は身近に存在、2人に1人が遭遇。5人に1人は身内にも?<意識調査>モンスターに関する意識調査 ブロガー向け情報サイト「ブロッチ」などネットマーケティングを展開する株式会社アイシェアは同社が提供するサービス会員をパネ・・・
≫続き[
ブロッチ.jp]
最近流行りのモンスター○○ですが、私の身近であったモンスターを紹介します。
私の勤めている会社は小さな旅行会社です。
インターネットの旅行会社と言えばオンラインで航空券を買ったりホテルを予約したりというイメージがあるかと思いますが、
弊社の場合、コーディネーターが「飛行機は何で、ホテルは何で、列車は何で・・・」と1つ1つ旅程を組みながら旅の手配を行います。詳しくは
こちらを見ていただくとしてまぁ要するに、お客さんが「ベルリンとパリとミラノを回りたい!」なんていいますと「ではこのような旅程でどうですか?」と提案をするのが他社との大きな違いになります。
で、このようなお客がいました。
はじめまして。
海外旅行初心者の新婚夫婦の新婚旅行です。
御社のHPの「お客様からのメール」を読み、
とても真剣に考えていただけそうだったので、
見積もりを依頼させていただきました。
上記の挨拶と共に、色々旅程の案を送信したのですが、そこはまぁ素人が考えることですので、実現性がありません。そこで、コーディネーターが4案程プランを作成し送信したところ下記の返信がありました。
提案して下さったプランCが目から鱗でした!
プランCを元に本日いろいろ調べ、考えた事を
報告させていただきます。
その後、航空機会社を何処にするかとかやり取りをしていたのですが、航空機会社から料金表が出ない為、何処にするか色々やりとりがありましたがその後に、
妻が不整脈の為、キャンセルします。
と連絡がありました。
本件ですが、メールでのやり取りの為、まだ正式な予約に至っていなかったので、(弊社の場合、航空券を仮押さえした後に正式な予約に入ります。)コーディネーターは「奥様が元気になられたらまたお声がけ下さい」と気を利かせてキャンセル料を頂きませんでした。
ところがこのお客さん他の旅行会社で予約をしていたんです。しかもコーディネーターが作成したアイデア(旅程)はそのままで
どういうつもりで他の旅行会社に申し込んだのか定かでないし(不整脈とウソをついているので)、コーディネーターが一生懸命考えた旅程を盗むのはマナー違反です。
今ひとつ、モンスターぶりが解らないかもしれませんが、弊社の場合、コーディネーターが旅程を考えて手配しているので、非常に手間がかかります。その旅程案だけが欲しいのならそのように言って頂ければ手数料を頂戴していました。ただ、今回は不慮の事故ということで、手数料を頂戴しませんでしたが、それはウソによるものです。このようなことを詐欺であると私は認識していますが、いやはや、インターネットの恐ろしさというかモンスターの恐ろしさを痛感しました。
ちなみに、なぜ他の旅行会社で予約したのか解るのか?というのは内緒です。
C++/STLで、ついついやってしまうミスに、コンテナの要素への参照を保存するがある。
最近、このミスをやってしまったので覚書にしておく。
要するに、コンテナに値を追加・削除するとイテレーターが無効になる、と同じことなのだが、参照だとついついやってしまいます。
ちなみに、このバグはコンテナの領域が再配置されない限り発生しないので、reserveメソッドを使用して適当な領域を確保するとデバッグが困難になるので、マジで注意が必要です。
以下、バグの再現コードです。
#include <iostream>
#include <vector>
using namespace std;
int main(void)
{
vector<int> array1;
array1.reserve(10);
for ( int i = 0; i < array1.capacity(); i++ ) {
array1.push_back(i);
}
int &last_value = array1.back(); // コンテナの要素の参照を得る
cout << "last_value: " << last_value << endl;
array1.push_back(10); // ここでlast_valueは無効になる
cout << "last_value: " << last_value << endl;
return 0;
}
実行結果
VC++ .NET 2003 / WINDOWS XP Professional 64 bit edition(32ビット環境で作成・実行)
last_value: 9
last_value: -572662307