Reputation: 4829
If I have the string .....ZZ..ZZ.....
or .Z.1.Z.23Z.4.Z55
,
Is there an easy way of shifting all Z
characters in the string one space right of the current position?
Some additional test strings are:
.Z
Z.
ZZ.
.ZZ
Z
ZZ
ZZZ
I think a few of the higher voted answers to this question (including the currently accepted one) do not work on these tests.
Upvotes: 1
Views: 12631
Reputation: 200766
Just iterate through the text and swap characters:
int main ()
{
char text[] = "...Z.Z.Z...", temp;
int text_len = strlen (text), i;
for (i = text_len - 1; i >= 0; i--)
{
if (text[i] == 'Z')
{
temp = text[i+1];
text[i+1] = text[i];
text[i] = temp;
}
}
printf ("%s\n", text);
return 0;
}
Produces:
[~]$ gcc zshift.c && ./a.out
....Z.Z.Z..
There's a lot of discussion in the comments about a possible off-by-1 error in the above code. However, simple testing / stepping through is enough to show that this is not the case.
zshift "Z." -> ".Z"
zshift ".Z" -> "."
zshift "Z" -> ""
I think the behavior of "dropping" trailing Zs when shifting off the end of the string is sensible. After all, if you shift the bits of an integer, bits that end up outside the bounds of the integer are dropped.
If another behavior is desired -- for example, shifting only within the string -- the change to the algorithm is minimal:
temp = text[i+1];
if (temp == 0) continue;
text[i+1] = text[i];
text[i] = temp;
Upvotes: 5
Reputation: 52337
Building on previously posted code here. Function gets str and strlen, overwrites str. Works also with subsequent Z. Going forward for speed improvement with subsequent Z.
void move_z_right (char* str, int strlen) {
for (unsigned int i = 0; i < strlen - 1; ++i)
{
if (str[i] == 'Z')
{
unsigned int j = i+1;
while (str[j] == 'Z' && j < strlen - 1) ++j;
if (j == strlen) break; // we are at the end, done
char tmp = str[j];
str[j] = str[i];
str[i] = tmp;
i = j; // continue after new Z next run
}
}
}
Note that John Millikin's solution is nicer to read and also correct.
Upvotes: 2
Reputation: 823
Slight fix to the previous answer (shift to the right and assume '.' means "can move here"):
char text[] = "...Z.Z.Z...";
for (int i = strlen(text) - 2); i > 0; --i) {
if (text[i] == 'Z' && text[i + 1] == '.') {
text[i] = '.';
text[i + 1] = 'Z';
}
}
Upvotes: 0