tags:

views:

80

answers:

2

I am new to C89, and don't really understand how strings work. I am developing on Windows 7.

Here is what I am trying to do, in Java:

String hostname = url.substring(7, url.indexOf('/'));

Here is my clumsy attempt to do this in C89:

// well formed url ensured
void get(char *url) {
    int hostnameLength;
    char *firstSlash;
    char *hostname;

    firstSlash = strchr(url + 7, '/');
    hostnameLength = strlen(url) - strlen(firstSlash) - 7;
    hostname = malloc(sizeof(*hostname) * (hostnameLength + 1));
    strncpy(hostname, url + 7, hostnameLength);
    hostname[hostnameLength] = 0; // null terminate
}

Update to reflect answers

For a hostnameLength of 14, hostname is malloc()'d 31 characters. Why does this happen?

+2  A: 

// now what? is strncpy():

hostname = malloc(hostnameLength + 1);
strncpy(hostname, url + 7, hostnameLength);
hostname[hostnameLength] = '\0'; // don't forget to null terminate!
Carl Norum
I'd use `memcpy` personally. It's harder to mess up and it doesn't do anything unexpected. But the OP's code _does_ need to check the return value of `strchr`, which no one has mentioned yet.
Chris Lutz
@Chris, that depends on whether or not he has guaranteed a well-formed URL elsewhere in the code.
Carl Norum
Do I want to use your `malloc()`, or the `malloc()` described in Reed's answer? Isn't yours too small?
Rosarch
@Rosarch, aren't they exactly the same?
Carl Norum
A: 

After that, you need to do:

hostname = malloc(sizeof(char) * (hostnameLength+1));
strncpy(hostname,  url + 7, hostnameLength);
hostname[hostnameLength] = 0;

See strncpy for details on the copying. It does require your destination pointer to be allocated in advance (hence the malloc), and will only copy so many characters...

Reed Copsey
Can you explain the significance of `hostname[hostnameLength] = 0;` ?
Rosarch
Yes - you need to null terminate the hostname - strncpy will copy "hostnameLength" characters, but it won't add the null termination character. Adding the 0 (or '\0') will terminate the string correctly.
Reed Copsey
C strings require a null byte on the end, and that covers the case where the string you're copying doesn't fit in the buffer, so strncpy didn't put the null on. If you don't do this, some string operation later is going to run off into random memory, and the program could do all sorts of strange things (although, admittedly, it will probably just crash with a segmentation fault).
Andrew McGregor
`sizeof(char)` is `1`. There's no reason to have that in there.
Carl Norum
Strings in C are null terminated (\0) - if you manually construct new strings from characters and string fragments, you may have to manually add the string terminator, or your regular string manipulation functions will happily wander off into unallocated memory
Michael Mullany
I agree with @Carl with the caveat that a `sizeof` might be acceptable here, but not as `sizeof(char)`. `sizeof(type)` creates another place where maintainers must change code if types change (say, `char` to `wchar_t`). `sizeof *hostname` adapts as necessary.
Chris Lutz
@Chris, that's a good idea for future-proofing.
Carl Norum