2017-07-07 66 views
-3

我试图移位一个字符串,左边和右边给出了移位字符串的位置数。在C中旋转一个字符串

这是我写的,但迄今为止它不工作。

void Shift(char* string, shift) 
{ 
    int length = strlen(string)-1; 
    int i; 
    char *buff; 
    buff = malloc((sizeof(char) *shift) + 1); 
    strncpy(buff, string, shift); 
    buff[shift] = '/0'; 
    while (string[i + shift] != '/0') 
     string[i++] = string[i + shift]; 
    strcat(string, buff); 
} 

我该如何解决这个问题? 这应该是例如: 移= 1个

HELLO - > OHELL

+4

“不起作用”不是一个明确的问题陈述。你能否用更具体的问题陈述来编辑你的问题? –

+4

'buff [n] ='\ 0''中的n是什么?它与什么有关? – AnT

+5

修复您的功能签名。这不是标准。 –

回答

2

我的解决方案使用了O旋转串代替(1)存储:

#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 

void rotleftmem(void *p, size_t len, size_t lshift) 
{ 
    unsigned char *d; 
    size_t start; 
    size_t dx, sx; 
    size_t todo; 
    unsigned char x; 

    if (!len) 
     return; 
    lshift %= len; 
    if (!lshift) 
     return; 

    d = p; 
    todo = len; 
    for (start = 0; todo; start++) { 
     x = d[start]; 
     dx = start; 
     while (1) { 
      todo--; 
      sx = dx + lshift; 
      if (sx >= len || sx < dx /*overflow*/) 
       sx -= len; 
      if (sx == start) { 
       d[dx] = x; 
       break; 
      } 
      d[dx] = d[sx]; 
      dx = sx; 
     } 
    } 
} 

void *rotatemem(void *p, size_t len, ssize_t rshift) 
{ 
    if (len) { 
     size_t lshift = rshift < 0 ? -rshift : len - rshift % len; 

     rotleftmem(p, len, lshift); 
    } 
    return p; 
} 

char *rotatestr(char *s, ssize_t rshift) 
{ 
    return rotatemem(s, strlen(s), rshift); 
} 

int main(int argc, char *argv[]) 
{ 
    ssize_t rshift; 
    char *s; 

    if (argc != 3) { 
     fprintf(stderr, 
       "usage: %s N STR\n" 
       "Rotate STR right by N or left by -N\n", 
       argv[0]); 
     return 2; 
    } 

    rshift = strtol(argv[1], NULL, 10); 
    s = argv[2]; 
    printf("%s\n", rotatestr(s, rshift)); 
    return 0; 
} 

代码的胆是在功能rotleftmem,其旋转的存储器块指定的长度留下一个指定的,无符号的“左移”值。 rotatemem是围绕rotleftmem围绕任一方向旋转的包装;负移位值向左旋转,正移位值向右旋转;带符号的移位值被转换为正的“左移”值。 rotatestr是一个围绕rotatemem的包装,它接受一个指向空终止字符串的指针,而不是指向void加长度的指针。 rotatestrrotatemem都返回原始指针。

对于rotleftmem,如果块长度(len)是非零的,“左移位”的值(lshift)降低模len。如果len或(减少的)lshift值中的任一值为0,则该函数不执行任何操作。否则,外环将迭代GCD(len, lshift)次(其中GCD(a, b)ab最大公约数)。对于外部循环的每次迭代,内部循环将迭代len/GCD(len, lshift)次,因此内部循环的迭代总数为len。时间复杂度是O(n),其中n是块的长度。

2

我的解决办法是基于模,使用负数到左侧和正数移位到右侧移位。

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <string.h> 

void shift(char* string, int shift) 
{ 
    char *tmp = strdup(string); 
    int len = strlen(string); 
    if (shift < 0) 
     shift = len + (shift % len); 
    for (int i = 0; string[i] != 0; i++) { 
     int new_idx = (i + shift) % len; 
     tmp[new_idx] = string[i]; 
    } 
    memcpy(string, tmp, len); 
    free(tmp); 
} 

int main(void) { 
    char test[] = "coucou"; 
    shift(test, -9); 
    printf("%s\n", test); 
    return 0; 
} 

诀窍是计算每个字符将在目标字符串中结束的位置。通过使用总大小的模数,确保它保持在边界之间,从而增加偏移量,然后确保它保持在边界内,从而得到正确的索引。

对于左移位,我只是改变了左移位偏移转换为右移位偏移,并重新使用移位码的权利。

1

可以使用XOR位运算符来交换字符和循环扭转他们。

#include <stdio.h> 
#include <stdlib.h> 


void reverse(char *a, int n) { 

    for (int i=0, j=n-1; i < j; i++, j--) { 
     a[i] = a[i]^a[j]; 
     a[j] = a[j]^a[i]; 
     a[i] = a[i]^a[j]; 
    } 
} 


int main(int argc, char const *argv[]) { 

int k = 1; // shift count 
int n = 5; 
char a[] = "HELLO"; 

reverse(&a[n-k], k); // reverse end of array 
reverse(a, n-k);  // reverse beginning of array 
reverse(a, n);  // reverse entire array 

// print output 
for (int i=0; i < n; i++) { 
    printf("%c\n", a[i]); 
} 

return 0; 

}

+0

'a [i]^= a [j]^= a [i]^= a [j];'具有未定义的行为。它需要每个作业之间的顺序点。 –

+0

@IanAbbott我继续前进并扩展它。现在应该定义操作顺序。 – n3wb

+1

三种交换事物是反模式。它会执行太多的内​​存写操作,并创建干扰流水线的错误依赖项。只是使用一个临时的;现在寄存器很丰富,所以你可以使用一个。如果要加快反向速度,可使用SIMD指令一次反转16个字节(每个末端8个字节),或者在最近的CPU上反转更多。 – rici