C 文字列操作 新しいページはコチラ
提供: yonewiki
(→文字列大文字小文字変換) |
(→文字列大文字小文字変換) |
||
3,341行: | 3,341行: | ||
<nowiki>***</nowiki>upr***系の関数になります。こちらも_str***に_wcs***、_mbs***と接尾句に****_sや****_lそして****_s_lがつくものの組み合わせが存在しています。 | <nowiki>***</nowiki>upr***系の関数になります。こちらも_str***に_wcs***、_mbs***と接尾句に****_sや****_lそして****_s_lがつくものの組み合わせが存在しています。 | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | #pragma once | ||
+ | #include "stdafx.h" | ||
+ | #include <stdlib.h> | ||
+ | #include <string> //std::string型定義 | ||
+ | #include <mbstring.h> //mbs***関数 | ||
+ | #include <iostream> //cpp cout etc 一般入出力関数 | ||
+ | #include <locale> //Locale関数 | ||
+ | #include <tchar.h> //TCHAR型+_tcs***関数 | ||
+ | #include "atlstr.h" //CString,CStringA,CStringWおよびLPTSTR,LPWSTR,LPSTR,LPCTSTR,LPCWSTR,LPCSTRの定義プリプロセッサ | ||
+ | #include "atlbase.h" //同上 | ||
+ | #include "cstringt.h" //CStringTの定義プリプロセッサ | ||
+ | #include <vector> | ||
+ | |||
+ | |||
+ | //_bstr_t型を利用するプリプロセッサ | ||
+ | #include "comutil.h" | ||
+ | #ifdef _DEBUG | ||
+ | #pragma comment(lib, "comsuppwd.lib") | ||
+ | #else | ||
+ | #pragma comment(lib, "comsuppw.lib") | ||
+ | #endif | ||
+ | //_bstr_t | ||
+ | |||
+ | //ICU ucnvプリプロセッサ | ||
+ | #include <unicode/ucnv.h> | ||
+ | #include <unicode/translit.h> | ||
+ | #include <unicode/regex.h> | ||
+ | #ifdef _DEBUG | ||
+ | //#pragma comment(lib, "icudt.lib") | ||
+ | #pragma comment(lib, "icuind.lib")//ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も | ||
+ | #pragma comment(lib, "icuucd.lib")//ICU ucnvを使うために必要なライブラリ | ||
+ | //#pragma comment(lib, "icuiod.lib") | ||
+ | #else | ||
+ | #pragma comment(lib, "icudt.lib") | ||
+ | #pragma comment(lib, "icuind.lib") | ||
+ | #pragma comment(lib, "icuuc.lib") | ||
+ | #pragma comment(lib, "icuio.lib") | ||
+ | #endif | ||
+ | |||
+ | |||
+ | #include "UnicodeConverter.h" | ||
+ | |||
+ | |||
+ | using namespace std; | ||
+ | int _tmain(int argc, _TCHAR* argv[]) | ||
+ | { | ||
+ | int nSizeValue; | ||
+ | |||
+ | _wsetlocale( LC_ALL, L"Japanese"); | ||
+ | const char *ppcStr[]={"abCdefG","HijKLmn","OpQRSTu","vWxyZ"}; | ||
+ | |||
+ | nSizeValue = sizeof(ppcStr)/sizeof(*ppcStr); | ||
+ | |||
+ | char** ppcStrConv = new char*[nSizeValue]; | ||
+ | |||
+ | printf("★大文字→小文字変換\n"); | ||
+ | for(int i = 0; i < nSizeValue; i++){ | ||
+ | *(ppcStrConv + i) = new char[strlen(*(ppcStr + i)) + 1]; | ||
+ | strcpy_s(*(ppcStrConv + i),strlen(*(ppcStr + i)) + 1, (*(ppcStr + i))); | ||
+ | _strlwr_s(*(ppcStrConv + i), strlen(*(ppcStrConv + i)) + 1); | ||
+ | } | ||
+ | |||
+ | for(int i = 0; i < nSizeValue; i++){ | ||
+ | printf("%s\n",*(ppcStrConv + i)); | ||
+ | } | ||
+ | |||
+ | for(int i = 0; i < nSizeValue; i++){ | ||
+ | delete[] *(ppcStrConv + i); | ||
+ | } | ||
+ | |||
+ | |||
+ | printf("★小文字→大文字変換\n"); | ||
+ | for(int i = 0; i < nSizeValue; i++){ | ||
+ | *(ppcStrConv + i) = new char[strlen(*(ppcStr + i)) + 1]; | ||
+ | strcpy_s(*(ppcStrConv + i),strlen(*(ppcStr + i)) + 1, (*(ppcStr + i))); | ||
+ | _strupr_s(*(ppcStrConv + i), strlen(*(ppcStrConv + i)) + 1); | ||
+ | } | ||
+ | |||
+ | for(int i = 0; i < nSizeValue; i++){ | ||
+ | printf("%s\n",*(ppcStrConv + i)); | ||
+ | } | ||
+ | |||
+ | for(int i = 0; i < nSizeValue; i++){ | ||
+ | delete[] *(ppcStrConv + i); | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | 上記のように変換できます。余談になりますが、配列はppcStr[i]のように記述できますが、結局のところ *(ppcStr + i)のように書き直すことができます。配列を宣言したときに、その変数は既にポインタ変数になっているので、宣言したときから、配列変数であることを示すプレフィックス(接頭句)としてpをつけておくのもよいですね。ポインタの配列はppと接頭句が付けられますし、char型ならppcという具合の接頭句の規則を自分は使っています。intはiじゃなくてnを接頭句に使うんですけど。面倒になって接頭句を付け忘れたりもします。そうするとしばらくして、これ何の変数だっけ?という具合になるおじいちゃんぶりを発揮します。たぶん、こうなってくると、「さっき食べたでしょ?おじいちゃん(^_^)。」って言われると、もう断食状態になります。やばいです。人が書いたプログラムと合わせると、また接頭句の規則が乱れて、自分自身では理解ができなくなってくるのです。たぶん自分は大きなプログラムを作るのには向いていませんね。せめて個人的に作っているプログラムの範囲では、規則どおりにやって間違いを減らしたいと思います。チームでやるときは、今までにつちかってきた規則と基盤を胸にきざみつつも応用力が試されます。int nSize[] = {10,20,30};みたいに宣言したときも実はnSizeってのは、この配列の先頭アドレスを保有する変数になってるわけだから、int pnSize[] = {10,20,30};として宣言して、*(pnSize + i) みたいにして、使うのもいいし、pnSize[i]として配列のように使うのもいい。ポインタ変数をあつかってるんだなぁって意識できてるだけマシ。プロになると、まぁそんな細かい事いわなくても自然と意識できるんでしょう。ただ、構造体やらクラスの配列だとpSize[i].mValueとかpSize[i].mFunc()みたいにできるものでも *(pSize + i).xxxとはできず、(*(pSize + i)).mValue のように全体をカッコでくくらないと駄目です。そして、アロー演算子は(*(ポインタ変数)).mValueのようなメンバ変数や関数の参照をおきかえるものでしたから、配列を[]を使わないで表現できることをしっていれば、(pSize + i)->mValueと記述を切り替えるのもたやすいですね。 | ||
+ | |||
+ | <nowiki>***</nowiki>upr***や***lwr***関数のように与えられたポインタの実体を置き換える関数では、引数にconstやリテラルを与えることはできないのが常です。確保するメモリ領域を十分に考慮した実体化されたポインタ変数にコピーを作成して、それを引数にしなければなりません。関数によっては、実体の大きさを再定義して別のメモリ空間にさしかえてアドレスをポインタに格納して値を返却してくれます。こういった操作が多いので、動的にメモリを確保したりする手法を知っておくのは大事な知識となります。リテラルを使わないで変数宣言して十分な要素を確保してから、その変数のアドレスをポインタ変数に入れるという手法もありますが、文字数がどうなるかわからないプログラムでは、動的に確保するやり方をマスタしておかないと無駄にメモリを確保しなければならない場面が多くなってしまいます。配列や文字列を活用するには、動的なメモリ確保のやり方を把握しておいた方がいいですね。 | ||
=='''文字列半角文字全角文字変換'''== | =='''文字列半角文字全角文字変換'''== |