tags:

views:

262

answers:

2

As said in the title, the goal is to copy a c-style string into memory without using any standard library functions or subscripting.

Here is what I have so far [SOLVED]

#include "std_lib_facilities.h"

char* strdup(const char* p)
{
    int count = 0;
    while(p[count]) ++count;
    char* q = new char[count+1];
    for(int i = 0; i < count+1; ++i) *(q+i) = *(p+i);
}

int main()
{
    char word[] = "Happy";
    strdup(word);
}

Obviously the problem is that allocating just *p (which is equivalent to p[0]) only allocates the letter "H" to memory. I'm not sure how to go about allocating the C-style string without subscripting or STL functions.

+5  A: 

C-style string ends with '\0'. You need to traverse the string inside the function character by character until you encounter '\0' to know how long it is. (This is effectively what you would do by calling strlen() to work it out.) Once you know how long the string is, you can allocate the right amount of memory, which is the length+1 (because of the '\0').

To access the i'th element of an array p, one use subscript: p[i].

Subscript of the form p[i] is formally defined to be *((p)+(i)) by both the C standard (6.5.2.1 of C99) and the C++ standard (5.2.1 of C99). Here, one of p or i is of the type pointer to T, and the other is of integral type (or enumeration in C++). Because array name is converted automatically (in most types of use anyway) to a pointer to the first element of said array, p[i] is thus the i'th element of array p.

And just like basic arithmetic, ((p)+(i)) is equivalent to ((i)+(p)) in pointer arithmetic. This mean *((p)+(i)) is equivalent to *((i)+(p)). Which also mean p[i] is equivalent to i[p].

KTC
Now his only problem is to figure out how to do this without using `[]`. Good exercise.
dmckee
Yes, I figured that I would need to know the string length, but even if I'm able to allocate the right amount of memory I still need to put the string in the memory. If I knew the string length this is what I would do: for(int i = 0; i < stringlength-1; ++i) q[i] = p[i]; but I can't use subscripting...
trikker
p[i] is the same as *(p + i)
KTC
^This is exactly what I was looking for. Thanks!
trikker
@KTC: Is it time to tell him about the i[p] exploit? :D
Hooked
There, done! :D
KTC
That's not really an exploit that is just part of the syntax. I couldn't use subscripting anyway and I can't see any real reason to use an i[p] format over a p[i] format unless you feel like confusing people.
trikker
A: 

Well, since this a self-teaching excercise, here's an alternative look at a solution that can be compared/contrasted with KTC's nice explanation of the equivalence between subscripting and pointer arithmetic.

The problem appears to be, "implement a strdup() function without using standard library facilities or subscripting".

I'm going to make an exception for malloc(), as there's no reasonable way to do the above without it, and I think that using it isn't detrimental to what's being taught.

First, let's do a basic implementation of strdup(), calling functions that are similar to the ones we might use from the library:

size_t myStrlen( char* s);
char* myStrcpy( char* dst, char* src);

char* strdup( char* p)
{
    size_t len = myStrlen( p);

    char* dup = (char*) malloc( len + 1);   /* include space for the termination character */

    if (dup) {
        myStrcpy( dup, p);
    }

    return dup;
}

Now lets implement the worker functions without subscripting:

size_t myStrlen( char* s)
{
    size_t len = 0;

    while (*s != '\0') {  /* when s points to a '\0' character, we're at the end of the string */
        len += 1;

        s += 1; /* move the pointer to the next character */
    }

    return len;
}


char* myStrcpy( char* dst, char* src)
{
    while (*src != '\0') {  /* when src points to a '\0' character, we're at the end of the string */
        *dst = *src;

        ++dst;  /* move both pointers to next character location */
        ++src;
    }

    *dst = '\0'; /* make sure the destination string is properly terminated */

    return dst;  /* this is just done to make myStrcpy() closely mimic strcpy() */
}

And there you have it. I think this satisfies the condition of the assignment and shows how pointers can be manipulated to move though an array of data items instead of using subscripting. Of course, the logic for the myStrlen() and myStrcpy() routines can be moved inline if desired, and more idiomatic expressions where the pointer increment can happen in the expression that copies the data can be used (but I think that's more confusing for beginners).

Michael Burr