質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.39%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

552閲覧

Visual StudioにおけるC++の文字化け

jigorw

総合スコア2

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

文字コード

文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2024/06/19 12:48

編集2024/06/19 12:51

実現したいこと

プログラミング初学者です。
日本株のデータ収集および分析のためのプログラムを作成したいと思い、
kabuステーションAPI  https://kabucom.github.io/kabusapi/reference/index.html
を用いて、C++プログラムの開発を試みています。
トークンを取得することは出来たのですが、そのトークンを用いて先物銘柄コードの取得を取得を試みた際に、実行結果に文字化けが発生してしまいました。

発生している問題・分からないこと

実行結果の一部が文字化けしております。(Tokenの値は一部変更しております。)

API Response: {"ResultCode":0,"Token":"f4efee8659b7d089173f9a51bd"}
Retrieved API Token: f4efee865bea4cc9b7d0a51bd
API Response: {"Symbol":"169090018","SymbolName":"譌・邨悟ケウ蝮・・迚ゥ 24/09"}
Retrieved Future Symbol: {"Symbol":"169090018","SymbolName":"譌・邨悟ケウ蝮・・迚ゥ 24/09"}

該当のソースコード

TKO.cpp

1#include <iostream> 2#include "token_fetcher.h" 3#include "future_symbol_fetcher.h" 4 5int main() { 6 std::string apiPassword = ""; /*blank for public access*/ 7 TokenFetcher tokenFetcher(apiPassword); 8 9 std::string token = tokenFetcher.getApiToken(); 10 std::cout << "Retrieved API Token: " << token << std::endl; 11 12 FutureSymbolFetcher futureSymbolFetcher(token); 13 std::string futureCode = "NK225"; 14 std::string derivMonth = "202409"; 15 16 std::string futureSymbol = futureSymbolFetcher.getFutureSymbol(futureCode, derivMonth); 17 std::cout << "Retrieved Future Symbol: " << futureSymbol << std::endl; 18 19 return 0; 20} 21 22 23} 24

future_symbol_fetcher.cpp

1#include "future_symbol_fetcher.h" 2#include <iostream> 3#include <cstring> 4#include <cstdlib> 5 6FutureSymbolFetcher::FutureSymbolFetcher(const std::string& apiToken) : apiToken(apiToken) {} 7 8FutureSymbolFetcher::~FutureSymbolFetcher() {} 9 10size_t FutureSymbolFetcher::WriteMemoryCallback(void* contents, size_t size, size_t nmemb, void* userp) { 11 size_t realsize = size * nmemb; 12 struct MemoryStruct* mem = (struct MemoryStruct*)userp; 13 14 char* ptr = (char*)realloc(mem->memory, mem->size + realsize + 1); 15 if (ptr == NULL) { 16 std::cerr << "Not enough memory (realloc returned NULL)\n"; 17 return 0; 18 } 19 20 mem->memory = ptr; 21 std::memcpy(&(mem->memory[mem->size]), contents, realsize); 22 mem->size += realsize; 23 mem->memory[mem->size] = 0; 24 25 return realsize; 26} 27 28std::string FutureSymbolFetcher::getFutureSymbol(const std::string& futureCode, const std::string& derivMonth) { 29 CURL* curl; 30 CURLcode res; 31 struct curl_slist* headers = NULL; 32 struct MemoryStruct chunk; 33 34 chunk.memory = (char*)malloc(1); 35 chunk.size = 0; 36 37 curl_global_init(CURL_GLOBAL_DEFAULT); 38 curl = curl_easy_init(); 39 40 if (curl) { 41 std::string apiUrl = apiUrlBase + "?FutureCode=" + futureCode + "&DerivMonth=" + derivMonth; 42 43 headers = curl_slist_append(headers, ("X-API-KEY: " + apiToken).c_str()); 44 45 curl_easy_setopt(curl, CURLOPT_URL, apiUrl.c_str()); 46 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 47 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); 48 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&chunk); 49 50 res = curl_easy_perform(curl); 51 52 if (res != CURLE_OK) { 53 std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; 54 } 55 else { 56 std::cout << "API Response: " << chunk.memory << std::endl; 57 } 58 59 curl_easy_cleanup(curl); 60 curl_slist_free_all(headers); 61 } 62 63 curl_global_cleanup(); 64 65 std::string futureSymbol(chunk.memory); 66 free(chunk.memory); 67 68 return futureSymbol; 69} 70

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

・構成プロパティ>C/C++>コマンドライン>追加のオプション
に「/utf-8」を追加しました。
→実行結果に変化なし

