Pointer retaining string

Viewed 78

So I wrote a code that inputs a word, takes it's first letter and puts it at the end of the word( eg. "egg" will be "gge", and if we do the same process again it will be "geg" and then finally back to "egg") I want to do this process only 1 time. And I want to use a pointer to memorize the initial value of the word, that is egg, and then the string has to memorize "gge".

This is the code:

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    char s[100],aux,*P;
    int p=1,i,n,k,j;
    cin.get(s,100);
    i=0;
    while(i>=0)
    {
        P=s; //this is the pointer that SHOULD memorize "egg"
        aux=s[0]; 
        for(j=1; j<=n; j++) s[j-1]=s[j];
        s[n]=aux;//until here it does the letter thing
        break;
    }
     cout<<P<<endl<<s;//now here the pointer P should be "egg" and the string s should be "gge"
     //but the program prints out "gge" and "gge".

    return 0;
}

What am I doing wrong and how am I supposed to do what I want?

2 Answers

What am I doing wrong and how am I supposed to do what I want?

You seem to have misunderstood what a pointer is. A pointer is a variable that points to something else. In this case

char s[100];
char *P = s;

P points to the first character element of s. This is the same pointer that s decays to in many contexts.

You still only have one array to store 100 characters. You just have two identifiers for that array, because you can reach it via either s or P.

If you mutate that array in place from "egg" to "gge" or whatever, P still just points to the same array it did originally. It didn't save a copy of anything but the location (address) and that isn't what changed.

If I can take two roads to get to your blue house, and you repaint the house green, one of the roads doesn't still lead to the original blue house. That isn't how roads work, or how houses work, or how pointers work.

You want somewhere to store the original 3 or 4 characters, which means you want another char array, or better a std::string. This will make a copy of the characters you care about before you change them.

The minimal working change is probably

// P = s <-- just stores the location
P = strdup(s); // <- copies the contents

but do note you should free(P) at some point after you're done with it. Switching to std::string is really much easier.


Simple example of using std::string value semantics to do the copying:

#include <string>
#include <algorithm>
#include <iostream>

// source is a copy of the string passed
std::string rotate_left(std::string source, size_t offset = 1)
{
    std::rotate(source.begin(), source.begin()+offset, source.end());
    return source;
}

int main()
{
    std::string original{"eggsoup"};
    // for interactive use: getline(std::cin, original);

    std::string rotated = rotate_left(original);

    std::cout << original << '\n' << rotated << '\n';
}

This is called rotating the string.

It's not clear why you have decided to use a pointer for this. A pointer is not a string. A pointer doesn't "contain" its own information*. A pointer points to some piece of information. Here you're making a pointer that points to the original string, and then you alter that string … but your pointer is still just pointing to that same, altered string. The pointer has no knowledge of what form the string used to take, only where it is.

If you want to store a copy of the original string, you have to literally do that, either by copying its elements into a second char array, or by switching to std::string because it's 2018.

* Well, obviously it does; it contains the address of the thing it points to, which in itself is "information". But it's not the information you wanted.

If you really want to use a pointer, you can actually get the expected outcome using them, but not in the way that you're expecting (i.e. not by storing a copy of the string). Since you know you have rotated the string n times, and you know where it starts (that's P!) and you know how long it is (that's n, although you currently aren't setting that, which is a bug), you can do some mathematics to output the original form of the string just by navigating its current form in a different order.

const char* startOfString = &s[0];
const size_t lengthOfString = strlen(s);
const size_t numberOfRotations = 1;

// ... do your rotation here

// Now we can still print the original form, char by char, using MATHS!
for (size_t index = 0; index < lengthOfString; index++)
{
   const size_t adjustedIndex = (index + lengthOfString - numberOfRotations) % lengthOfString;
   std::cout << startOfString[adjustedIndex];
}

(live demo)

But, then, you may as well have "performed" (or pretended to perform) the actual rotation in this manner in the first place, too.

Or just print the string when you get it, before you rotate it.

Related