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

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

新規登録して質問してみよう
ただいま回答率
85.51%
C++

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

Q&A

解決済

2回答

4039閲覧

int型をchar型に変換するには

Asahi_1115

総合スコア13

C++

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

0グッド

0クリップ

投稿2017/08/02 13:39

編集2017/08/02 13:43

一対一通信で1~10の乱数の中から一つのはずれを引くと通信を終了する爆弾ゲームのようなものを作ってるのですが、
実行結果でクライアントから受信した数字が正しく表示されません。1~10の数字を選んでも爆発が起こりません。

char型とint型の比較をするためにwhile ((int)buf != s);という形にしたのですがここに問題があると思われます。
int s;
char c = s + '0';
でint型の数値をchar型の数字に変換する方法があったのですが、この方法は0~9までしか変換できないようです。

どのように書き直せば完成に近づけるでしょうか
教えてもらえるとありがたいです。

[サーバ]
クライアントからの接続待ち
数字を選んでください...1
相手が選んでいます...。
相手の選んだ数字→3733856
数字を選んでください...3
相手が選んでいます...。
相手の選んだ数字→3733856
数字を選んでください...

[クライアント]
相手が選んでいます...。
相手の選んだ数字→ 1

数字を選んでください...2
相手が選んでいます...。
相手の選んだ数字→ 3

数字を選んでください...4
相手が選んでいます...。

サーバ側

#include <stdio.h> #include <io.h>//基本入出力関数 #include <winsock2.h> #include<stdlib.h>//乱数 #include<time.h>//乱数 #define BUF_LEN 100//入出力バッファサイズ int main() { WSADATA wsaData; SOCKET sock0; struct sockaddr_in addr; struct sockaddr_in client; int len; SOCKET sock; char buf[BUF_LEN];//入出力バッファ // winsock2の初期化 WSAStartup(MAKEWORD(2, 0), &wsaData); // ソケットの作成 sock0 = socket(AF_INET, SOCK_STREAM, 0); // ソケットの設定(アドレス構造体の設定) addr.sin_family = AF_INET;//インターネットを使用する addr.sin_port = htons(12345);//サーバ(自分自身)のポート番号 addr.sin_addr.S_un.S_addr = INADDR_ANY;//IPアドレスすべての値指定 //ソケットのディスクリプタとアドエス構造体を結びつける bind(sock0, (struct sockaddr *)&addr, sizeof(addr)); // TCPクライアントからの接続要求を待てる状態にする(待ちクライアント数指定) listen(sock0, 5); // TCPクライアントからの接続要求を受け付ける printf("クライアントからの接続待ち\n"); len = sizeof(client); sock = accept(sock0, (struct sockaddr *)&client, &len); int s; srand(time(NULL)); //1~10のランダムな数 s = rand()%10+1; //1~10のランダムな数 //送受信処理 do{ printf("数字を選んでください..."); memset(buf, 0, sizeof(buf));//送受信バッファ0クリア _read(0, buf, sizeof(buf));//キーボードから入力 send(sock, buf, sizeof(buf), 0);//送信 printf("相手が選んでいます...。"); memset(buf, 0, sizeof(buf)); recv(sock, buf, sizeof(buf), 0);//受信 printf("相手の選んだ数字→%s",buf); } while ((int)buf != s); printf("爆発しました\n"); // TCPセッションの終了 closesocket(sock); // winsock2の終了処理 WSACleanup(); return 0; }

クライアント側

