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

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

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

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

Q&A

1回答

728閲覧

TCP型サーバのプログラムでstrtokとsprintfを使い計算結果の文字列をクライアントに返す方法が分かりません

mercury

総合スコア11

C

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

0グッド

0クリップ

投稿2019/05/18 03:16

編集2019/05/18 03:19

strtokとsprintfを使いTCP型クライアントから入力された「add,30,10」等(四則演算)の文字列をサーバで受け取り計算しクライアントに返すという問題で、strtokを使いこの文字列を3つに区切り、sprintfで計算結果の文字列をStrBufに入れてクライアントに返すやり方が分かりません。自分でやりましたが、そもそもstrtokの処理をしていないようなのでどうすれば良いか分かりません。
入力された文字列をそのまま返し、「.」が来たら終了する。ということまではできていました。
サーバ側のプログラムだけ変更する問題ですがクライアント側も載せておきます。
↓サーバのプログラム

c

1#include <winsock.h> //Windows用ソケットライブラリ用 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5#include <ctype.h> 6 7#pragma comment(lib,"wsock32.lib") //WinSockライブラリをリンク 8 9#define MAX_BUFF_12A 1024 //通信用バッファのバイト数 10 11int ServerPort = 10010; // サーバーのポート番号 12 13 14// 15//  メイン関数 16// 17int main( void ) 18{ 19 char StrBuf[128],Str[100],tmp[100] ; 20 int rVal; 21 int a, b, res,i; 22 char *word[5] 23 SOCKADDR_IN local, from; 24 WSADATA wsaData ; 25 SOCKET listen_socket; //Listen用ソケット 26 SOCKET DataSocket; //送受信用ソケット 27 WORD wVersionRequested ; 28 int fromlen = sizeof( from ) ; 29 30 31 printf("サーバ起動時のポート番号(1024以上):"); scanf("%d", &ServerPort); 32 33 34 35 // ソケットの初期化(ウィンドウズ用Winsockの初期化) 36 wVersionRequested = MAKEWORD( 1, 1 ); 37 rVal = WSAStartup( wVersionRequested, &wsaData ); 38 if(rVal != 0 ) { //初期化のエラー 39 printf("エラー:ソケット初期化・・・終了します\n"); 40 WSACleanup(); 41 return(-1); 42 } 43 44 // ソケット生成用のSOCKADDR_IN構造体の設定 45 local.sin_family = AF_INET ; 46 local.sin_addr.s_addr = INADDR_ANY ; 47 local.sin_port = htons( (unsigned short)ServerPort ); 48 49 50 listen_socket = socket( AF_INET, SOCK_STREAM, 0 ) ; 51 if( listen_socket == INVALID_SOCKET ) { 52 printf("エラー:ソケット生成・・・終了します\n"); 53 WSACleanup(); 54 return(-1); 55 } 56 57 // 生成したソケットにバインド 58 if( bind( listen_socket, (struct sockaddr*)&local, sizeof(local) ) 59 == SOCKET_ERROR) { 60 printf("エラー:バインドbind・・・終了します\n"); 61 WSACleanup(); 62 return(-1); 63 } 64 printf("******サーバの起動*****\n"); 65 66 // Listen(クライアントからの接続待ち) 67 listen( listen_socket, 5 ); 68 printf("ポート番号%dをlistning中(接続待ち)...", ServerPort ); 69 70 // accept(クライアントからの接続要求OK) 71 DataSocket = accept( listen_socket, (struct sockaddr*)&from, &fromlen ); 72 printf("\nサーバ=%s, ポート番号=%dに接続.\n\n", 73 inet_ntoa(from.sin_addr), htons(from.sin_port) ) ; 74 75 76 77 /******** データの受信 ********/ 78 while (1) { 79 rVal = recv(DataSocket, StrBuf, sizeof(StrBuf), 0); 80 StrBuf[rVal] = '\0'; //受信したデータ(文字列)の最後にNULL文字付加 81 82 if (rVal == SOCKET_ERROR || rVal == 0) { //受信時エラー(または切断) 83 printf("エラー:相手からの切断されました\n・・・終了します\n"); 84 break; // ←← 問題A2以降はコメントを外す 85 } 86 for (i = 0;i < 3;i++) { //ここから 87 if (i == 0) { 88 word[i] = strtok(StrBuf, ","); 89 } 90 else { 91 word[i] = strtok(NULL, ","); 92 } 93 if (word[i] == NULL) 94 break; 95 }                  //ここまで自分で追加した場所です 96 97 if (StrBuf == '.') 98 break; 99 100 101 102 103 /******** 受信したデータ(文字列)をホスト画面に表示 *********/ 104 105 if (i == 3) { //ここから 106 if (strcmp(word[0], "add") == 0) { 107 a = atoi(word[1]); 108 b = atoi(word[2]); 109 res = a + b; 110 sprintf(StrBuf, "%d+%d=%d\n", a, b, res); 111 } 112 else { 113 sprintf(StrBuf, "[%s %s %s]の計算はできません", word[0], word[1], word[2]); 114 } 115 } 116 else { 117 sprintf(StrBuf, "[%s]数式ではありません\n", StrBuf); 118 }                       //ここまで自分で追加した場所です 119 120 121 /******** 文字列の送信 *********/ 122 send(DataSocket, StrBuf, (int)strlen(StrBuf), 0); 123 124 } 125 126 127 // ソケット終了処理 128 closesocket( DataSocket ); //ソケットのクローズ 129 WSACleanup(); //ソケットの破棄 130 131 printf("\n\nEnterキーを1,2回押してプログラム終了"); 132 getchar(); //プログラム一時停止(キー入力待ち) 133 getchar(); //プログラム一時停止(キー入力待ち) 134 135 return(0); 136} 137

