C 文字列操作 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(文字列と日付・日時・時間の変換)
(文字列の抽出)
7,195行: 7,195行:
  
  
 +
とにかく文字を数えて、文字列ポインタを移動させ、サロゲートペアなら4バイト、通常のワイド文字範囲なら2byteってなかんじで数えます。面倒ですが、サロゲートペアのことを考えると文字数での抽出はこのような気遣いが必要です。マルチバイト文字でやるときは、また違った対応が必要になります。仕組みとしては文字数とバイト数をきちんと数えて、先頭文字にポインタを合わせる。***ncpy系の関数でそこから必要なバイト数をコピーするという感じになります。コンソール画面ではShiftJISなので文字化けしますから、Unicode文字としてテキストに出力するプログラムになっています。
 +
<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>      //Vector型テンプレートクラス
  
 +
#include <sys/timeb.h> //Timeb型構造体
 +
 +
//_bstr_t型を利用するプリプロセッサ(ライブラリはデバッグモードとリリースモード個別設定)
 +
#include "comutil.h"
 +
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "comsuppwd.lib")
 +
#else
 +
#pragma comment(lib, "comsuppw.lib")
 +
#endif
 +
//_bstr_t _End
 +
 +
//ICU ucnvプリプロセッサ(ライブラリはデバッグモードとリリースモード個別設定)
 +
#include <unicode/ucnv.h>    //ucnv文字コード変換ライブラリヘッダ
 +
#include <unicode/translit.h> //文字変換ライブラリヘッダ
 +
#include <unicode/regex.h>    //正規表現
 +
#include <unicode/ucsdet.h>  //文字コード判定
 +
#include <unicode/ucal.h>  //文字コード判定
 +
#include <unicode/uclean.h> //u_cleanup関数
 +
/* for uloc_getDefault() */
 +
#include <unicode/uloc.h>
 +
#include <unicode/calendar.h>
 +
#include <unicode/smpdtfmt.h>
 +
 +
//#include "unicode/utypes.h"
 +
//#include "unicode/locid.h"
 +
//#include "unicode/unistr.h"
 +
//#include "unicode/tzfmt.h"
 +
//#include "unicode/tznames.h"
 +
 +
 +
#ifdef _DEBUG
 +
#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuucd.lib")  //ICU ucnvを使うために必要なライブラリ
 +
#pragma comment(lib, "icuind.lib")  //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "iculed.lib")
 +
#pragma comment(lib, "iculxd.lib") 
 +
#pragma comment(lib, "icuiod.lib") 
 +
#pragma comment(lib, "icutud.lib") 
 +
 +
#else
 +
//#pragma comment(lib, "icudt.lib")
 +
#pragma comment(lib, "icuind.lib")  //ICU Transliterate関数を使うために必要なライブラリ 正規表現関数も
 +
#pragma comment(lib, "icuuc.lib")  //ICU ucnvを使うために必要なライブラリ
 +
//#pragma comment(lib, "icuio.lib")
 +
#endif
 +
//Data  Library                    icudtXX(d).dll icudt(d).lib
 +
//Common Library                    icuucXX(d).dll icuuc(d).lib
 +
//Internationalization(i18n) Library icuinXX(d).dll icuin(d).lib
 +
//Layout Engine                      iculeXX(d).dll icule(d).lib
 +
//Layout Extention Engine            iculxXX(d).dll iculx(d).lib
 +
//ICU I/O(Unicode stdio) Library    icuioXX(d).dll icuio(d).lib
 +
//Tool Utility Library              icutuXX(d).dll icutu(d).lib
 +
 +
//ICU ucnv _End
 +
 +
#include "UnicodeConverter.h"
 +
 +
using namespace std;
 +
 +