・future_symbol_fetcher.cppについて、
ファイル>名前を付けて future_symbol_fetcher.cpp を保存>エンコード付きで保存>
にて、エンコードをUnicode(UTF-8 シグネチャ付き) コードページ 65001で保存
→実行結果に変化なし

補足

main.cppファイルのソースコードをすべてコメントアウトし、以下のプログラムを実行した場合にも、文字化けが発生しています。
//#include <iostream>
//
//int main() {
// std::cout << "有難うございます" << std::endl;
//

しかし、別のプロジェクトを立ち上げ、上記のプログラムを実行した場合は文字化けが発生していません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiroki-o

2024/06/19 15:43

UTF-8をShift_JISで開いた時の文字化けですね。(表示したいテキストは、日経平均先物)
natural2

2024/06/19 15:49

.editorconfigでcharset utf-8-bom 指定するのが楽な解決方法な気もします
guest

回答2

0

ベストアンサー

Windows 11で確認しました。

提示の環境の場合、std::stringにはUTF-8で格納されていますが、std::coutした先のコマンドプロンプトのデフォルトがShift_JISのため、文字化けしています。
コマンドプロンプトをUTF-8に変更するには

chcp 65001

と叩きます。元のShift_JISに戻すには、コマンドプロンプトを開き直すか、

chcp 932

と叩きます。

Visual Studioのプロジェクトの設定を何も変更せずに、std::cout<<"~"<<std::endl;した場合はShift_JISなので、別のプロジェクトでは文字化けしなかったのです。

投稿2024/06/19 16:18

hiroki-o

総合スコア896

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jigorw

2024/06/20 09:23

早々にご返事いただいたのにも関わらず、お礼が遅くなってしまい申し訳ございません。 hitoki-oさんが回答して下さったことで、問題を解決することが出来ました。 ファイルを追加する過程でエンコードの方法が変わってしまった、とばかりを考えており、コマンドプロンプト側が原因だとは考えてられておりませんでした。 詳細な説明までしていただき、ありがとうございました。
guest

0

回答ではありません

挙動はランタイムライブラリと端末のコードページ(chcpの設定値、GetConsoleOutputCPの戻り値)の他に、Cのロケール設定(""の場合はシステムロケール設定(GetACPの戻り値))やC++のロケール設定(今回は省略)に依存します。
私の環境はVS2019と古いし、C++のバージョンも確か14相当だと思うので新しいバージョンだと違う可能性が高いですが、色々な状況での出力を残しておきますね。

なお、/utf-8オプションのビルドはソースコードの文字セットの他に、実行時の文字セットも同時指定するオプションです。ソースコードの文字セットは正しく指定されれば何を指定してもバイナリに影響しませんが、実行時の文字セットはバイナリ内に含まれる文字セットも変わるので、実行時の文字セット(/execution-charset)はutf-8にもして試しています。

補足としてu8が付いている文字列リテラルは内部的にソースコードの文字セットをUTF-8に変換したものが入っています。

ご参考までに。

c++

1#include <iostream> 2#include <clocale> 3#include <iomanip> 4#include <windows.h> 5void print(std::string s) { 6 for (char ch : s) { 7 std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(static_cast<unsigned char>(ch)) << std::dec << " "; 8 } 9 std::cout << std::endl; 10 std::cout << s << std::endl; 11} 12int main() 13{ 14 auto acp = GetACP(); 15 auto cp = GetConsoleOutputCP(); 16 std::cout << "ANSI CP/Terminal CP: " << acp << "/" << cp << std::endl; 17 const char* locales[] = { "C", "", ".UTF-8" }; 18 for (const auto s : locales) { 19 std::cout << "===== std::setlocale(LC_CTYPE, \"" << s << "\"); =====" << std::endl; 20 auto l = std::setlocale(LC_CTYPE, s); 21 std::cout << "current locale: " << l << std::endl; 22 print("テスト (normal)"); 23 print(u8"テスト (utf8)"); 24 } 25 return 0; 26}

普通にビルドして実行した場合

端末がCP932だった場合(chcp 932)

console

1ANSI CP/Terminal CP: 932/932 2===== std::setlocale(LC_CTYPE, "C"); ===== 3current locale: C 483 65 83 58 83 67 20 28 6e 6f 72 6d 61 6c 29 5テスト (normal) 6e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 7繝・せ繝・(utf8) 8===== std::setlocale(LC_CTYPE, ""); ===== 9current locale: Japanese_Japan.932 1083 65 83 58 83 67 20 28 6e 6f 72 6d 61 6c 29 11テスト (normal) 12e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 13繝・せ繝・(utf8) 14===== std::setlocale(LC_CTYPE, ".UTF-8"); ===== 15current locale: Japanese_Japan.utf8 1683 65 83 58 83 67 20 28 6e 6f 72 6d 61 6c 29 17 18e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 19テスト (utf8) 20

