如果我有字符串.....ZZ..ZZ.....
or .Z.1.Z.23Z.4.Z55
,
有没有一种简单的方法可以将Z
字符串中的所有字符在当前位置右侧移动一个空格?
一些额外的测试字符串是:
.Z
Z.
ZZ.
.ZZ
Z
ZZ
ZZZ
我认为这个问题的一些较高投票的答案(包括当前接受的答案)在这些测试中不起作用。
只需遍历文本并交换字符:
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;
}
产生:
[~]$ gcc zshift.c && ./a.out
....Z.Z.Z..
评论中有很多关于上述代码中可能出现的 off-by-1 错误的讨论。但是,简单的测试/单步执行就足以表明情况并非如此。
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;
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.
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';
}
}