2018-12-08 C è¨èª. 2016/03/04 cè¨èªãc++ã®ãã¼ã¸ã®ã½ã¼ã¹ã³ã¼ããä¸é¨ä¿®æ£ 2014/01/31 cè¨èªé¢æ°ä¸è¦§ãã¼ã¸ã«11ãã¼ã¸ã»ã©è¿½å 2014/01/31 cè¨èªé¢æ°ä¸è¦§ãã¼ã¸ã«30ãã¼ã¸ã»ã©è¿½å 2014/01/30 cè¨èªé¢æ°ä¸è¦§ãã¼ã¸ä½æä¸ つまり_mbstrlen関数をはじめとするマルチバイト系の関数は、Windows環境ではUTF-8を上手く扱えません。, 標準関数にmblenという関数があり、これはマルチバイト文字のバイト数を返します。 Cè¨èª. UTF-8ではアルファベットは1バイトですが日本語は3バイトで表すためです。, つまりUTF-8の環境では日本語を100文字格納するために必要なchar型配列のサイズは200(+NULL文字)ではなく300ということです。 失敗した場合は自作関数を使用します。, setlocale関数の第二引数に指定している数値はコードページというものです。 ååã¯ã ããç´¹ä»ãã¾ããã ããã§ã¯cè¨èªã§ã®æ¥æ¬èªã®åãæ±ãæ¹æ³ãã¿ã¦ããã¾ãã æ¥æ¬èªã®åãæ±ã. cè¨èªã®æ¼ç®åã«ã¤ãã¦ãç®è¡æ¼ç®åãè«çæ¼ç®åãæ¡ä»¶æ¼ç®åãæ¯è¼æ¼ç®åããããæ¼ç®åãcè¨èªã®ã¹ãä¹ã®æ¼ç®åã¨ã¯ãcè¨èªã®ä½ãã®æ¼ç®åã¨ã¯ãçã«ã¤ãã¦èª¬æãã¦ãã¾ããåªå
度ããããåªå
é ä½ä¸è¦§ãããã¾ãã ここにできるだけ使用できそうな値を指定し、成功した場合はmblen関数を使用します。 (このコードでは配列のサイズを1024で決め打ちしているので、それ以上のサイズのファイルの場合は途中で文字列が切れます), setlocale関数の第二引数には言語と文字コードを設定します。 setlocale、_wsetlocale | Microsoft Docs 文字列データが壊れている場合も正しい結果となりません。, ちなみに当方のテスト環境ではWindows10ではUTF-8の処理に、CentOS7ではShift_JISの処理にそれぞれ自作関数が使用されました。. ããããé
åã®å ´åãé常ã®å¼æ°ã¨ã¯ç°ãªãæ§è³ªãå¤ããæ±ãã«ãããªãã¾ãã ã¨ãããããä»ã¾ã§éãã®æ¹æ³ã§é
ååã®å¼æ°ãæã¤é¢æ°ãä½ã£ã¦ã¿ã¾ãã 弿°ã¯intåã§è¦ç´ 10ã®é
åã¨ããé
åã«ä»£å
¥ãããå¤ã®å¹³åãæ±ãã颿°ãä½ãã¾ãã C/C++ã®æ°å¤ã®0ï¼NULLï¼ç©ºæåï¼'\0'ï¼ï¼ç©ºæååï¼""ï¼ã®éããããããããªããªã£ãã®ã§æ´çããã å
é¨çãªå¤ ã¾ãï¼ãããã®å
é¨çãªå¤ã以ä¸ã®ããã°ã©ã ã§ç¢ºèªããã null.c/// \file null.c#include #define PRINT(x) printf(#x":%x\n プログラム内で使用する文字列は日本語のみ、または英数字のみと決まっているのならばそれほど問題はありませんが、これらが混在する場合に正確な文字数を得ることはできません。, 上記の実行結果はWindows+VisualStudioでコードを実行した場合です。 Code Page Identifiers - Windows applications | Microsoft Docs, mblen関数の第二引数には現在の文字コードが一文字で使用する最大のバイト数を指定します。 åºå åããã¼ã¿åãæ ¼ç´ãã夿°ãã¾ã¨ãã¦ç®¡çãããã¨ãã§ããé
åã§ããcè¨èªã§ã¯æååã¯æåã®é
åã使ã£ã¦è¡¨ç¾ããã¾ããããã§ã¯é
åã«ã¤ãã¦ç¢ºèªãã¦ããã¾ãã これはをインクルードすることで使用できます。, 出現する文字毎のバイト数が分かれば文字列全体の文字数も判別できるはずです。 ãã«ããã¤ãæåã¯Cè¨èªã§ã¯charåã®é
åã§æ±ããã¨ãã§ãã¾ãã æ¥æ¬èªä¸æåã表ãã«ã¯2ãã¤ã(以ä¸)å¿
è¦ãªã®ã§ããããã¨ããæåãæ ¼ç´ããã ãã§ãcharåé
åã使ç¨ããå¿
è¦ãããã¾ãã どちらも配列の終端にNULL文字が入っているので、文字の格納に必要なバイト数+1の配列サイズになっています。, sizeof演算子は単に配列のサイズを返すだけです。 以下はその例です。, 適当なテキストファイルを用意して、ファイルのエンコード(文字コード)に合わせてMyMBStrlen関数の引数を変更することで適切な文字数を得ることができます。 Q Cè¨èªã§æååããããæ£ããæ¸ãæ¹ãç¥ãããã§ãï¼ Cè¨èªã§æ¬¡ã®è¦åã表示ããã¾ãã æååãè¿ãããã®ã§ãããæ£ããæ¸ãæ¹ã¯ã©ã®ããã«ããã°è¯ãã®ã§ããããï¼ jci.h(20) : warning C4172; ãã¼ã«ã«å¤æ°ã¾ãã¯ãã³ãã©ãªã®ã¢ãã¬ã¹ãè¿ãã¾ãã Cè¨èªã«ã¯strlenãstrcpyãstrncpyãstrcatãstrcmpãªã©ã®æååãæ±ã颿°ãæ¨æºã©ã¤ãã©ãªã«ç¨æããã¦ãã¾ãã ãããã®é¢æ°ã使ãéã«ã¯ãããã¼ãã¡ã¤ã«ã string.h ããã¤ã³ã¯ã«ã¼ãããå¿
è¦ãããã¾ãã ã§ã³ã§æ¬ã£ãæååãªãã©ã«ãåæå¤ã¨ãã¦ä¸ãããããã¨ã¯ç¥ã£ã¦ãã¾ãããå®ã¯æååãªãã©ã«ã¯ãã¤ã³ã¿å¤æ°ã¸ãåæåã»ä»£å
¥ãããã¨ãå¯ â¦ _mbslenという類似関数もあるのですが、これもVisualStudioでしか使用できません。 これをマルチバイト文字といいます。 しかしmblen関数もsetlocale関数が必要なので、そのままではすべての環境に対応することは困難です。 C ++の文字列の場合、 strlenを使用する理由はありません。 単にstring::length使用してください:, 次の理由からstrlen(str.c_str())を強く strlen(str.c_str())します。, Clarity: length() (またはsize() )メンバ関数は、文字列の長さを明白に返します。 strlen(str.c_str())が何をしているのか把握することは可能ですが、読者は少しでも一時停止する必要があります。, 効率: length()とsize()は時間O(1)で実行され、 strlen(str.c_str())は文字列の終わりを見つけるのにΘ(n)時間かかる。, スタイル:特にそうでない特別な理由がない限り、Cバージョンの関数のC ++バージョンをC言語バージョンよりも好む方がいいです。 これは、たとえば、パフォーマンスに影響する他のいくつかの要因が作用しない限り、通常、 std::sortをqsortまたはstd::lower_boundよりもbsearchで使用する方が良いと考えられるからです。, std::string::sizeまたはstd::string::length (どちらも同じです)。, const char*を返すstd::string::c_strの使用法に注意してください。, しかし、 strlenは\0 charとstd::stringがそのようなstd::stringを格納するまでカウントします。 言い換えれば、 strlenは時々サイズのために横たわることができます。. ãã®è¨äºã§ã¯cè¨èªã«ãããé
åã¨ããæ©è½ã«ã¤ãã¦åå¿è
ã«ããããããã説æãã¦ãã¾ãã ã¾ãé
åã使ç¨ããæååã®ä½¿ãæ¹ã説æãã¦ããã®ã§åå¿è
ã®æ¹ã¯ãã²ç¿å¾ãã¦ãã ããï¼ そこで、setlocale関数で文字コードを指定できる場合はmblen関数を使用し、使用できない場合は自作関数を使用することにします。 æååãå
¥ããé
åãµã¤ãºã決ããã¨ãã¯ãnullæåã®åãèæ
®ããã㨠ãã®ç« ã®æ¦è¦ã§ãã 1. ç®ç 2. æ¹æ³â ï¼ãããããååãªè¦ç´ æ°ã確ä¿ãã¦ãããæ¿å
¥ããï¼ 2.1. é
åã®å
容ãç´æ¥å¤ãã¦ããã¨ãã«ãã使ããªã 2.2. æ¿å
¥å¾ã®æåæ°ãäºæ¸¬ã§ããªããã°ãªããªã 3. æ¹æ³â¡ï¼ã¡ã¢ãªé åãåçã«ç¢ºä¿ãã¦ãæ¿å
¥å¾ã®æååãçæããï¼ 3.1. æ¹æ³â ã®å¿
è¦æ¡ä»¶ãè§£æ¶ã§ãã 3.2. åçãªã¡ã¢ãªå²ãå½ã¦ã¯é
ãããè§£æ¾ã®ãã¨ãèããªããã°ãªããªã ããç¥ã颿°ã¨ãã¦ãstrlenãç¨æããã¦ãã¾ãã ããã§ã¯ãstrlen颿°ã®ä½¿ãæ¹ã説æãããã¨æãã¾ãã 日本語一文字を表すには2バイト(以上)必要なので、「あ」という文字を格納するだけでもchar型配列を使用する必要があります。, Shift_JISではアルファベット(半角)は一文字で1バイト、日本語は一文字で2バイトが必要です。 Cè¨èªã®sizeofã«ãããé
åããã¤ã³ã¿ãæ§é ä½ãªã©ã®åãã®ã¾ã¨ã . æ°å¤ã 2鲿° 8鲿° 10鲿° 16鲿° æååã«å¤æããæ¹æ³; æååãã³ãã¼ããæ¹æ³ãå±éºãªstrcpy颿°ã¨å®å
¨ãªæååè¤è£½ã strcpy颿°ï¼strncpy颿°ã詳解ï½å±éºæ§ã¨æ³¨æç¹ strlcpyã®èå¼±æ§ã æååãé£çµã»çµåãããstrcatã®å±éºæ§ã¨snprintfã®å®å
¨æ§ã ä»åã¯æåå颿°ã«ã¤ãã¦å¦ã³ã¾ãããã以åãé
åã使ã£ã¦æååãæ ¼ç´ãããã¨ãããã¾ãããâé
åã«ã¤ãã¦Cè¨èªã«ã¯ãã®æã®ãããªæååã«ã使ç¨ã§ãã颿°ãããã¾ããä»åã¯ãã®é¢æ°ã«ã¤ãã¦å¦ã³ã¾ããããããã§ã¯è¦ã¦ã¿ã¾ãããã<stri ã¾ãã¯æ¬¡ã®ããã°ã©ã ãã¿ã¦ã¿ã¾ãããã ã¯ããã« ä»åã¯ãæ¨æºã©ã¤ãã©ãªã®fgetc颿°ãfgets颿°ã使ã£ã¦ãããã¹ããã¡ã¤ã«ã«ä¿åãããæååããå¥ã«ç¨æããé
åï¼1次å
é
ååã³2次å
é
åï¼ã«æ ¼ç´ããæ¹æ³ã«ã¤ãã¦æ¸ãã¦ããã¾ãã ç®æ¬¡ 1. ãã¡ã¤ã«å
ã®æååã1次å
ã®é
åã«æ ¼ç´ããæ¹æ³ï¼fgetc颿°ã使ç¨ï¼ 1-1. å¹çï¼ length()ã¨size()ã¯æéOï¼1ï¼ã§å®è¡ããã strlen(str.c_str())ã¯æååã®çµãããè¦ã¤ããã®ã«Îï¼nï¼æéãããã ã¹ã¿ã¤ã«ï¼ç¹ã«ããã§ãªãç¹å¥ãªçç±ããªãéããCãã¼ã¸ã§ã³ã®é¢æ°ã®C ++ãã¼ã¸ã§ã³ãCè¨èªãã¼ã¸ã§ã³ãããå¥½ãæ¹ãããã§ãã (adsbygoogle = window.adsbygoogle || []).push({}); Code Page Identifiers - Windows applications | Microsoft Docs. ããæ¬¡ã®å¼ã§å ç®ããã len = strlen(buff1) + strlen(buff2); ããæå®ãã弿°ãå¢ãã¦ãããã¨ã§ãã (nã¯ããããnumberãnumericã®æå³) size_t strnlen( const char *str size_t numberOfElements ); 1. æååstrã®å
é ããNULLæåãåºç¾ããã¾ã§ã®ãã¤ãæ°ãåå¾ããã ãã ãnumberOfElements以ä¸ã®ãã¼ã¿ã¯èªã¿åããªãã strlen颿°ã¯NULLæåãåºç¾ããã¾ã§æåãèªã¿è¾¼ã¿ã¾ãã ããstrlen颿°ã«NULLæåã§çµãããªãcharé
åãæå®ããã¨ãé
åã®ã¡ã¢ãªé åãè¶
ã ⦠(「文字列」ではなく一文字のバイト数) 自作関数は失敗時の判定がありませんが、mblen関数は失敗すると-1を、NULL文字だった場合は0を返しますので、その場合はそこで判定を打ち切ります。, このサンプルコードはそれぞれの文字コードでの正しい文字列を先頭から順に読んだ場合にのみ処理できます。 ASCIIでは制御文字も含めて0~127に文字を割り当てており、char型ですべての文字を扱うことができます。, しかし日本語などは文字種が多く、1バイトでは足りないので2バイト以上を使用してひとつの文字を表します。 strlen関数はマルチバイト文字を想定していないので結局はバイト数を返しますが(NULL文字が出現するまでのバイト数)、_mbstrlen関数はマルチバイト文字を一文字と数え、正しい文字数を返します。, しかし_mbstrlen関数はVisualStudioでは使用できますが、他のコンパイラでは使用できません。 Cè¨èªå
¥éï¼æååãæ¯è¼ãã(strcmp) 2ã¤ã®æååãæ¯è¼ãã颿°ã¨ãã¦ãstrcmpãç¨æããã¦ãã¾ãã ããã§ã¯ãstrcmp颿°ã®ä½¿ãæ¹ã説æãããã¨æãã¾ãã cè¨èª å
¥é; é
å. マルチバイト文字の途中(2バイト目以降)から読み込むことはできません。 æååstrããNULL(\0)ã®ç´åã¾ã§ã®æåæ°ãæ±ããã(NULLã¯æåæ°ã«ã¯å«ããªãï¼ strã®ä¸ã«NULLãåå¨ããªãå ´åã以éã®é åãä¾µãã¦ã§ãNULLãæ¢ãã®ã§æ³¨æãè¦ããã Cè¨èªã§ã intåã®é
åãåãåãã ãã®æå°å¤ãæ»ã颿°int minimumï¼int *ï¼ï¼ã使ããã ãã ããåãåãé
åã®æå¾ã®è¦ç´ ã«ã¯å¿
ã0ãå
¥ã£ã¦ãããã®ã¨ããæå¹ãã¼ã¿ããªãå
é è¦ç´ ã«0ãå
¥ã£ã¦ããå ´åã¯0 ãæ»ãã 設定に失敗するとNULLを返します。 Cè¨èªã§ã¯æååã®çµç«¯ã示ãããã«ãæåã³ã¼ã 0 ã®ç¹å¥ãªæå nullæåï¼'\0'ï¼ãç¨ããæ±ºã¾ãã«ãªã£ã¦ãã¾ããã ããã§ã¯ãnullæåã«é¢ããTipsãããã¤ãæãããã¨æãã¾ãã nullæåã«é¢ããTips. (先頭にアンダースコアが付けられている関数はマイクロソフト独自の拡張です), また、マルチバイト文字を扱う関数を使用する場合、事前にsetlocale関数で文字コードを指定するのですが、Windows環境ではどうもUTF-8が設定できないようです。 Cè¨èªã®sizeofã«ã¤ãã¦è²ã
調ã¹ãã®ã§ã¾ã¨ãã¦ã¿ã¾ããã ... åèè¨äºï¼ä¾ã¨ã³ã¸ãã¢å¡¾ã®Cè¨èªã®ãµã³ãã«ãã¤ããããã - Qiita. 第二引数は使用しないのですが、mblen関数との整合性のために設定しています。, mblen関数も自作関数も一文字に使用されているバイト数を返しますので、戻り値の分だけポインタを進めることで次の文字の先頭バイトにポインタ位置をセットしています。 æ°å¤ã¸ã®å¤æ Cè¨èªã«ã¯ãæååãå¦çããããã®æ§ã
ãªé¢æ°ãç¨æããã¦ãã¾ãã ãããããã¾ã使ããã¨ã§ãæååãèªç±ã«å¦çã§ãã¾ãã atoi颿°ã¯ãæååãæ°å¤ã«å¤æããçµæã夿°ã«ä»£å
¥ã㾠⦠英語圏で使用される文字は種類が少ないので、1バイト(256種)の情報量ですべての文字を表すことができます。 çµç«¯æååãåºç¾ããã¾ã§ãã¤ã³ããã¯ã¹ãã«ã¼ãå¦ç 1ã¤ç®ã¯ãä¸è¨ã®ããã«ãçµç«¯æååãåºç¾ããã¾ã§ãé
åã®ã¤ã³ããã¯ã¹ãwhileæã§ã«ã¼ãå¦çãã¦åç
§ããæ¹æ³ã§ãã ãã¤ã³ã¿ã使ãã¨ã¿ã«ãããªãã¨æããã®ã§ã好ããªæ¹ã»ã»ã» 同じコードをUTF-8で扱う環境でコンパイル&実行すると「2」と「4」が出力されるはずです。 1バイトのみで表せる文字をシングルバイト文字といいます。, マルチバイト文字はC言語ではchar型の配列で扱うことができます。 é
åã®è¦ç´ æ°ã¯ ã¨ãã2ã¹ãããã§ç°¡åã«æ±ãããã¾ãããµã³ãã«ã³ã¼ãã¯ä»¥ä¸ã®éãã§ãã å®è¡çµæï¼ sizeofæ¼ç®åããã¤ãåä½ã§ã¡ã¢ãªãµã¤ãºãæ±ãã¦ãããã®ã§ã é
åã®è¦ç´ æ°(arrayNumber) = é
åã®è¦ç´ å
¨ä½ã®å¤§ãã(sizeof array) / é
åã®è¦ç´ ä¸ã¤åã®å¤§ãã(sizeof array[0]) ã¨ããç°¡åãªå²ãç®ã®å¼ã§é
åã®è¦ç´ æ°ãæ±ãããã¨ãã§ãã¾ãã 文字コードによって一文字に必要なバイト数が変わることは知っておいた方が良いです。, ちなみにShift_JISの半角カナは1バイトですが、EUC-JPの場合は2バイトです。, 文字列の長さの取得の項では、文字数のカウントにはstrlen関数か_mbstrlen関数を使用すると説明しました。 これはMB_CUR_MAXという定数がありますので、それを指定します。, バイト数判定の自作関数はマルチバイト文字の先頭のバイトを見てその文字のバイト数を判別しています。 詳しくは以下を参考にしてください。