端末がCP65001だった場合(chcp 65001)

console

1ANSI CP/Terminal CP: 932/65001 2===== std::setlocale(LC_CTYPE, "C"); ===== 3current locale: C 483 65 83 58 83 67 20 28 6e 6f 72 6d 61 6c 29 5eXg (normal) 6e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 7テスト (utf8) 8===== std::setlocale(LC_CTYPE, ""); ===== 9current locale: Japanese_Japan.932 1083 65 83 58 83 67 20 28 6e 6f 72 6d 61 6c 29 11テスト (normal) 12e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 13繝・せ繝・(utf8) 14===== std::setlocale(LC_CTYPE, ".UTF-8"); ===== 15current locale: Japanese_Japan.utf8 1683 65 83 58 83 67 20 28 6e 6f 72 6d 61 6c 29 17 18e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 19テスト (utf8) 20

/execution-charset:utf-8 でビルドして実行した場合

端末がCP932だった場合(chcp 932)

console

1ANSI CP/Terminal CP: 932/932 2===== std::setlocale(LC_CTYPE, "C"); ===== 3current locale: C 4e3 83 86 e3 82 b9 e3 83 88 20 28 6e 6f 72 6d 61 6c 29 5繝・せ繝・(normal) 6e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 7繝・せ繝・(utf8) 8===== std::setlocale(LC_CTYPE, ""); ===== 9current locale: Japanese_Japan.932 10e3 83 86 e3 82 b9 e3 83 88 20 28 6e 6f 72 6d 61 6c 29 11繝・せ繝・(normal) 12e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 13繝・せ繝・(utf8) 14===== std::setlocale(LC_CTYPE, ".UTF-8"); ===== 15current locale: Japanese_Japan.utf8 16e3 83 86 e3 82 b9 e3 83 88 20 28 6e 6f 72 6d 61 6c 29 17テスト (normal) 18e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 19テスト (utf8) 20

端末がCP65001だった場合(chcp 65001)

console

1ANSI CP/Terminal CP: 932/65001 2===== std::setlocale(LC_CTYPE, "C"); ===== 3current locale: C 4e3 83 86 e3 82 b9 e3 83 88 20 28 6e 6f 72 6d 61 6c 29 5テスト (normal) 6e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 7テスト (utf8) 8===== std::setlocale(LC_CTYPE, ""); ===== 9current locale: Japanese_Japan.932 10e3 83 86 e3 82 b9 e3 83 88 20 28 6e 6f 72 6d 61 6c 29 11繝・せ繝・(normal) 12e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 13繝・せ繝・(utf8) 14===== std::setlocale(LC_CTYPE, ".UTF-8"); ===== 15current locale: Japanese_Japan.utf8 16e3 83 86 e3 82 b9 e3 83 88 20 28 6e 6f 72 6d 61 6c 29 17テスト (normal) 18e3 83 86 e3 82 b9 e3 83 88 20 28 75 74 66 38 29 19テスト (utf8) 20

投稿2024/06/20 01:18

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jigorw

2024/06/20 10:29

全体の理解が深まる回答をしていただき、ありがとうございます。 ご回答いただけたことで、 端末のコードページ以外にも挙動に関わる要素がある点、と/utf-8オプションにはソースコード・実行時・およびその両方に影響するものがあることを知ることが出来ました。
退会済みユーザー

退会済みユーザー

2024/06/20 11:03

よく読むと ソースコードはシフトJISのままでも、/execution-charset:utf-8指定することで、 またロケール設定を変更することで、全ての文字列をUTF-8として動作させることができ、端末のコードページに関係なくシフトJISにある文字なら出力できることが分かります。 逆に言うと今度はシフトJISの文字列を処理できなくなるわけですけどね。 C++のロケール設定だとプロセス全体に影響させないような機能もあるのですが、既存の標準機能は特に文字セットの変換に問題があり17で非推奨となり26で削除予定。しかも代替機能が出たという話も聞いておらず、先行き不透明でとても回答に使えるような状態ではありません。 標準でなければいくつかライブラリがあるし、プラットフォーム固有のAPIも利用可能ですが、そこまで行くと質問内容との乖離が大きくなります。で、中途半端ではありますが、こんな記載になっております。そもそもプラットフォーム依存をしたくないのかも分かりませんし、文字化けしたというだけで何をどうしたいのかよく分からなかったですけどね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.39%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問