2017-07-07 108 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