質問するログイン新規登録
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio Code

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

Q&A

解決済

1回答

217閲覧

C言語による将棋のプログラムについて

todasan

総合スコア81

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual Studio Code

Visual Studio Codeとは、Microsoft社が開発したマルチプラットフォーム対応のテキストエディタです。Visual Studioファミリーの一員でもあります。拡張性とカスタマイズ性が高く、テキストエディタでありながら、IDEと遜色ない機能を備えることができます。

0グッド

2クリップ

投稿2025/09/25 05:25

編集2025/09/25 05:28

0

2

実現したいこと

将棋のプログラムをC言語で作成しています。gccを使い、visualstudiocodeで、作成しています。
文字列の切り出しがうまくできないです。

shougi_shisaku.cの以下の部分で、koma_strに先香と切り出しいですが、画像の結果の
ようにうまくできません。どのように記載すればよろしいですか。
画像にvisualstudiocodeから実行して、以下のprint文のdataretu[koma_data].komaには、
先香が入っている事は確認できました。
↓この書き方で、koma_strに先香は格納されませんが、どのように記載すれば、よろしいですか。

memcpy((void *)koma_str, dataretu[koma_data].koma, 5);

printf("dataretu[koma_data].koma|%s \n", dataretu[koma_data].koma); memcpy((void *)koma_str, dataretu[koma_data].koma, 5); printf("koma_str|%s \n", koma_str);

shougi_shisaku.c

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> // #include <iostream> // #include "shougi_shisaku.h" extern void explode(const char*, char*, int); // 項目を取り出す person data[81]; // 駒のデータの読み込み person dataretu[81]; // 駒のデータのコピー先 char kuuhaku[] = "  "; char tate_str[] = "一二三四五六七八九"; int tate_mae, yoko_mae, tate_ato, yoko_ato; void banmen_hyouji() { int readtate, readyoko, coma_cnt = 0; char sub_str[4]; printf("将棋盤\n"); printf("|9    |8    |7    |6    |5    |4    |3    |2    |1     \n"); printf("--------------------------------------------------------------------------------------------\n"); for (readtate = 1; readtate < 10; readtate++) { for (readyoko = 9; readyoko > 0; readyoko--) { if (dataretu[coma_cnt].tate == readtate && dataretu[coma_cnt].yoko == readyoko && dataretu[coma_cnt].koma[0] != '\0') { // 駒の情報がある時 printf("|%s ", &dataretu[coma_cnt].koma[0]); coma_cnt++; } else { // 駒の情報がない時 printf("|%s ", kuuhaku); coma_cnt++; } if (readyoko == 1) { // 縦の駒番号を表示する。 // strから部分文字列を切り出す strncpy(sub_str, tate_str + (readtate - 1) * 2, 2); sub_str[3] = '\0'; // 切り出した部分の終端文字を追加 // printf("|%s ", sub_str); } } printf("\n"); printf("--------------------------------------------------------------------------------------------\n"); } } void taikyoku_kaisi() { int koma_data; char koma_str[10] = {}; printf("***先手の番です***\n"); printf("***どの地点を動かしますか***\n"); scanf("%d%d", &tate_mae,&yoko_mae); printf("***どこにを動かしますか***\n"); scanf("%d%d", &tate_ato, &yoko_ato); for (koma_data = 0; koma_data < 81; koma_data++){ if (dataretu[koma_data].tate == tate_mae && dataretu[koma_data].yoko == yoko_mae){ printf("dataretu[koma_data].koma|%s \n", dataretu[koma_data].koma); memcpy((void *)koma_str, dataretu[koma_data].koma, 5); printf("koma_str|%s \n", koma_str); memset((void *)dataretu[koma_data].koma, '\0', 10); } } for (koma_data = 0; koma_data < 81; koma_data++){ if (dataretu[koma_data].tate == tate_ato && dataretu[koma_data].yoko == yoko_ato){ memcpy((void*)dataretu[koma_data].koma, (const void*)koma_str, 10); } } } int main() { FILE* fp; char buf[512], * cp; int tatehoukou; printf("\n***将棋ゲーム***\n"); fopen_s(&fp,"shougi_banmen.csv", "r"); // 将棋のファイルを開く if (fp == NULL) goto END; // ファイルを開けない tatehoukou = 0; memset(&data[0], '\0', sizeof(data)); // データの全文字をNULLに while (1) { cp = fgets(buf, 256, fp); // 1レコードを読む if (cp == NULL) break; // EOF explode(",", buf, tatehoukou); // csvデータを1行ずつ、項目を取り出す tatehoukou = tatehoukou + 1; if (tatehoukou == 9) break; } fclose(fp); // 将棋のファイルを閉じる // memcpyを使ったコピー memcpy(&dataretu, &data, sizeof(person)*81); banmen_hyouji(); taikyoku_kaisi(); banmen_hyouji(); END:; }
後香,後桂,後銀,後金,後王,後金,後銀,後桂,後香, ,後飛,,,,,,後角,, 後歩,後歩,後歩,後歩,後歩,後歩,後歩,後歩,後歩, ,,,,,,,,, ,,,,,,,,, ,,,,,,,,, 先歩,先歩,先歩,先歩,先歩,先歩,先歩,先歩,先歩, ,先角,,,,,,先飛,, 先香,先桂,先銀,先金,先王,先金,先銀,先桂,先香,