int _tmain(int argc, _TCHAR* argv[])
 +
{
 +
  _tsetlocale(LC_ALL, _T("Japanese")); //ロケールセットすると_l関数でロケール指定しなくても日本語が使われます。
 +
 +
_locale_t localeJpanease;
 +
localeJpanease = _create_locale(LC_ALL, "Japanese");
 +
 +
  FILE* pfileText;
 +
  fpos_t* fposPos = new fpos_t;
 +
  errno_t errNo;
 +
  size_t* psizeRuturnValue = new size_t;
 +
 
 +
  wchar_t pwcStrFilePath[]            = L"C:\\...\\...\\...\\test_new_Extract.txt";
 +
  char* pcStrStream;
 +
  pcStrStream = new char[1024];
 +
  int nCloseResult = 0;
 +
 
 +
  wchar_t pwcStrSurrogate[] = L"\xD840\xDC0B\xD867\xDE3Dごはん\xD840\xDC0B\xD842\xDFB7を食べたYo。";//L"𠀋𩸽ごはん𠀋𠮷を食べたYo。"と同じ。
 +
  const wchar_t* pwcStrPos;//実体は持たない文字位置格納変数
 +
  const wchar_t* pwcStrStPos;//実体は持たない文字位置格納変数
 +
  wchar_t* pwcStrSurrogateExtract;
 +
 +
  pwcStrPos = pwcStrSurrogate;
 +
  int nSize =  wcslen(pwcStrSurrogate);
 +
  int nByteCnt = 0;
 +
  int nCharCnt = 0;
 +
  int nStPos = 2;//文字位置では0文字目からカウントする仕組みなので、3文字目にポインタが合います。
 +
  printf("%d\n",nSize);
 +
  while (nByteCnt < nSize && nCharCnt < nStPos){
 +
    unsigned int unValue = _wcsnextc(pwcStrPos);
 +
    pwcStrPos++;
 +
    printf("%0x:",unValue);
 +
    if(unValue >= 0xD800 && unValue <= 0xDFFF){ 
 +
      pwcStrPos++;
 +
      nByteCnt++;
 +
    }
 +
    nCharCnt++;
 +
    nByteCnt++;
 +
  }
 +
  pwcStrStPos = pwcStrPos;//先頭の文字列にポインタを合わせる。
 +
  printf("\n");
 +
  printf("%d[Byte],%d[文字]\n",nByteCnt,nCharCnt);
 +
  int nEnPos = 5;//先頭文字から5文字目までのバイト数を数えます。そういう意味では最初の先頭文字の指定と合わせた方が良かったかも。
 +
  nByteCnt = 0;
 +
  nCharCnt = 0;
 +
  nSize =  wcslen(pwcStrPos);
 +
 +
  printf("%d\n",nSize);
 +
  while (nByteCnt < nSize && nCharCnt < nEnPos){
 +
    unsigned int unValue = _wcsnextc(pwcStrPos);
 +
    pwcStrPos++;
 +
    printf("%0x:",unValue);
 +
    if(unValue >= 0xD800 && unValue <= 0xDFFF){ 
 +
      pwcStrPos++;
 +
      nByteCnt++;
 +
    }
 +
    nCharCnt++;
 +
    nByteCnt++;
 +
  }
 +
  printf("\n");
 +
 +
  pwcStrSurrogateExtract = new wchar_t[nByteCnt + 1];
 +
  wcsncpy_s(pwcStrSurrogateExtract, nByteCnt + 1, pwcStrStPos, nByteCnt);//5文字分のバイト数をコピーする。7バイトだね。
 +
 +
  printf("%d[Byte],%d[文字]\n",nByteCnt,nCharCnt);
 +
  wprintf(L"%s",pwcStrPos);
 +
  printf("\n");
 +
 +
  fpos_t* pfposStartPos = new fpos_t;
 +
  printf("★テキストの新規書き込み\n");
 +
  errNo = _wfopen_s( &pfileText, pwcStrFilePath, L"w,ccs=UTF-16LE");
 +
  printf("Error?->%d\n", errNo);
 +
 
 +
  fputws(pwcStrSurrogate,pfileText);
 +
  fputws(L"\n",pfileText);
 +
 +
  fputws(pwcStrStPos,pfileText);
 +
  fputws(L"\n",pfileText);
 +
 +
  fputws(pwcStrPos,pfileText);
 +
  fputws(L"\n",pfileText);
 +
 +
  fputws(pwcStrSurrogateExtract,pfileText);
 +
 +
  fclose(pfileText);
 +
  return 0;
 +
}
 +
</syntaxhighlight>
 +
コンソール側出力
 +
<syntaxhighlight lang="text">
 +
18
 +
d840:d842:
 +
4[Byte],2[文字]
 +
14
 +
3054:306f:3093:d840:d842:
 +
7[Byte],5[文字]
 +
を食べたYo。
 +
★テキストの新規書き込み
 +
Error?->0
 +
</syntaxhighlight>
 +
テキスト出力
 +
<syntaxhighlight lang="text">
 +
𠀋𩸽ごはん𠀋𠮷を食べたYo。
 +
ごはん𠀋𠮷を食べたYo。
 +
を食べたYo。
 +
ごはん𠀋𠮷
 +
</syntaxhighlight>
 
<!--
 
<!--
 
{|class="wikitable"
 
{|class="wikitable"

2014年10月20日 (月) 00:00時点における版



個人用ツール
名前空間

変種
操作
案内
ツールボックス