goo blog サービス終了のお知らせ 

われこわれこ

プログラムじゃあ~りませんか!

vectorの小技

2015-06-01 21:09:42 | C++
しかしまあ、何ですなあ~は小枝。
C++やり始めてvectorをよく使う。Cの経験の長いワテにはvectorが便利なのだが、使い方を良く忘れるのでメモ。
 
1. 二つのvector<T>を結合する関数。テンプレート関数で作ってみた。

template<typename Tvector<T> vector_concat(const vector<T>&A, const vector<T>&B)
{
	vector<T> AB;
	AB.reserve(A.size() + B.size()); // preallocate memory
	AB.insert(AB.end(), A.begin(), A.end());
	AB.insert(AB.end(), B.begin(), B.end());
	return AB;
}
 
2. vector<wstring>の中で空文字列な要素を削除する関数
わざわざ、関数にする必要は無いかもしれないが、よく使うので関数化した。
 
vector<wstring> vector_remove_empty(vector<wstring> &v)
{
	v.erase(remove(v.begin(), v.end(), L""), v.end());
	return v;
}
void main()
{

vector<string> v = { "abc", "", "de", "", "fgh" };

for (const wstring& s : v)
wcout << s << endl;

vector<wstring>v2 = vector_remove_empty(v);

for (const wstring& s : v2)
wcout << s << endl;   // "abc", "de",  "fgh" }

}


文字列リテラル LR"()" って何でカッコが""の中にあるんだよ!

2015-05-16 11:35:18 | C++
C++でパス名に含まれる¥記号やバックスラッシュ\ はエスケープの意味なので文字列中では通常は二個続けて書く。
const wstring pathFileName1 = L"C:\\Users\\wate\\Documents\\わてのファイル.txt";
でも、C#なら先頭に@を付けると二個続けて書く必要は無くて、
string pathFileName3 = @"C:\Users\wate\Documents\わてのファイル.txt";
と書ける。一方C++でも、Rを付ければ(LはwstringのL)
const wstring pathFileName3 = LR"(C:\Users\wate\Documents\わてのファイル.txt)"; 
と書けるのだが、何で R"()" と決めたんだろう? R("")でいいだろ。つまり
const wstring pathFileName3 = LR("C:\Users\wate\Documents\わてのファイル.txt");
まあ、LR()というマクロが別の意味で定義されていると問題になるかもしれないが、何でこんなヘンテコな
R"()"っていう文法にしたんだろう?
これで困るのは、正規表現のパターンを書くときに使う()と混同してしまうんだようなあ。
wstring pattern = LR"(((?:こんな|あんな)文字列を(?:探す|探さない))+)" // これだと¥使っていないのでR"()"使う必要ないか。。。
一番外側の()は正規表現とは関係ないR"()"のカッコだ。
これくらいなら混乱しないけれど、文字列を連結して複雑なパターンを定義しようとすると、もう訳分からんん。
まあ、Windowsでパス名の文字列なら、スラッシュ一個でこんな風に書いても行けるようだが、
const wstring pathFileName2 = L"C:/Users/wate/Documents/わてのファイル.txt";
パスでしか使えないと思うので。
ということで、誰が R"()" みたいなヘンテコな文法を考えたんだよ!責任者は出てこなくてもいいです。

isspace(), iswspace() ではCR, LF, Tabなども真になる。知らなんだ。

2015-05-16 10:11:08 | C++
iswspace() では、
 全角空白
 半角空白
 タブ
 改行 CR キャリッジリターン(Carriage Return)、リターン(Return) 0D \r 13
 復帰 LF ラインフィード(Line Feed)、ニューライン(New Line) 0A \n 10
を全て空白と判定するようだ。
http://www.cplusplus.com/reference/cctype/isspace/
を見ると
 

isspace

int isspace ( int c );
Check if character is a white-space
Checks whether c is a white-space character.

For the "C" locale, white-space characters are any of:
' ' (0x20) space (SPC)
'\t' (0x09) horizontal tab (TAB)
'\n' (0x0a) newline (LF)
'\v' (0x0b) vertical tab (VT)
'\f' (0x0c) feed (FF)
'\r' (0x0d) carriage return (CR)

なので、そのwchar_t版はこれらのwchar_tを空白と判定するのか。

キャリッジリポビタンD

2015-05-16 09:48:01 | C++
プログラムを書いていて、CR, LFをいろんな場面で使うが、良く混同するのでまとめておこう。
 

キャリッジリターン のウイキ

 

問題は、

CR、LF、\r, \n, 10, 13

の対応がどれがどれかよく忘れる。

ワテ流の覚え方

'N'ew Line Feed    で \n 

Carriage 'R'eturn で  \r    キャリッジリターン -> キャリッジリポビタンD -> 0D ->13

 

みなさんもどうぞ。

 

 


ファイルの日付を変更したい場合

2015-05-14 13:37:00 | C++

昨日、あるファイルをCopyFile関数でコピーしたのだが、何故か分からないのだが、作成されたファイルの日付が コピー元のファイルの日付と一致しない変な症状に遭遇した。

ファイルの日付には

作成日時

更新日時

アクセス日時

があるが、その時の変な症状では、何度やってもコピー後のファイルの日付(Windowsのエクスプローラーで表示される更新日時)が、コピー元ファイルの作成日時になってしまうのだ。

おかしい。 結局、原因が分からなかったので、即席でファイルの日時を設定する関数を作ってみた。

set_file_datetime_now(LR"(D:\MyDocuments\テストファイル.txt)");

で実行すると、現在時刻がセット出来た。

#include "stdafx.h"
#include <Windows.h>
#include <string>
using namespace std;
 
void set_file_datetime_now(const wstring &pathFName)
{
	BOOL success;
 
	//ファイルのハンドルというのを取得する
	HANDLE hFile = CreateFile(pathFName.c_str(),
		FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL, NULL);
 
 
	SYSTEMTIME thesystemtime;
	GetSystemTime(&thesystemtime);		// 現在の日時をSYSTEMTIMEで取得して後でFILETIMEに変換する
 
#if(0)	// もし特定の日時にセットしたい場合
	thesystemtime.wDay = 07;	//changes the day
	thesystemtime.wMonth = 04;	//changes the month
	thesystemtime.wYear = 2012;	//changes the year
#endif
 
	//creation of a filetimestruct and convert our new systemtime
	FILETIME thefiletime;
 
	success = SystemTimeToFileTime(&thesystemtime, &thefiletime);
	//戻り値
	// 関数が成功すると、0 以外の値が返ります。
	// 関数が失敗すると、0 が返ります。拡張エラー情報を取得するには、 関数を使います。
 
 
	success = SetFileTime(		
		_In_     hFile,			//       HANDLE   hFile,
		_In_opt_ &thefiletime,	// const FILETIME *lpCreationTime,
		_In_opt_ &thefiletime,	// const FILETIME *lpLastAccessTime,
		_In_opt_ &thefiletime	// const FILETIME *lpLastWriteTime
		);
	//戻り値
	// 関数が成功すると、0 以外の値が返ります。
	// 関数が失敗すると、0 が返ります。拡張エラー情報を取得するには、 関数を使います。
 
 
	success = CloseHandle(
		_In_ hFile				//HANDLE hObject
		);
 
	//戻り値
	// 関数が成功すると、0 以外の値が返ります。
	// 関数が失敗すると、0 が返ります。拡張エラー情報を取得するには、 関数を使います。
 
}