C言語関係掲示板

過去ログ

No.326.IPアドレスの変換方法

[戻る] [ホームページ]
No.2028

IPアドレスの変換方法
投稿者---takeo(2002/07/09 21:58:48)


こんばんは。

バイナリ表記で表現したIPアドレスを、ドットデシマル表記の文字列に変換する
方法を教えて頂けないでしょうか。


例えば、202.224.197.114(CA.E0.C5.72) のようなIPアドレスであれば、
以下のプログラムの結果として

"IPアドレスは [202.224.197.114]"

と表示されるような関数 change_addr() の作成方法を教えてほしいの
です。

====================================================
char *change_addr(unsigned long ipaddr)
{


}


main()
{
  unsigned long addr = 0xCAE0C572;
  char ip_addr[15];

  ip_addr = change_addr(addr);

  printf("IPアドレスは [%s]", ip_addr);
}
====================================================


どうかよろしくお願いします。

No.2033

Re:IPアドレスの変換方法
投稿者---かずま(2002/07/10 02:58:02)


>  char ip_addr[15];
>
>  ip_addr = change_addr(addr);

"202.224.197.114" は最後につく '\0' を含めて 16バイトです。
ip_addr は配列変数ですが、式の中ではポインタの値に変換されるので、
代入演算子の左辺に置くことは出来ません。

さて、char *change_addr(unsigned long ipaddr) ですが、ポインタを返す場合、
ポインタの指す実体をどこに置くかが非常に問題になります。
このままだと、関数 change_addr の内部で、static な領域を用意しておくか、
あるいは、malloc で動的に確保するかでしょう。
それよりは、char *change_addr(char *str, unsigned long ipaddr) として、
呼び出し元が領域を渡すほうが良いのではないでしょうか。
char *change_addr(char *str, unsigned long ipaddr)
{
    sprintf(str, "%d.%d.%d.%d", p[3], p[2], p[1], p[0]);
    return str;
}
これは、リトルエンディアンの CPU を仮定しています。ビッグエンディアンだと、
3〜0 が逆になります。どちらにも対応できるようにするなら、次のようになります。
char *change_addr(char *s, unsigned long ipaddr)
{
    static long a = 1;
    unsigned char *p = (void *)&ipaddr;
    if (*(char *)&a)
        sprintf(s, "%d.%d.%d.%d", p[3], p[2], p[1], p[0]);
    else
        sprintf(s, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
    return s;
}


No.2036

Re:IPアドレスの変換方法
投稿者---かずま(2002/07/10 04:04:18)


訂正です。unsigned char *p = (unsigned char *)&ipaddr; が抜けていました。

char *change_addr(char *str, unsigned long ipaddr)
{
    unsigned char *p = (unsigned char *)&ipaddr;
    sprintf(str, "%d.%d.%d.%d", p[3], p[2], p[1], p[0]);
    return str;
}


No.2039

Re:IPアドレスの変換方法
投稿者---かずま(2002/07/10 13:12:21)


> これは、リトルエンディアンの CPU を仮定しています。ビッグエンディアンだと、
> 3〜0 が逆になります。どちらにも対応できるようにするなら、次のようになります。

エンディアンに依存しないやり方は、こっちのほうがよいでしょう。
char *change_addr(char *s, unsigned long ipaddr)
{
    sprintf(s, "%d.%d.%d.%d",
        ipaddr>>24, ipaddr>>16 & 0xFF, ipaddr>>8 & 0xFF, ipaddr & 0xFF);
    return s;
}


No.2042

Re:IPアドレスの変換方法
投稿者---takeo(2002/07/10 13:35:13)


この質問を投稿したtakeoです。
かずまさん、回答していただきありがとうございます。大変助かりました。
sprintfを使えばよかったんですね。


あと、差猫さんが言われたマルチポストについてですが、確かに色々な回答が
得られると言う事で、いままでも特に気にせずにしていましたが、各掲示板で
教えていただいた回答を各場所に反映しなかったのは確かによくないですね。

snowさんのご指摘通り、注意事項を読んでいないと言うのもまさにその通りで
自己中心的だったと反省しております。


さっそくですが、質問を投稿した掲示板はここ以外に下の二つです。
http://cgi2.html.ne.jp/~piro/bbs/wforum.cgi
http://www.tachiki.com/cgi-bin/chatc/ealis.cgi

教えていただいた回答(2種類)を添付しておきます。
どちら回答も、かずまさんが指摘していたメモリの確保をちゃんと行っている
ところが大変参考になりました。

今度もよろしくお願いいたします。

-------------------------------------------------------------
[Ryuhne さんのご回答]
char* change_addr(unsigned long addr)
{
  int i;

  char *AddressBuf = (char*)malloc(15);
  unsigned char *pos = (char*)&addr;
  *AddressBuf = 0;

  for(i=0;i<4;i++){
    char tmp[4];
    itoa(*pos, tmp, 10);
    strcat(AddressBuf, tmp);
    pos++;
  }

  return AddressBuf;
}
-------------------------------------------------------------

-------------------------------------------------------------
[Nimda さんのご回答]
// ANSI C準拠
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *change_addr(char*, unsigned long int);

int main(void)
{
 unsigned long int addr = 0xCAE0C572;
 char ip_addr[16];

 printf("%s\n", change_addr(ip_addr, addr));

 return 0;
}

char *change_addr(char *ip_addr, unsigned long int addr)
{
 unsigned long int work;
 char temp[3];
 int i;

 *ip_addr = '\0';

 for (i = 0; i < 4; i++) {
  work = addr;
  work <<= i * 8;
  work >>= 24;
  if (i == 3)
   sprintf(temp, "%d", work);
  else
   sprintf(temp, "%d.", work);
  strcat(ip_addr, temp);
 }

 return ip_addr;
}
-------------------------------------------------------------