luac
luac

Reputation: 41

C++ string matching(hostname and port)

I want to seperate a const char* hostName in the form of "hostName:port" to a const char* hostNameFinal and a number port.

I have currently following code:

const char* hostName = "localhost:643246";

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

The output of the hostNameChar is: localhost:643246 The output of port is a crazy number but not 643246

Sometimes the value of port is too big, which datatype should i use? How can I match the hostName correctly, that I get 2 variables with the needed info?

Upvotes: 4

Views: 6747

Answers (6)

rturrado
rturrado

Reputation: 8064

Another C++ solution (awful compared to the C one :)

#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;
}

Upvotes: 0

Loki Astari
Loki Astari

Reputation: 264391

Try this:

#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);
}

This is because %s scans a word. Words are delimited by whitespace.
The %[<BLA>] matches a string that contains the characters <BLA>. Unless the first character is ^. In which case it matches the string where the characters are not <BLA>.

Upvotes: 2

Adam Bowen
Adam Bowen

Reputation: 11230

Since you have C++ in your question title, I would suggest steering clear of char arrays and using 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?
}

Upvotes: 4

Gareth McCaughan
Gareth McCaughan

Reputation: 19971

sscanf with %s will read up to the next whitespace character; it doesn't know to look for a colon. So, instead: First locate the : in hostName using strchr and only then use sscanf (or, better, something like atoi) to parse the port number. An unsigned int or any sort of long will be long enough for your port number on any platform; an int will be long enough on anything other than a little embedded thing with 16-bit integers (where port numbers with the top bit set will turn into negative numbers, which you probably don't want).

(643246 is not a legal port number; port numbers are only 16 bits. They range from 0 to 65535.)

EDITED to add some actual code in case it isn't clear what I'm suggesting:

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

EDITED again to acknowledge Mark Loeser's correct observation that atoi doesn't do any error checking. To make the above code production-worthy you should (1) check the return value from strchr so as not to fail when there is no colon in the string, (2) check it again so as not to fail when there's a colon but it's further in than 256 characters (or allocate hostNameChar dynamically or something), (3) use strtol rather than atoi, (4) check the return value from strtol to make sure the port number is legal, and (5) check the other kinda-return-value from strtol to make sure there isn't trailing junk after the port number. The code above, however, should give the general idea.

Upvotes: 2

vlg789
vlg789

Reputation: 751

You can use UrlGetPart http://msdn.microsoft.com/en-us/library/bb773781(v=VS.85).aspx

If the buffer was too small, E_POINTER is returned, and the value pointed to by pcchOut will be set to the minimum number of characters that the buffer must be able to contain, including the terminating NULL character.

Upvotes: 0

Javi R
Javi R

Reputation: 2350

Try this:

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

ld = long signed int

However, I think the port number cannot be > 65536

Upvotes: -1

Related Questions