C++将Uint32 IP地址转换为文本x.x.x.x

6

我想将一个Uint32 IP地址转换为串联的字符串。

在此过程中,我得到了uint8数据,但我需要将其更改为const char*以便能够将其连接到IP的其他部分,以便在一个变量中打印完整的IP。

我该如何将uint8更改为const char*?或者是否有更好的转换方法?

uint32 ipAddress = GetHostIp();
if (ipAddress)
 {
    const int NBYTES = 4;
        uint8 octet[NBYTES];
        int x;
        char *ipAddressFinal;
        for (x = 0; x < NBYTES; x++)
        {
             octet[x] = (ipAddress >> (x * 8)) & (uint8)-1;
        }
        for (x = NBYTES - 1; x >= 0; --x)
        {
            if (NBYTES==4)
                        {
                            const char *IPPart = octet[x]; // HERE IS THE BUG!!!!! ?
                strcpy(ipAddressFinal, IPPart);
                        }
            else
                        {
                            const char *IPPart = octet[x];  // HERE IS THE BUG!!!!! ?
                strcat(ipAddressFinal, IPPart);
                        }
            if (x > 0)
                strcat(ipAddressFinal, ".");
        }
     LogAlways("IP:   %s", ipAddressFinal);
 }

编辑

谢谢大家 - 问题已解决!感谢所有人!在短时间内得到非常好的答案真是太棒了!特别感谢Lacrymology!!!这里是现在正在运行的代码,我没有使用Linux,应该把我的操作系统等信息写下来...

if (ipAddress)
{
    const int NBYTES = 4;
    uint8 octet[NBYTES];
    char ipAddressFinal[16];
    for(int i = 0 ; i < NBYTES ; i++)
    {
        octet[i] = ipAddress >> (i * 8);
    }
    sprintf(ipAddressFinal, "%d.%d.%d.%d", octet[3], octet[2], octet[1], octet[0]);
    LogAlways("IP:   \"%s\"", ipAddressFinal);
}

2
请格式化您的代码 - 它无法读取 - ssmir
我认为你还有一些关于C++字符串和指针的知识需要学习。 - Mark Ransom
提醒一下,你的工作代码存在一个 bug。你的 ipAddressFinal[] 只分配了 15 个字节,但是考虑到空终止符,它应该有 16 个字节。每个字段最多有 3 个字符,所以 3 + 1 + 3 + 1 + 3 + 1 + 3 + 1 = 16。我已经修改了它,以便复制和粘贴的人不会传播这个错误。 - Mark Lakata
6个回答

9

我猜你正在使用Linux - gethostip() 似乎出现在Linux手册页中。无论如何,如果是这种情况,那么使用 inet_ntoa() 怎么样?

sprintf(ip_src, "%s", inet_ntoa(ipdata->ip_src));

假设char* ip_src有足够的空间来存储IP地址。旨在将struct in_addr转换为char*
包含方式:#include <arpa/inet.h>

这些函数已被弃用,因为它们无法处理IPv6!请改用inet_ntop()或inet_pton()!它们仍然包含在此处,因为它们仍然可以在某些情况下使用。 - sehe

6
如何只是简单地
uint32 ipAddress = GetHostIp();
if (ipAddress) {
    char ipAddr[16];
    snprintf(ipAddr,sizeof ipAddr,"%u.%u.%u.%u" ,(ipAddress & 0xff000000) >> 24 
                                                ,(ipAddress & 0x00ff0000) >> 16
                                                ,(ipAddress & 0x0000ff00) >> 8
                                                ,(ipAddress & 0x000000ff));
    // depending on the byte order your GetHostIp() returns the IP address in
    // you might need to reverse the above (i.e. print (ipAddress &0x000000ff)) first.
    LogAlways("IP:   %s", ipAddr);
}

你也可以使用 inet_ntoa 或者 getnameinfo 来将IP地址转换为字符串。


减一:这段代码不具备可移植性,因为我必须改变字节序。加一:感谢您提供的代码 :) - Zac
如果它不可移植,那是因为你的GetHostIp()函数没有做好处理,导致它以小端格式而非大端格式返回IP地址 :) - nos

4

这里是一个实际的C++解决方案

  #include <arpa/inet.h>

  std::string GetIPString(uint32_t x) const
  {
      char buffer[INET_ADDRSTRLEN + 1];
      auto result = inet_ntop(AF_INET, &x, buffer, sizeof(buffer));
      if (result == nullptr) throw std::runtime_error("Can't convert IP4 address");
      return buffer;
  }

2

首先,你标记为“HERE IS THE BUG”的那一行应该是类似于sprintf("%d", octet[x]);但我将给出我认为更好的解决方案(并不是最好的方案)

uint32 ipAddress = GetHostIp();
if (ipAddress)
{
    const int NBYTES = 4;
    uint8 octet[NBYTES];
    int x;
    char *ipAddressFinal[16];
    for(int i = 0 ; i < NBYTES ; i++)
    {
        octet[i] = ipAddress >> (i * 8);
    }
    sprintf("%d.%d.%d.%d", octet[0], octet[1], octet[2], octet[3]);
}

现在,这段代码是“错误”的,因为我假设一个IP地址有4个字节,但它可以完成任务。同样地,你也可以改变那个for循环:

if (ipAddress)
{
   union {
       uint32 raw;
       uint8 octet[4];
   } ip;
   ip.raw = ipAddress;
   sprintf("%d.%d.%d.%d", ipAddressFinal, ip.octet[0], ip.octet[1],
                                          ip.octet[2], ip.octet[3]);
}

如果您不想假定有4,那么您必须坚持第一种方法,做类似于以下操作:

sprintf("%s.%d", ipAddressFinal, , ipAddressFinal, ip.octet[i]);

我不知道这是否有效,因为它具有相同的字符串输入和输出。


@Ninefingers所说的甚至更好XD - Lacrymology

1

-1

感谢各位 - 问题已解决!感谢大家!能在短时间内得到非常好的答案真是太棒了!特别感谢Lacrymology!!!这里是可工作的代码,我不使用Linux,应该写下我的操作系统等信息...

if (ipAddress) { const int NBYTES = 4; uint8 octet[NBYTES]; char ipAddressFinal[15]; for(int i = 0 ; i < NBYTES ; i++) { octet[i] = ipAddress >> (i * 8); } sprintf(ipAddressFinal, "%d.%d.%d.%d", octet[3], octet[2], octet[1], octet[0]); LogAlways("IP: \"%s\"", ipAddressFinal); }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接