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

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

ただいまの
回答率

90.04%

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,120

Asahi_1115

score 11

一対一通信で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;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • WoodenHamlet

    2017/08/03 08:45

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

    キャンセル

回答 2

checkベストアンサー

0

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

while (atoi(buf) != s);

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

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
main(int argc, char* argv[]) {
  int n;
  char *err = NULL;
  char buf[20];

  strcpy(buf, "1s"); // サンプルの入力

  n = strtol(buf, &err, 10);
  if (err != NULL) {
    printf("入力エラーです。エラーの位置は: %s\n", err);
  } else {
    printf("入力した数値は %ld です\n", n); 
  }
  return 0;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/03 19:40

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

    キャンセル

0

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

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


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

const int ABNORMAL -1;
int buf_i;
if(strlen(buf)==1){
  buf_i = buf[0]-'0';
}
else if(buf[0]==1 && buf[1]==0){
  buf_i = 10;
}
else{
  buf_i = ABNORMAL;
}

このコードの後に、

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


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/02 23:52 編集

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

    キャンセル

  • 2017/08/03 19:42

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

    キャンセル

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

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る