🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

解決済

2回答

2551閲覧

ネットワークアドレス構造体を文字列に変換したいです

ht3433

総合スコア19

C

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

0グッド

0クリップ

投稿2019/12/25 05:19

編集2019/12/26 07:30

ネットワークアドレス構造体を文字列に変換したいです。
そして、その変換ができるinet_ntopを自作してみたのですが、2点ほどうまくいかないところがあります。
1つ目は、文字列に変換する際、8ビット毎に数値を文字列に変換し、そのたびに「.」を付け加えたいのですが、やり方が思い浮かびません。
2つ目は、テストパターンです。簡単にではあるのですが、テストパターンを一つ作っています。
ですが、本当は、inet_ntop(const void *src,char *dst, socklen_t cnt)のように引数3つでのテストパターンを作成したいのですが、うまく作成できません。

下記は、inet_ntopのmanページです。
AF_INETの場合を考えます。
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/inet_ntop.3.html

6時間考えても分からなかったので、ご教授していただきたいです。
宜しくお願い致します。

C言語

1#include <stdio.h> 2#include <stdlib.h> 3#include <assert.h> 4#define N 256 5 6int inet_ntop( int src ) { 7 8 // 変数の宣言 9 char s1[N] = {'\0'}; 10 11 // 数値を文字列に変換 12 sprintf( s1, "%d", src ); 13 14 // 変換したものを出力 15 fprintf( stdout, "%s\n", s1 ); 16 17 return( 0 ); 18} 19 20int main(){ 21 22 int result; 23 24 result = inet_ntop( 1300723 ); 25 assert( result == 0 ); 26 27 return( 0 ); 28}

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

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

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

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

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

LouiS0616

2019/12/25 08:30 編集

そもそも数値 1300723 をIPアドレスとして認識するのは人間にも不可能では? 130.0.7.23 とも 130.0.72.3 とも読めます。 仮に 130.0.7.23 を数値として扱いたいなら四つの整数 130, 0, 7, 23 として保持するか、16進表記するのが自然でしょう。少なくとも10進表記しても 1300723 にはなりません。
jimbe

2019/12/25 08:36 編集

inet_ntop を作っているのでしょうか, それとも inet_pton を作っているのでしょうか. ご提示の inte_ntop のドキュメントを参照して何をどうしたいのかが分かりかねます.
ht3433

2019/12/25 08:41

コメントしていただき、ありがとうございます。 inet_ntop を作ろうとしています。 そのために、 inte_ntop のドキュメントを参照しています。 コードでは、分からないなりに作成しただけで、jimbeさんのおっしゃるとおり、ただよくわからない数値を文字列に変換しただけのコードとなっています。 分かりにくくて申し訳ございません。
jimbe

2019/12/25 08:46

既にあるのに, なぜ作ろうとされているのでしょう. そしてなぜコードは inet_pton なのでしょう.
ht3433

2019/12/25 08:52

課題として、inet_ntopを作るというのがありまして、聞ける方が周りにいないので、質問させていただきました。 コードに関しては、すみません、間違っていました。 本当は、inet_ntopです。修正しておきます。
SHOMI

2019/12/25 09:10 編集

>8ビット毎に数値を文字列に変換し、そのたびに「.」を付け加えたいのですが、やり方が思い浮かびません 編集前に張り付けられていたコードの中でやっていますが、何がわからないのでしょうか? もしかして本当にわからないことはポインタのキャストですか?
ht3433

2019/12/25 09:13

>編集前に張り付けられていたコードの中でやっていますが、何がわからないのでしょうか? もしかして下記のコードでしょうか? #include <stdio.h> #include <assert.h> #include <string.h> #include <arpa/inet.h> int inet_pton( const char *src, void *dst ){ // 変数の宣言 int suuti1, suuti2, suuti3, suuti4; char buf[32]; // 共用体の型の定義 union number{ uint32_t number1; uint8_t number2[4]; }; // 共用体変数の宣言 union number No; // srcの文字列を数値に変換し、その数値が4つあるか判定 if ( sscanf( src, "%u.%u.%u.%u", &suuti1, &suuti2, &suuti3, &suuti4 ) != 4 ) { return( 0 ); } // srcの文字列をbufの文字配列に格納 // 格納する際、値の範囲チェックのためuint8_tにキャスト sprintf( buf, "%u.%u.%u.%u", ( uint8_t )suuti1, ( uint8_t )suuti2, ( uint8_t )suuti3, ( uint8_t )suuti4 ); // srcとbufの文字列が異なるか判定 if ( strcmp( src, buf ) ){ return( 0 ); } // srcの数値が格納されている変数を共用体の型のunit8_tの変数に代入 No.number2[0] = suuti1; No.number2[1] = suuti2; No.number2[2] = suuti3; No.number2[3] = suuti4; // unit32_tのメモリをdstにコピー memcpy( dst, &No.number1, 4 ); return( 1 ); } int main(){ int result; struct in_addr in_addr; result = inet_pton( "130.0.7.23", &in_addr ); assert( result == 1 && in_addr.s_addr == ( ( 23 << 24 )|( 7 << 16 )|( 0 << 8 )|130 ) ); result = inet_pton( "130.00.7.23", &in_addr ); assert( result == 0 ); return(0); }
SHOMI