#define _WINSOCK_DEPRECATED_NO_WARNINGS #include <stdio.h> #include <io.h>//基本入出力関数 #include <winsock2.h> #define BUF_LEN 100//入出力バッファサイズ int main() { WSADATA wsaData; struct sockaddr_in server; SOCKET sock; char buf[BUF_LEN];//入出力バッファ // winsock2の初期化 WSAStartup(MAKEWORD(2, 0), &wsaData); // ソケットの作成 sock = socket(AF_INET, SOCK_STREAM, 0); // 接続先指定用アドレス構造体の準備 server.sin_family = AF_INET;//インターネット使用 server.sin_port = htons(12345);//接続先ポート番号 server.sin_addr.S_un.S_addr = inet_addr("*.*.*.*");//接続先IPアドレス // サーバに接続 connect(sock, (struct sockaddr *)&server, sizeof(server)); //受信送信処理 int n = 1; do { memset(buf, 0, sizeof(buf));//送受信バッファ0クリア printf("相手が選んでいます...。"); recv(sock, buf, sizeof(buf), 0);//受信 printf("相手の選んだ数字→ %s\n",buf); printf("数字を選んでください..."); memset(buf, 0, sizeof(buf));//送受信バッファ0クリア _read(0, buf, sizeof(buf));//キーボードから入力 send(sock, buf, sizeof(buf), 0);//送信 } while (n = 1); printf("爆発しました\n"); // TCPセッションの終了 closesocket(sock); // winsock2の終了処理 WSACleanup(); return 0; }

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

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

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

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

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

WoodenHamlet

2017/08/02 23:45

この質問とは直接関係ないからこっちに書くけど、クライアント側のDo-while文の判定式、while(n=1)としているけど、(n=1)の値は常に1…真になるので無限ループに陥ってますよ
guest

回答2

0

まず、C言語で文字列は文字型の配列として扱われ、配列どうしの比較演算は定義されていない事(つまり、文字列同士の比較は==や!=では行えないという事)を念頭に置いて、この後の話を読んでいだたきたいと思います。
まず、(int)bufを

C

1printf("%d\n",(int)buf);

のようにして書き出してみてください。
恐らく適当な値(数十万程度)が出力されると思います。
それをsと比較すると、絶対に一致するはずのないことがわかります。
これは、bufはbuf配列の先頭アドレスを示しており、(int)bufはそのアドレスをint型にキャストしたものになってしまうからです。
ですので、まずはbuf配列の中身を数字として書き出す必要があります。
C++を使っているのであれば数ステップで変換できるのですが、C言語だと些か面倒ですので、範囲を1-10に限定したコードを例示します。

C

1const int ABNORMAL -1; 2int buf_i; 3if(strlen(buf)==1){ 4 buf_i = buf[0]-'0'; 5} 6else if(buf[0]==1 && buf[1]==0){ 7 buf_i = 10; 8} 9else{ 10 buf_i = ABNORMAL; 11}

このコードの後に、

C

1if(buf_i != ABNORMAL){ 2 //処理 3}

などを使って10以外の数値が入力された場合の処理をかけばいいとおもいます。
質問者様の意図に沿った回答ができているか不安ですので、わからない場合は返信していただければお答えいたします。

投稿2017/08/02 14:50

編集2017/08/02 14:55
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2017/08/02 14:53 編集

あー…… atoi使えばよかったですね。 atoiはSTLの関数だと勘違いしておりました。 失礼いたしました。
Asahi_1115

2017/08/03 10:42

丁寧なご助言ありがとうございます!
guest

0

ベストアンサー

C言語で文字列を数値にするには atoi を使います。

c

1while (atoi(buf) != s);

ただし気を付けないといけないのは atoi は例えば数字でない物を入力した場合でも 0 になってしまいます。つまり本当に 0 を入力したのか abc を入力したのか分からないという事です。

これを解決するには strtol という関数を使います。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5int 6main(int argc, char* argv[]) { 7 int n; 8 char *err = NULL; 9 char buf[20]; 10 11 strcpy(buf, "1s"); // サンプルの入力 12 13 n = strtol(buf, &err, 10); 14 if (err != NULL) { 15 printf("入力エラーです。エラーの位置は: %s\n", err); 16 } else { 17 printf("入力した数値は %ld です\n", n); 18 } 19 return 0; 20}

投稿2017/08/02 14:28

編集2017/08/02 14:54
mattn

総合スコア5030

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

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

Asahi_1115

2017/08/03 10:40

ありがとうございます! おかげで遂に完成しました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問