回答編集履歴

4

m

2020/05/30 14:13

投稿

yumetodo
yumetodo

スコア5852

test CHANGED
@@ -208,6 +208,10 @@
208
208
 
209
209
 
210
210
 
211
+ [https://wandbox.org/permlink/sSSbwj1fHIyB06jH](https://wandbox.org/permlink/sSSbwj1fHIyB06jH)
212
+
213
+
214
+
211
215
  なおより本格的に扱う場合はicuというライブラリを利用します。
212
216
 
213
217
 

3

ref

2020/05/30 14:13

投稿

yumetodo
yumetodo

スコア5852

test CHANGED
@@ -223,3 +223,9 @@
223
223
  - [UTF-8文字リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp17/utf8_character_literals.html)
224
224
 
225
225
  - [UTF-8文字列リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp11/utf8_string_literals.html)
226
+
227
+ - [svリテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/reference/string_view/basic_string_view/op_sv.html)
228
+
229
+ - [basic_string_view::substr - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/reference/string_view/basic_string_view/substr.html)
230
+
231
+ - [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

test CHANGED
@@ -122,6 +122,96 @@
122
122
 
123
123
 
124
124
 
125
+ なお余談ですが、C++がCから受け継いだ文字列操作系関数はいくつもありますが、このうち多くの関数が安全に使うのが難しいものです。実際MSVCでは`_CRT_SECURE_NO_WARNINGS`なしではそれらの関数に警告を出すはずです。なのでもしC言語のような文字操作をするなら、`memcpy`を利用すると良いです。`strcpy`と違い、文字数より一つ多くバッファを確保しなければならないことを忘れる懸念は自分で明示的にNULL文字を代入しますから減りますし、実際MSVCは何も言ってきません。
126
+
127
+
128
+
129
+ しかしまあ、せっかくC++を使うのですからもう少しだけC++っぽく扱ってみましょう。`std::basic_string`とC++17で追加された`std::basic_string_view`を使います。`std::basic_string_view`を使って`std::basic_string`を構築するときに勝手にNULL文字終端する性質を利用しています。
130
+
131
+
132
+
133
+ ```cpp
134
+
135
+ #include <iostream>
136
+
137
+ #include <string>
138
+
139
+ #include <string_view>
140
+
141
+ #include <stdexcept>
142
+
143
+ #if !defined(__cpp_char8_t)
144
+
145
+ using char8_t = char;
146
+
147
+ #endif
148
+
149
+ std::size_t charlen(const char8_t* s)
150
+
151
+ {
152
+
153
+ if (*s == 0) {
154
+
155
+ } else if ((*s & 0x80) == 0) {
156
+
157
+ return 1u;
158
+
159
+ } else if ((*s & 0xE0) == 0xC0) {
160
+
161
+ return 2u;
162
+
163
+ } else if ((*s & 0xF0) == 0xE0) {
164
+
165
+ return 3u;
166
+
167
+ } else if ((*s & 0xF8) == 0xF0) {
168
+
169
+ return 4u;
170
+
171
+ }
172
+
173
+ return 0;
174
+
175
+ }
176
+
177
+ auto extract_nth_char(std::basic_string_view<char8_t> s, std::size_t n)
178
+
179
+ {
180
+
181
+ std::size_t front_i = 0, len = 0, limit = n ? n - 1 : throw std::invalid_argument("0 is invalid");
182
+
183
+ for (std::size_t i = 0; i < limit; ++i, front_i += len = charlen(&s.data()[front_i]));
184
+
185
+ return s.substr(front_i, len);
186
+
187
+ }
188
+
189
+ int main()
190
+
191
+ {
192
+
193
+ using namespace std::literals;
194
+
195
+ const auto str = u8"あいうえお"sv;//string_viewになる
196
+
197
+ //std::basic_stringに変換することでNULL終端する
198
+
199
+ const std::basic_string<char8_t> dest{extract_nth_char(str, 3)};
200
+
201
+ //コンソールの文字エンコードがUTF-8だと仮定する
202
+
203
+ std::cout << reinterpret_cast<const char*>(dest.c_str()) << std::endl;
204
+
205
+ }
206
+
207
+ ```
208
+
209
+
210
+
211
+ なおより本格的に扱う場合はicuというライブラリを利用します。
212
+
213
+
214
+
125
215
  ## 参照
126
216
 
127
217
 

1

ref

2020/05/30 13:18

投稿

yumetodo
yumetodo

スコア5852

test CHANGED
@@ -119,3 +119,17 @@
119
119
 
120
120
 
121
121
  Windowsで動作させるときはWindows 10 1607よりあとのOSで、あらかじめ`chcp 65001`したコマンドプロンプトで実行してください。
122
+
123
+
124
+
125
+ ## 参照
126
+
127
+
128
+
129
+ - [C++標準化委員会、ついに文字とは何かを理解する: char8_t](https://qiita.com/yumetodo/items/54e1a8230dbf513ea85b)
130
+
131
+ - [UTF-8エンコーディングされた文字の型として`char8_t`を追加 - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp20/char8_t.html)
132
+
133
+ - [UTF-8文字リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp17/utf8_character_literals.html)
134
+
135
+ - [UTF-8文字列リテラル - cpprefjp C++日本語リファレンス](https://cpprefjp.github.io/lang/cpp11/utf8_string_literals.html)