↓クライアント側のプログラム

c

1#include <winsock.h> //Windows用ソケットライブラリ用 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5#include <ctype.h> 6 7#pragma comment(lib,"wsock32.lib") //WinSockライブラリをリンク 8 9#define MAX_BUFF_12A 1024 // バッファの長さ 10 11int NetPortNo = 10010; 12char HostAddr[50] = "127.0.0.1"; 13 14// 15// main 16// 17int main( void ) 18{ 19 char StrBuf[MAX_BUFF_12A+1] ; 20 char szHost[MAX_BUFF_12A+1]; 21 SOCKET DataSocket; 22 WSADATA wsaData; 23 SOCKADDR_IN server; 24 HOSTENT *hostEnt; 25 int rVal; 26 WORD wVersionRequested; 27 unsigned int addr; 28 29 // ソケットの初期化(ウィンドウズ用Winsockの初期化) 30 wVersionRequested = MAKEWORD( 1, 1 ); 31 rVal = WSAStartup( wVersionRequested, &wsaData ); //初期化の関数 32 if(rVal != 0 ) { //初期化のエラー 33 printf("エラー:ソケット初期化・・・終了します\n"); 34 WSACleanup(); 35 return(-1); 36 } 37 38 // ソケット生成(TCPソケット) 39 DataSocket = socket( AF_INET, SOCK_STREAM, 0 ) ; // ソケット生成の関数 40 41 if( DataSocket < 0 ) { printf("エラー:ソケット生成・・・終了します\n"); return(-1);} 42 43 44 printf("サーバのホスト名(またはIPアドレス):"); scanf("%s",HostAddr); 45 printf("サーバのポート番号:"); scanf("%d",&NetPortNo); 46 47 48 49 // サーバ情報の取得 50 strcpy( szHost, HostAddr ); 51 if( isalpha( szHost[0] ) ) { // 名前の場合 52 hostEnt = gethostbyname( szHost ); //DNSへ問合せ 53 } 54 else { // IPアドレスの場合 55 addr = inet_addr( szHost ); 56 hostEnt = gethostbyaddr( (char*)&addr, 4, AF_INET ); 57 } 58 if( hostEnt == NULL ) { printf("エラー:アドレスを解決不能[%s]\n・・終了!\n", szHost);return(-1); } 59 60 printf("******クライアントの起動*****\n"); 61 // サーバ接続のための初期化 62 memset( &server, 0, sizeof(server) ); 63 memcpy( &(server.sin_addr), hostEnt->h_addr, hostEnt->h_length ); 64 65 server.sin_family = hostEnt->h_addrtype; 66 server.sin_addr.s_addr = *(( unsigned long*)hostEnt->h_addr ); //サーバアドレス 67 68 server.sin_port = htons( (unsigned short)NetPortNo ); 69 70 // サーバへ接続を試みる(connect関数) 71 printf("サーバ[%s]へ接続中...", szHost ) ; 72 if( connect( DataSocket,(struct sockaddr*)&server, sizeof(server) ) 73 == SOCKET_ERROR) { 74 printf("エラー:サーバへの接続(connect)\n・・・終了します\n"); return(-1); } 75 76 printf("%sに接続完了しました\n", szHost ); 77 78 79 80 /******** 文字列のキーボードからの読込み *********/ 81 while (1) { 82 printf("文字列を入力:"); 83 scanf("%s", StrBuf); 84 getchar(); 85 86 /******** 文字列の送信 *********/ 87 send(DataSocket, StrBuf, (int)strlen(StrBuf), 0); //送信(send関数) 88 if (StrBuf[0] == '.') 89 break; 90 /******** データの受信 ********/ 91 rVal = recv(DataSocket, StrBuf, sizeof(StrBuf), 0); //受信(recv関数) 92 StrBuf[rVal] = '\0'; //受信したデータ(文字列)の最後にNULL文字付加 93 94 if (rVal == SOCKET_ERROR || rVal == 0) { //受信時エラー(または切断) 95 printf("エラー:相手からの切断されました\n・・・終了します\n"); 96 break; // ←← 問題A2以降はコメントを外す 97 } 98 99 // メッセージを表示する 100 printf("受信文字列:%s\n", StrBuf); 101 } 102 103 104 105 // ソケット終了処理 106 closesocket( DataSocket ); //ソケットのクローズ 107 WSACleanup(); //ソケットの破棄 108 109 printf("\n\nEnterキーを1,2回押してプログラム終了"); 110 getchar(); //プログラム一時停止(キー入力待ち) 111 getchar(); //プログラム一時停止(キー入力待ち) 112 113 return(0); 114} 115

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

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

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

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

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

guest

回答1

0

C

1#include <stdio.h> 2#include <string.h> 3 4void calc(char* in, char* out) { 5 char* command = strtok(in,","); 6 char* op1 = strtok(NULL,","); 7 char* op2 = strtok(NULL,","); 8 /* ひとまず add のみ */ 9 if ( strcmp(command, "add") == 0 ) { 10 sprintf(out,"%d", atoi(op1) + atoi(op2)); 11 } 12 return; 13} 14 15/* おためしに "add,30,10" をcalcに食わす。"40"が返って来ればok */ 16int main() { 17 char in[] = "add,30,10"; 18 char out[30]; 19 calc(in, out); 20 puts(out); 21 return 0; 22}

投稿2019/05/18 03:38

episteme

総合スコア16614

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問