Соответствие строки C ++ (имя хоста и порт) - PullRequest
3 голосов
/ 22 марта 2011

Я хочу разделить const char * hostName в форме "hostName: port" на const char * hostNameFinal и номер порта.

У меня есть следующий код:

const char* hostName = "localhost:643246";

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

Вывод hostNameChar: localhost: 643246 Выход порта - сумасшедшее число, но не 643246

Иногда значение порта слишком велико, какой тип данных мне следует использовать? Как правильно сопоставить hostName, чтобы я получил 2 переменные с необходимой информацией?

Ответы [ 6 ]

4 голосов
/ 22 марта 2011

Поскольку у вас есть C ++ в заголовке вашего вопроса, я бы предложил исключить массивы символов и использовать 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?
}
1 голос
/ 22 марта 2011

Попробуйте:

#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 сканирует слово.Слова разделяются пробелами.
% [] соответствует строке, содержащей символы .Если первый символ не является ^.В этом случае это соответствует строке, где символы не .

1 голос
/ 22 марта 2011

sscanf с %s будет читать до следующего пробела; он не знает, чтобы искать двоеточие. Итак, вместо этого: сначала найдите : в hostName, используя strchr, и только затем используйте sscanf (или, лучше, что-то вроде atoi) для анализа номера порта. unsigned int или любой тип long будет достаточно длинным для вашего номера порта на любой платформе; int будет достаточно длинным для всего, кроме небольшой встроенной вещи с 16-битными целыми числами (где номера портов с установленным верхним битом превратятся в отрицательные числа, которые вы, вероятно, не хотите).

(643246 не является допустимым номером порта; номера портов только 16 бит. Они варьируются от 0 до 65535.)

ИЗМЕНЕНО, чтобы добавить какой-то фактический код на случай, если неясно, что я предлагаю:

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

Снова отредактировал, чтобы подтвердить правильное замечание Марка Лозера о том, что atoi не проверяет ошибки. Чтобы сделать вышеописанный код пригодным для производства, вы должны (1) проверить возвращаемое значение из strchr, чтобы не потерпеть неудачу, когда в строке нет двоеточия, (2) проверить его снова, чтобы не потерпеть неудачу, когда есть двоеточие но он длиннее 256 символов (или динамически или что-то выделяет hostNameChar), (3) используйте strtol вместо atoi, (4) проверьте возвращаемое значение из strtol, чтобы убедиться, что номер порта допустим и (5) проверьте other kinda-return-value из strtol, чтобы убедиться, что после номера порта нет завершающего мусора. Однако приведенный выше код должен дать общее представление.

0 голосов
/ 22 марта 2011

Другое решение 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;
}
0 голосов
/ 22 марта 2011

Вы можете использовать UrlGetPart http://msdn.microsoft.com/en-us/library/bb773781(v=VS.85).aspx

Если буфер был слишком мал, возвращается E_POINTER, и значение, на которое указывает pcchOut, будет установлено равным минимальному количеству символов, которое должен содержать буфер, включая завершающий символ NULL.

0 голосов
/ 22 марта 2011

Попробуйте:

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

ld = длинная подпись int

Однако, я думаю, номер порта не может быть> 65536

...