2019/12/25 10:50

sprintfで何をしているかわかりますよね? あとはあなたが貼ったmanページの通り const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); のsrcをstruct in_addrへのポインターとしてキャストしてやればいいだけですよね?
SHOMI

2019/12/25 11:20

周りに聞ける相手がいないとのことですが、課題なら出題者に質問できるのでは?
ht3433

2019/12/26 06:37

コメントしていただき、ありがとうございます。 出題者に質問して、アドバイスをいただき、下記のようなソースコードを作成しました。 私としては、ほぼ解決済みなのですが、なにかご指摘があればお願い致します。 ソースコード #include <stdio.h> #include <string.h> #include <errno.h> #include <arpa/inet.h> #define p ( ( const unsigned char* )src ) const char* inet_ntop( const void* src, char* dst, socklen_t cnt ){ // 変数の宣言 char buf[sizeof "255.255.255.255"]; // srcの数値を文字列に変換 const unsigned n = 1 + sprintf( buf, "%u.%u.%u.%u", p[0], p[1], p[2], p[3] ); // 文字列がdstのサイズを超えているか判定 if ( cnt < n ) { errno = ENOSPC; return( NULL ); // 変換した文字列をdstにコピー }else{ return( ( const char* )memcpy( dst, buf, n ) ); } } int main(){ struct in_addr a; char dst[256]; a.s_addr = inet_addr( "130.0.7.23" ); if ( inet_ntop( &a, dst, sizeof dst ) ) { printf( "%s\n", dst ); return( 0 ); }else{ return( 1 ); } }
SHOMI

2019/12/26 07:45

特に問題ないと思いますよ。 manページ参照しているのでlinuxだったのですね。 すみません、それだとin_addrの中身はuint32_tですね。VCだと共用体になっていて1バイト毎にもアクセスできるのでそのつもりで書いていました。
ht3433

2019/12/26 07:49

コメントしていただき、ありがとうございます。 そうだったんですね。こちらも環境をお伝えしていなくてすみませんでした。
guest

回答2

0

自己解決

C言語

1#include <stdio.h> 2#include <string.h> 3#include <errno.h> 4#include <arpa/inet.h> 5#define p ( ( const unsigned char* )src ) 6 7const char* inet_ntop( const void* src, char* dst, socklen_t cnt ){ 8 9// 変数の宣言 10char buf[sizeof "255.255.255.255"]; 11 12// srcの数値を文字列に変換 13const unsigned n = 1 + sprintf( buf, "%u.%u.%u.%u", p[0], p[1], p[2], p[3] ); 14 15// 文字列がdstのサイズを超えているか判定 16if ( cnt < n ) { 17errno = ENOSPC; 18return( NULL ); 19 20// 変換した文字列をdstにコピー 21}else{ 22 23return( ( const char* )memcpy( dst, buf, n ) ); 24} 25} 26 27int main(){ 28struct in_addr a; 29char dst[256]; 30 31a.s_addr = inet_addr( "130.0.7.23" ); 32 33if ( inet_ntop( &a, dst, sizeof dst ) ) { 34printf( "%s\n", dst ); 35return( 0 ); 36}else{ 37return( 1 ); 38} 39}

投稿2019/12/26 07:51

ht3433

総合スコア19

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

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

rubato6809

2019/12/27 14:54 編集

ちゃくちゃくと解決済みにしてるけど、なんか、この人もあぶなっかしいなあ(苦笑)。 1. char dst[256]; のサイズは 256。 inet_ntop( &a, dst, sizeof dst ) は inet_ntop(&a, dst, 256); となって if ( cnt < n ) { という条件は決して成り立たない。だから その inet_ntop() がNULLを返すことは無い、ということは理解できているかな? 2. せっかくプログラムコードをmarkdown記法で貼り付けているんだからインデントをつけようよ。 3. 念の為に確認するけど、inet_addr() は標準の関数を使っているんですよね?
guest

0

以下のようにしてください。

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <assert.h> 4#define N 256 5 6int inet_ntop( int src ) { 7 8 // 変数の宣言 9 char s1[N]; 10 int p1,p2,p3,p4; 11 p1 = src & 0xFF; 12 p2 = (src >> 8) & 0xFF; 13 p3 = (src >> 16) & 0xFF; 14 p4 = (src >> 24) & 0xFF; 15 16 // 数値を文字列に変換 17 sprintf( s1, "%d.%d.%d.%d", p1,p2,p3,p4 ); 18 19 // 変換したものを出力 20 fprintf( stdout, "%s\n", s1 ); 21 22 return( 0 ); 23} 24 25int main(){ 26 27 int result; 28 29 result = inet_ntop( 1300723 ); 30 assert( result == 0 ); 31 32 return( 0 ); 33}

投稿2019/12/26 06:13

tatsu99

総合スコア5493

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

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

tatsu99

2019/12/26 07:50

うーむ。そうなんですか・・・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問