explode.c

#include <stdio.h> // #include <iostream> // #include "shougi_shisaku.h" void explode(const char*, char*, int); // 項目を取り出す extern person data[81]; // 駒のデータの読み込み int koma_cnt = 0; void explode( /*----------------------------------*/ /* CSVデータから項目を取り出す */ /*----------------------------------*/ const char* kugiri, // 区切り文字 char* buf, // CSVの1レコード int tatehoukou) { char* cp0, * cp; int yokohoukou = 0, len; cp0 = buf; // CSVデータの先頭アドレス for (yokohoukou = 0; yokohoukou < 9; yokohoukou++) { if (*cp0 == 0x22) cp0++; // 最初の"(0x22)を除く cp = strstr(cp0, kugiri); // 区切り文字を検索 if (cp == NULL) break; // 区切り文字なし len = cp - cp0; // 項目の文字数 if (*(cp - 1) == 0x22) len--; // 最後の"(0x22)を除く if (len > 0) // 項目あり { memcpy(&data[koma_cnt].koma[0], cp0, len); // 項目の文字列をコピー data[koma_cnt].tate = tatehoukou + 1; data[koma_cnt].yoko = 9 - yokohoukou; koma_cnt = koma_cnt + 1; }else{ data[koma_cnt].tate = tatehoukou + 1; data[koma_cnt].yoko = 9 - yokohoukou; koma_cnt = koma_cnt + 1; } cp0 = cp + 1; // 次の文字のアドレス } }

shougi_shisaku.h

typedef struct hyakunin { int tate; // �ʒu_�c int yoko; // �ʒu_�� char koma[10]; // ��̎�� } person;

Makefile

# コンパイラの指定 CC=gcc # コンパイル時のオプション CFLAGS=-I. -Wall # 最終的な実行ファイル名 TARGET=myapp.exe # 最終ターゲット $(TARGET): shougi_shisaku.o explode.o $(CC) -o $(TARGET) shougi_shisaku.o explode.o # main.cからmain.oを生成 shougi_shisaku.o: shougi_shisaku.c $(CC) -c shougi_shisaku.c $(CFLAGS) # sub.cからsub.oを生成 explode.o: explode.c $(CC) -c explode.c $(CFLAGS) # 'make clean' を実行した時に実行ファイルとオブジェクトファイルを削除 clean: rm -f $(TARGET) shougi_shisaku.o explode.o

イメージ説明

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

質問に詳細を記載した。

エラーメッセージ

error

1質問に詳細を記載した。

該当のソースコード

特になし

試したこと・調べたこと

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

質問に詳細を記載した。

補足

特になし

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

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

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

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

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

melian

2025/09/25 05:52 編集

memcpy((void *)koma_str, dataretu[koma_data].koma, 5); ですが、koma_str と person.koma の容量は 10 なので全てコピーすればよいのではないでしょうか。(5を10に変更)
int32_t

2025/09/25 05:51

memcpy()ではなくstrcpy()を使うと直ったりしますか?
todasan

2025/09/25 06:07

int32_t さん ご指摘ありがとうございます。 melian さん 10で全てコピーして直りました。ありがとうございます。 なぜ5ですとうまくできないのかは、御存知ですか。
toge_

2025/09/25 06:10

2点気になることがあります。 1. 一般的にC言語では文字列のコピーはmemcpyではなくstrcpyやstrcpyを利用した方が良いです。 2. memcpyで5byte固定でコピーをしていますが、これはShiftJISの場合にしかなりたたないです。「先香」はShiftJISならば4byteですが、UTF-8では6byteになります。この判定が面倒であればstrcpyを使えばコピー元の文字列全体をコピーしてくれます。より安全な動作をさせるならばstrncpyを使う方が良いですが、まずはstrcpyで確認されてはどうでしょうか?
melian

2025/09/25 06:30

> なぜ5ですとうまくできないのかは、御存知ですか。 「先香」 という文字列の長さは UTF-8 エンコーディングの場合には以下の様に 6 byte になります。(1byteづつ16進数表記) $ printf 先香 | od -tx1 0000000 e5 85 88 e9 a6 99 wide char 文字列をコピーするので wcscpy()/wcscpy_s() を利用するとよいかと思いますが、変更箇所が多くなりますので、ご参考ということで。 strcpy、wcscpy、_mbscpy | Microsoft Learn https://learn.microsoft.com/ja-jp/cpp/c-runtime-library/reference/strcpy-wcscpy-mbscpy strcpy_s、wcscpy_s、_mbscpy_s、_mbscpy_s_l | Microsoft Learn https://learn.microsoft.com/ja-jp/cpp/c-runtime-library/reference/strcpy-s-wcscpy-s-mbscpy-s
todasan

2025/09/25 06:58

toge_ さん ご指摘ありがとうございます。 melian さん 4バイトと終端文字で、勝手に5バイトと思っていました。参考になりました。 ありがとうございます。
guest

回答1

0

自己解決

memcpy((void *)koma_str, dataretu[koma_data].koma, 5);
について、koma_str と dataretu[koma_data].koma の容量は 10 なので全てコピーする。
以下のように修正しました。
memcpy((void *)koma_str, dataretu[koma_data].koma, 10);

投稿2025/09/25 06:08

編集2025/09/25 06:10
todasan

総合スコア81

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.29%

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

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

質問する

関連した質問