4

我想将“hostName:port”形式的 const char* hostName 与 const char* hostNameFinal 和数字端口分开。

我目前有以下代码:

const char* hostName = "localhost:643246";

long int port;
char hostNameChar[256];
sscanf(hostName, "%s:%d", hostNameChar, &port);

hostNameChar 的输出是:localhost:643246 port 的输出是一个疯狂的数字但不是 643246

有时端口的值太大,我应该使用哪种数据类型?如何正确匹配主机名,获得 2 个带有所需信息的变量?

4

6 回答 6

4

由于您的问题标题中有 C++,因此我建议您避开 char 数组并使用 std::string。

#include <string>
#include <sstream>

std::string hostName = "localhost:643246";

size_t colonPos = hostName.find(':');

if(colonPos != std::string::npos)
{
     std::string hostPart = hostName.substr(0,colonPos);
     std::string portPart = hostName.substr(colonPos+1);

     std::stringstream parser(portPart);

     int port = 0;
     if( parser >> port )
     {
          // hostname in hostPart, port in port
          // could check port >= 0 and port < 65536 here
     }
     else
     {
         // port not convertible to an integer
     }
}
else
{
    // Missing port?
}
于 2011-03-22T17:24:58.947 回答
2

sscanfwith%s将读取到下一个空白字符;它不知道寻找冒号。所以,相反:首先找到:in hostNameusing strchr,然后才使用sscanf(或者,更好的是,类似的东西atoi)来解析端口号。在任何平台上,一个unsigned int或任何类型的long端口号都足够长;int除了具有 16 位整数的小嵌入式事物(其中设置了最高位的端口号将变为负数,您可能不想要)之外,an将足够长。

(643246 不是合法的端口号;端口号只有 16 位。它们的范围从 0 到 65535。)

编辑添加一些实际代码,以防我不清楚我的建议:

const char * colon = strchr(hostName, ':');
memcpy(hostNameChar, hostName, colon-hostName);
hostNameChar[colon-hostName];
port = atoi(colon+1);

再次编辑以承认 Mark Loeseratoi没有进行任何错误检查的正确观察。为了使上述代码具有生产价值,您应该(1)检查返回值,strchr以免在字符串中没有冒号时失败,(2)再次检查,以免在有冒号时失败,但它更进一步超过 256 个字符(或hostNameChar动态分配或其他),(3)使用strtol而不是atoi,(4)检查返回值strtol以确保端口号是合法的,以及(5)检查另一个返回值 from strtolto确保端口号后面没有尾随垃圾。然而,上面的代码应该给出一般的想法。

于 2011-03-22T17:15:14.277 回答
1

尝试这个:

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

int main()
{
    const char* hostName = "localhost:643246";

    long int port;
    char hostNameChar[256];
    if (sscanf(hostName, "%[^:]:%d", hostNameChar, &port) != 2)
    {
        // It did not work.
        // scanf() returns the number of matched tokens.
        fprintf(stdout, "Fail\n");
        exit(1);
    }
    fprintf(stdout, "Host(%s) Port(%d)\n", hostNameChar, port);
}

这是因为 %s 扫描了一个单词。单词由空格分隔。
%[<BLA>] 匹配包含字符 <BLA> 的字符串。除非第一个字符是 ^。在这种情况下,它匹配字符不是 <BLA> 的字符串。

于 2011-03-22T17:25:22.147 回答
0

另一种 C++ 解决方案(与 C 相比很糟糕 :)

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main()
{
  const char* hostName = "localhost:643246";
  long int port;
  char hostNameChar[256];

  istringstream iss(hostName);
  string hostNameString;
  getline(iss, hostNameString, ':');
  strcpy(hostNameChar, hostNameString.c_str());
  iss >> port;
  cout << hostNameChar << "-" << port << endl;
}
于 2011-03-22T17:41:44.060 回答
0

您可以使用 UrlGetPart http://msdn.microsoft.com/en-us/library/bb773781(v=VS.85).aspx

如果缓冲区太小,则返回 E_POINTER,并将 pcchOut 指向的值设置为缓冲区必须能够包含的最小字符数,包括终止 NULL 字符。

于 2011-03-22T17:23:28.970 回答
-1

尝试这个:

sscanf(hostName, "%s:%ld", hostNameChar, &port);

ld = 长符号整数

但是,我认为端口号不能> 65536

于 2011-03-22T17:15:07.757 回答