teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

4

m

2020/05/30 14:13

投稿

yumetodo
yumetodo

スコア5852

answer CHANGED
@@ -103,6 +103,8 @@
103
103
  }
104
104
  ```
105
105
 
106
+ [https://wandbox.org/permlink/sSSbwj1fHIyB06jH](https://wandbox.org/permlink/sSSbwj1fHIyB06jH)
107
+
106
108
  なおより本格的に扱う場合はicuというライブラリを利用します。
107
109
 
108
110
  ## 参照

3

ref

2020/05/30 14:13

投稿

yumetodo
yumetodo

スコア5852

answer CHANGED
@@ -110,4 +110,7 @@
110
110
  - [C++標準化委員会、ついに文字とは何かを理解する: char8_t](https://qiita.com/yumetodo/items/54e1a8230dbf513ea85b)
111
111
  - [UTF-8エンコーディングされた文字の型として`char8_t`を追加 - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp20/char8_t.html)
112
112
  - [UTF-8文字リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp17/utf8_character_literals.html)
113
- - [UTF-8文字列リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp11/utf8_string_literals.html)
113
+ - [UTF-8文字列リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp11/utf8_string_literals.html)
114
+ - [svリテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/reference/string_view/basic_string_view/op_sv.html)
115
+ - [basic_string_view::substr - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/reference/string_view/basic_string_view/substr.html)
116
+ - [basic_string::コンストラクタ - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/reference/string/basic_string/op_constructor.html) (14)のコンストラクタを呼び出している

2

string

2020/05/30 13:21

投稿

yumetodo
yumetodo

スコア5852

answer CHANGED
@@ -60,6 +60,51 @@
60
60
 
61
61
  Windowsで動作させるときはWindows 10 1607よりあとのOSで、あらかじめ`chcp 65001`したコマンドプロンプトで実行してください。
62
62
 
63
+ なお余談ですが、C++がCから受け継いだ文字列操作系関数はいくつもありますが、このうち多くの関数が安全に使うのが難しいものです。実際MSVCでは`_CRT_SECURE_NO_WARNINGS`なしではそれらの関数に警告を出すはずです。なのでもしC言語のような文字操作をするなら、`memcpy`を利用すると良いです。`strcpy`と違い、文字数より一つ多くバッファを確保しなければならないことを忘れる懸念は自分で明示的にNULL文字を代入しますから減りますし、実際MSVCは何も言ってきません。
64
+
65
+ しかしまあ、せっかくC++を使うのですからもう少しだけC++っぽく扱ってみましょう。`std::basic_string`とC++17で追加された`std::basic_string_view`を使います。`std::basic_string_view`を使って`std::basic_string`を構築するときに勝手にNULL文字終端する性質を利用しています。
66
+
67
+ ```cpp
68
+ #include <iostream>
69
+ #include <string>
70
+ #include <string_view>
71
+ #include <stdexcept>
72
+ #if !defined(__cpp_char8_t)
73
+ using char8_t = char;
74
+ #endif
75
+ std::size_t charlen(const char8_t* s)
76
+ {
77
+ if (*s == 0) {
78
+ } else if ((*s & 0x80) == 0) {
79
+ return 1u;
80
+ } else if ((*s & 0xE0) == 0xC0) {
81
+ return 2u;
82
+ } else if ((*s & 0xF0) == 0xE0) {
83
+ return 3u;
84
+ } else if ((*s & 0xF8) == 0xF0) {
85
+ return 4u;
86
+ }
87
+ return 0;
88
+ }
89
+ auto extract_nth_char(std::basic_string_view<char8_t> s, std::size_t n)
90
+ {
91
+ std::size_t front_i = 0, len = 0, limit = n ? n - 1 : throw std::invalid_argument("0 is invalid");
92
+ for (std::size_t i = 0; i < limit; ++i, front_i += len = charlen(&s.data()[front_i]));
93
+ return s.substr(front_i, len);
94
+ }
95
+ int main()
96
+ {
97
+ using namespace std::literals;
98
+ const auto str = u8"あいうえお"sv;//string_viewになる
99
+ //std::basic_stringに変換することでNULL終端する
100
+ const std::basic_string<char8_t> dest{extract_nth_char(str, 3)};
101
+ //コンソールの文字エンコードがUTF-8だと仮定する
102
+ std::cout << reinterpret_cast<const char*>(dest.c_str()) << std::endl;
103
+ }
104
+ ```
105
+
106
+ なおより本格的に扱う場合はicuというライブラリを利用します。
107
+
63
108
  ## 参照
64
109
 
65
110
  - [C++標準化委員会、ついに文字とは何かを理解する: char8_t](https://qiita.com/yumetodo/items/54e1a8230dbf513ea85b)

1

ref

2020/05/30 13:18

投稿

yumetodo
yumetodo

スコア5852

answer CHANGED
@@ -58,4 +58,11 @@
58
58
 
59
59
  [https://wandbox.org/permlink/BIkWAMmrI0t1KHa6](https://wandbox.org/permlink/BIkWAMmrI0t1KHa6)
60
60
 
61
- Windowsで動作させるときはWindows 10 1607よりあとのOSで、あらかじめ`chcp 65001`したコマンドプロンプトで実行してください。
61
+ Windowsで動作させるときはWindows 10 1607よりあとのOSで、あらかじめ`chcp 65001`したコマンドプロンプトで実行してください。
62
+
63
+ ## 参照
64
+
65
+ - [C++標準化委員会、ついに文字とは何かを理解する: char8_t](https://qiita.com/yumetodo/items/54e1a8230dbf513ea85b)
66
+ - [UTF-8エンコーディングされた文字の型として`char8_t`を追加 - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp20/char8_t.html)
67
+ - [UTF-8文字リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp17/utf8_character_literals.html)
68
+ - [UTF-8文字列リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp11/utf8_string_literals.html)