1

I have a null terminated array of chars. Also known as a c-string. I have written a function that will shift the elements at each index left, <---- by a given number of indexes. For example, when the char array of "hello world" is passed to the function, with a shiftBy value of 3, it should transform the char array to be: "lo worldhel".

Currently, this function works for all strings that <= 11 elelements. Anything over that and the last three spots in the array don't get shifted. Keep in mind, the very last index is holding the null terminator!

This is a tricky one and I have been stuck for hours. I also can't use any standard functions or vectors, I am stuck with these deprecated arrays and simple loops. So please don't troll with "Why don;t you use blank function"....because trust me, if I could I wouldn't be here.

Here is the code, have at at:

    void shiftLeft (char szString[], int size, int shiftBy)
{
    if(shiftBy > size){
        shiftBy = shiftBy - size;
    }

    if(size == 1){
        //do nothing, do nothing, exit function with no change made to myarray
    }
    else{
        char temp;
        //for loop to print the array with indexes moved up (to the left) <-- by 2
        for (int i = 0; i <= size-shiftBy; i++)//size = 11
        {//EXAMPLE shift by 3  for a c-string of `hello world`
            if(i < size-shiftBy){
                temp = szString[shiftBy + i];//temp = h
                szString[shiftBy + i] = szString[i];//d becomes l
                szString[i] = temp;//h becomes l
            }
            else{//it will run once while i=8
                temp = szString[i];//temp = l
                szString[i] = szString[i+1];//8th element becomes h
                szString[i+1] = szString[size-1];//9th element becomes e
                szString[size-1] = temp;//last element becomes l

            }

        }
    }
}

2 Answers2

0

From azillionmonkeys.com/qed/case8.html

void shiftLeft(char szString[], int size, int shiftBy) {
            int c, tmp, v;

            if (size <= 0) return;
            if (shiftBy < 0 || shiftBy >= size) {
                shiftBy %= size;
                if (shiftBy < 0) shiftBy += size;
            }
            if (shiftBy == 0) return;

            c = 0;
            for (v = 0; c < size; v++) {
                int t = v, tp = v + shiftBy;
                char tmp = szString[v];
                c++;
                while (tp != v) {
                    szString[t] = szString[tp];
                    t = tp;
                    tp += shiftBy;
                    if (tp >= size) tp -= size;
                    c++;
                }
                szString[t] = tmp;
            }
        }
ryanpattison
  • 6,151
  • 1
  • 21
  • 28
  • I am very concerned why there is a `return` statement in the middle of this `void` function. –  Nov 06 '14 at 02:55
  • Not an error at all.http://stackoverflow.com/questions/2249108/can-i-return-in-void-function – ryanpattison Nov 06 '14 at 02:59
  • Damn it, I concede. I got this to work and it works flawlessly. I wasn't the one who downvoted this answer, but I sure will upvote it. Thanks for the help and sorry for the poor attitude. Thanks to you I can finally go to bed mate. Also I will study it more in depth tomorrow, and try my best to learn from it. –  Nov 06 '14 at 03:05
0

If the only purpose you're trying to accomplish is shifting chars in a terminated string left with rotation (and judging by your sample of "helloworld" resulting in "loworldhel" after a 3-shift, that seems to be the case), you're making this much harder than it needs to be.

The traditional algorithm to do this in O(N) time with no temporary space requirements is to reverse the left-side of the shift, then the entire sequence, then the right side of the shift, all based from the beginning of the sequence. For example, suppose we want to left-shift the following string 3 slots:

1234567890

First, reverse the first shiftBy slots

1234567890
^-^
3214567890

Second, reverse the entire sequence

3214567890
^--------^
0987654123

Finally, reverse the (length-shiftBy) slots:

0987654123
^-----^
4567890123

Using the standard library would make this trivial, but apparently you're prof considers that... cheating. Without using any library apis the above algorithm isn't very hard regardless:

#include <iostream>

void shiftLeft(char sz[], size_t shiftBy)
{
    const char *p = sz;
    while (*p) ++p;
    std::size_t len = p - sz;

    if (len > 1 && (shiftBy %= len))
    {
        char *ends[] = { sz+shiftBy, sz+len, sz+(len - shiftBy) };
        for (std::size_t i=0; i<3; ++i)
        {
            char *start = sz, *end = ends[i];
            while (start < --end)
            {
                char ch = *start;
                *start++ = *end;
                *end = ch;
            }
        }
    }
}

int main()
{
    char sz[] = "1234567890";
    std::cout << sz << '\n';

    shiftLeft(sz, 11);
    std::cout << sz << '\n';

    shiftLeft(sz, 4);
    std::cout << sz << '\n';

    shiftLeft(sz, 1);
    std::cout << sz << '\n';

    shiftLeft(sz, 20);
    std::cout << sz << '\n';
}

Output

1234567890
2345678901
6789012345
7890123456
7890123456

If you're really set on doing this in temp space, so be it, but I cannot possibly fathom why you would do so.

Best of luck.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • Thank you, this is also a fantastic and helpful answer. I also like that you inadvertently made a smiley faces. ^-^ –  Nov 06 '14 at 03:11
  • @DracoM. So long as you understand the concept behind it, its all good. Glad it helped. I just hope I explained the algorithm well enough. – WhozCraig Nov 06 '14 at 03:16