概要
1、記載事項の背景
(1)動機:VC6++で作成したコードをVisual Studio 2008 下で実行時、生成フォルダの文字化けの発生のため
(2)コンパイラー:VS2008、VS2010
(3)対象:c++ の文字 string 型の扱い
2、結論
"#include<mbstring.h>"と "setlocale( LC_ALL, "japanese" )" の記述で、フォルダ名の文字化けはない。
なお、VS2008、VS2010のプロジェクトのプロパティで構成プロパティの全般の個所中の文字セットを
"マルチ バイト文字セット"を使用するを選択する必要がある。
3、文字の判別について
(1)c++での文字列の区別
・Single Byte(8bit=1byte)=SBCS 、Double Byte(16bite=2byte)=DBCS
・Single Byte=SBCS、Multi Byte(8and16bit以上、1byte以上)=MBCS
・Multi Byte Charcter、Wide Character=wchar_t
・Ascii文字コード=char、Unicode
・TCHAR (マイクロソフトのVisual Studioの専用の typedef 文字列体系で、
_UNICODEあるいは_MBCSのオプションでcharやwcharに変換する。)
上記は、多くの web page、および Wikipedia 等を参照している。
(2)コードの説明 (コード1)
文字列に あいうえおのような平仮名、全角カタカナの日本語が含まれているかの識別方法を示す。
識別方法は、文字列の文字数を上記の SBCS、MBCS 、終端にNULL(char型) のない string 型で、算出し、
これらの文字数の比較で、日本語が含まれているかいなかの判定を行う方法である。
他の方法も検討したが、文字列が SBCS か MBCS かは、全体の文字数で判断するこの方法が判り易い。
1)文字数の算出
c++ の文字に関する ST Lの一つであるstring 型の文字数を、以下の関数で求めた。
関数 char型 strlen()、Multibyte型 _mbstrlen()、string型 x.size()
例えば、上記の型に応じて、入力された文字 string型 indata の文字数を以下のように求める。
int strlen_indata=strlen(indata.c_str()); //string 型を char 型とし、single換算の文字数
int mbs_indata=_mbstrlen(indata.c_str()); //string 型を char 型とし、実際の文字数
nt sizetyp_indata=indata.size(); //string 型の single換算時のサイズ(文字数)
2)数の判定
・これらの数を比較し、同数の文字数であれば single とし、同数でなければ Multibyte の文字が含まれてい
るとした。更に、 _MBC_SINGLE と照合し、文字分類を行う。
3)Codeのヘッダーについて
#include <clocale> は地域設定を示すが、日本向け VS2010 では既に内部設定されているようである。
#include <Mbctype.h>はマルチバイト文字の _MBC_SINGLの表示に必要である。
#include <mbstring.h>はmbstype(マルチバイト文字列)の文字型判定に必要である。
4、使用した関数とSTL
strlen()、mbstrlen()、indata.size()、
indata.c_str() 補足:x.c_str() は string 型である indata あるいは x を char 型に変える。
indata.substr(0,1) と indata.substr(0,1).c_str()
補足1:substr(0,1) は indata の文字列から0番目(最初)の文字を 1 文字分取り出す。
取り出した文字は、string 型のために、indata.substr(0,1).c_str() で char 化。
補足2:substr() は、single byte 文字を前提し、切り出す関数である。従い、ひらがな等の全角文字
double byte(Multi byte) の文字を探索あるいは切り出す場合は、substr(i,2)のように 2の倍数
で、行う必要がある。この事は、次節でも説明する。
_mbsbtype(char*,0) char文字の0番目(最初)の文字のtype(singleかmultiか)が判る。Singleは容易に判る。
概要
1、記載事項の背景
(1)目的:string型データからフォルダ生成し、各フォルダにファイルを区別して格納する事。
(2)コンパイラー:VS2008、VS2010
(3)目標:数値計算での各出力ファイルをフォルダに格納する事
2、結論
・string型データからフォルダを生成し、そのフォルダに生成fileを格納する方法の記述。
・meta文字(\\)位置をdirectoryの文字列から探し、その位置からdirの上方位置にホルダを生成する方法の記述。
・VC++ の関数からフォルダやファイルを生成する方法の記述。
3、フォルダ生成およびファイル格納について
(1)フォルダ生成とファイル格納の方法
以下3つの方法で行った。
・_getcwdから得た dir に \\ 付きのファイル名を足す方法。
・VC++の splitpath と makepath を使用する方法。
・VC++の CreateDirectory() による方法。
(2)コードの説明(コード2)
現在の dir(directory) 下に、フォルダを生成する場合には、"\\" をフォルダ名の最初に付け加える。
この\マークは、単なる\記号と区別するために\\と二つ記述する。(過去の調査でevidenceは忘却の彼方)
1)関数 _getcwdから得た dir に \\ 付きのファイル名を足す方法。
・新たに作るフォルダ名を string 型 indata とする。
・_getcwd で、その場所の tree での位置 dir(directory) を得る。
"\\"+indata は、string 型のために .c_str() で char 型にし、
strcat_s で結合し、
_mkdir()で indata 名のフォルダを生成する。
次に、このフォルダに格納するファイル(今回は拡張子.csv)をこのフォルダと結合する。
更に、新たなファイル名(folder1)を ofstram out1()の第一項にいれて、文字等を書き込む。
次に、そのコードのおかれた dir から、上位の dir に フォルダを生成し、 file を格納する事を行う。
その方法として、コードあるいは実行形式の exe のおかれた dictory のフルパスを
c++の string 型にcast化する。
ひらがな等の全角文字が含まれても、single byte 文字換算の文字数で示す size() 関数を使い、
"\\" の位置を string のメンバー関数である single byte文字が前提である substr()
で、探す。
コード2でのこの部分を下記に示す。
char folder3[BUFFSIZE]; //current directory を得る _getcwd は
char 型を許容
_getcwd(folder3,BUFFSIZE);
string up_dir3=(string)folder3; // string 型文字列を扱う substr() に適用するので、stringにcast化
vector<int> position; //current directory で "\\" の位置を書き込む。下記のsubstr(x,1)の1に注意
for(int i=0;i<(int)up_dir3.size();i++) if(up_dir3.substr(i,1)=="\\") position.push_back(i);
position.resize(position.size());//push_backでは、resize() する方が安全サイド
・directory を示す "\¥" の位置のある vector のデータ列から一つ上位の "\\"
位置を得る。
上位位置までのデータを string 型の初期化の手法を利用し、新たな記号に新たな文字列を代入する。
新位置に新たにフォルダを生成する。コード2でのこの部分を下記に示す。ファイルの格納は上に同じ。
string up_dir4(up_dir3,0,position[position.size()-1]);//string up_dir4 の初期化。下記の関数で説明。
string newfolder2="\\カウント法_"+indata; //string型故に、\\カウント_ に indata をプラスする。
string newdir1=up_dir4+newfolder2; // dir情報のある up_dir4 に 上記の newfolder2
をプラス。
_mkdir(newdir1.c_str()); // string型を char 化し、新たに、dir を生成する。
2)VC++の splitpath と makepath を使用する方法。
・splitpathは、_getcwd で得た directory 情報を drive、dir、filename、ext(拡張子)に分解する方法。
・makepath は、drive、dir、filename、ext の入力情報から path (指定した位置にfile)を作成。
・_splitpath_s や _makepath_s は、前もって、drive 等の数値を決めてから使用する必要がある。
・コード
char dirdata2[BUFFSIZE];
_getcwd(dirdata2,BUFFSIZE);
char drive[3]; //drive 名の大きさは、c や d、e であるから 3 byte あれば十分。
char detect_dir[256];
char fname[_MAX_FNAME]; // stdlib.h で決めている _MAX_FNAME の大きさは判らないが。
char ext[256]; // 拡張子の大きさは、256 byte 以下だろう。
上記の定義の下で、以下のように、記載すると、
_splitpath_s(dirdata2, drive, 3, detect_dir,256, fname,_MAX_FNAME, ext,256 );
dirdata2 等々にデータが記入される。これらのデータから新たにフォルダ、ファイルを作る。
・コード
char path_buffer1[_MAX_PATH];
char path_buffer2[_MAX_PATH];
char drive1[_MAX_DRIVE];//splitpathのdriveのままでよいが、体裁をつくろうため。
char dir_new1[_MAX_DIR];//detect_dirでよいが、体裁のために設けた
char newfname[_MAX_FNAME];
char ext1[_MAX_EXT];
string newfolder3="\\Splitpath_"+indata; //string 同士故に + 記号のみで合算
strcpy_s(newfname,newfolder3.c_str());/strcpy_s は char 文字列専用のために、.c_str()
を適用
strcpy_s(drive1,drive);
strcpy_s(dir_new1,detect_dir);//Splitpathで得た情報内容のまま上記の体裁のため。
strcat_s(dir_new1,newfolder3.c_str());
strcpy_s(newfname,"結果121");//newfnameを使用するために敢えて設けた。
strcpy_s(ext1,"csv");//ext1を使用するために敢えて設けた。
_mkdir(dir_new1) ;//このdir_new1のdirがないとpath先がないので、この文が必要である。
_makepath_s(path_buffer1, _MAX_PATH,drive1,dir_new1,newfname,ext1);
_makepath_s(path_buffer2, _MAX_PATH,drive1,dir_new1,"結果122", "csv" );//file名と拡張子の記載
3)VC++の CreateDirectory() による方法。
この方法は、
System::IO::Directory::CreateDirectory("CreatDirectry_method_folder" );
のように、("folder-name")部の folder-name に生成するフォルダ名を記載すると、directoryが出来る。
次に、 folder 名を冠した "\\” 付きのファイル名(拡張子有)を sprin tf_s でbuffer部に作るとfileが出来る。
4)その他
・コード2の実行形式 exe では、置いた場所に2つのフォルダと3つのファイル、
"exe"の格納フォルダと同じ位置に2つのフォルダが生成される。
・ directory を移動させる方法として、UNIXやDosでは "chdir" が準備されている。
・ここでのFile生成の手法 1) を 数値計算 5 直交関数 Legendre多項式 の直交性確認の計算に用いた。
・注意事項としてdirname=_getcwd(dirdata,256)で、dirnameに、"\\xxx"を付加し、新たにディクトリを
作ると、dirdataが新たなディクトリ名に変更される。
4、使用した関数とSTL
string str2(str1,2,3); // string str1="123abc" の時に、str1の0番目が1、1番目が2で、2番目が3である。
str2(str1,2,3) は、str1の2番目の3から3つの文字で初期化され、"3ab"と表示。
_getcwd()、 _mkdir()、
strcpy_s、strcat_s、
_splitpath_s()、 _makepath_s()、 CreateDirectory()、
int xx.size()、
string xy=(string)yyのcast、// yyは char 型
zz.push_back()、
zz.resize(zz.size()) //データを push_back() で取入れた際、最後にデータのsize()を確定した方が安全。