設一個操作數x有s位則循環左移n位的操作爲:
(x << n) | (x >> (s - n));
同理右移n位位:
(x >> n) | (x << (s - n));
實際編程中可以用宏定義實現循環移位:
#define ROTATE_LEFT(x, s, n) ((x) << (n)) | ((x) >> ((s) - (n)))
#define ROTATE_RIGHT(x, s, n) ((x) >> (n)) | ((x) << ((s) - (n)))
例如:
#include <stdio.h>
#define ROTATE_LEFT(x, s, n) ((x) << (n)) | ((x) >> ((s) - (n)))
#define ROTATE_RIGHT(x, s, n) ((x) >> (n)) | ((x) << ((s) - (n)))
int main()
{
unsigned int a;
scanf("%x", &a);
printf("%08x\n", a);
printf("%08x\n", ROTATE_LEFT(a, 8 * sizeof(int), 4));
printf("%08x\n", ROTATE_RIGHT(a, 8 * sizeof(int), 8));
return 0;
}
運行結果:
12345678 //原數
23456781 //移1位後
具體樣例:
設有數據 a=01111011,循環左移2位 正確結果: 11101101
分步實現:
b=a>>(8-2) ;//用來得到正常左移丟失的位和循環移位後其正確位置 b="00000001";
a="a"<<2;//左移 a="11101100"
a=a|b; //a=11101101
如果不是用中間變量一步實現: a=(a>>(8-2))|(a<<2);
總長度N(8 16 32)
循環左移n (a>>(N-n))|(a>>n)
循環右移n (a<<(N-n))|(a>>n)
C語言的位運算功能是其區別於其他大多數高級程序設計語言的特色之一,用它可以方便實現一些特殊功能,靈活掌握是用C程序編寫系統程序的基礎。
其他對位進行操作的還有位域法;
幾個對位操作的樣例如下:
#define SETBIT(REG,N) REG|=(1<<N) //對REG的N位置1
#define CLRBIT(REG,N) REG&=~(1<<N) //對REG的N位清零
#define INVBIT(REG,N) REG^=(1<<N) //對REG的N位取反
===================================================================================================================================
我們在C語言中常常碰到字符串循環左右移位的題型,下面對其進行詳解:
例如:有一組char的字符串:abcdefghijk 。你要循環左移3位變成ijkabcdefgh(也有寫出ijkabcdefghi);或右移三位變成defghijkabc(也有寫成cdefghijkabc);
首先我們來解決字符串循環右移的問題:
方法一:利用已有的字符串函數。
#include<stdio.h>
#include<string.h>
void rightloop(char *a, int n);
main()
{
char a[100]; int n;
printf("請輸入要循環的字符串:/n");
scanf("%s",a);
printf("請輸入要循環字符串的位數:/n");
scanf("%d",&n); //以上代碼也可以直接賦初值,我考慮的是一般情況//
void rightloop(a,n); //本例以a[]="abcdefghijk", n=3爲例講解//
printf("輸出循環右移的字符串:%s/n",a);
}
void rightloop(char *a, int n)
{
char b[100]; //數組b要做的夠大即可//
int m;
m=strlen(a)-n; //求出除去要循環右移之後剩下的字符的個數//
strcpy(b,a+n); // a+n,a代表a[0]的地址再加上n,表示要把a[n]之後的字符串(即那些不用循環右移的字符,共有m個)複製到數組b中。這時b[]="defghijk"。 //
strcpy(b+m,a); // b+m, 因爲上面已經把沒有循環的m個字符賦給了b,所以b[m]之前的不能在賦值了,只能把a的全部字符串賦給b[m]之後的空間了。這時b[]="defghijkabcdefghijk"。//
*(b+strlen(a))='/0'; //這裏是問題的關鍵,要根據a字符串的長度來捨棄b數組中多餘的字符串,並給數 組b加結束符。這時b[]="defghijkabc";//
strcpy(a,b); //把數組b中調整好的字符串重新賦給數組a。//
}
方法二:就是用簡單的c語句;
#include<stdio.h>
void rightloop(char , int )
main()
{
char a[100]; int n;
printf("請輸入要循環的字符串:/n");
scanf("%s",a);
printf("請輸入要循環字符串的位數:/n");
scanf("%d",&n); //以上代碼也可以直接賦初值,我考慮的是一般情況//
void rightloop(a,n); //本例以a[]="abcdefghijk", n=3爲例講解//
printf("輸出循環右移的字符串:%s/n",a);
}
void rightloop(char a[ ], int n)
{
int i=0,j=0,k=0;
int m; char b[100];
while(a[i]!='/0')
{ i++; } //這裏用i來計算數組a中字符串的大小;//
while(a[n]!='/0')
{
b[j]=a[n]; j++; n++;
} //這裏是把不需要循環右移的字符串賦值到數組b中;b[ ]="defghijk"。//
while(a[k]!='/0')
{
b[j]=a[k]; j++; k++;
} //因爲上一個while循環中,數組b已經賦值到b[j]了。所以這裏直接從b[j]開始把數組a中的字符串全部賦值到數組b[j]以後的空間中;b [ ]="defghijkabcdefghijk";//
b[i]='/0'; //通過用數組a中字符串的長度i來調整數組b的長度,刪去數組b中多餘的字符串 ,b[]="defghijklabc"。
for(i=0;b[i]!='/0';i++)
{ a[i]=b[i]; } //把數組b中調整好的字符串重新賦給數組a。//
}
再次我們來解決字符串循環左移的問題
方法一:調用已經有的字符串函數。
#include<stdio.h>
#include<string.h>
void leftloop(char *a, int n);
main()
{
char a[100]; int n;
printf("請輸入要循環的字符串:/n");
scanf("%s",a);
printf("請輸入要循環字符串的位數:/n");
scanf("%d",&n); //以上代碼也可以直接賦初值,我考慮的是一般情況//
void leftloop(a,n); //本例以a[]="abcdefghijk", n=3爲例講解//
printf("輸出已經循環左移的字符串:%s/n",a);
}
void leftloop(char*a,int n)
{char b[100]; //數組b要做的夠大即可//
int m;
m=strlen(a)-n; //求出除去要循環右移之後剩下的字符的個數//
strcpy(b,a+m); // a+m,a代表a[0]的地址再加上m,表示要把a[m]之後的字符串(即那些需要循環左移的字符,共有n個)複製到數組b中。這時b[]="ijk"。 //
strcpy(b+n,a); // b+n, 因爲上面已經把需要循環的n個字符賦給了b,所以b[n]之前的不能在賦值了,只能把a的全部字符串賦給b[n]之後的空間了。這時b[]="ijkabcdefghijk"。//
*(b+strlen(a))='/0'; //這裏是問題的關鍵,要根據a字符串的長度來捨棄b數組中多餘的字符串,並給數組b加結束符。這時b[]="ijkabcdefgh";//
strcpy(a,b); //把數組b中調整好的字符串重新賦給數組a。//
}
方法二:就是用簡單的c語句;#include<stdio.h>
void leftloop(char , int )
main()
{
char a[100]; int n;
printf("請輸入要循環的字符串:/n");
scanf("%s",a);
printf("請輸入要循環字符串的位數:/n");
scanf("%d",&n); //以上代碼也可以直接賦初值,我考慮的是一般情況//
void leftloop(a,n); //本例以a[]="abcdefghijk", n=3爲例講解//
printf("輸出已經循環左移的字符串:%s/n",a);
}
void leftloop(char a[ ], int n)
{
int i=0,j=0,k;
int m; char b[100];
while(a[i]!='/0')
{ i++; } //這裏用i來計算數組a中字符串的大小;//
k=m=i-n; //計算出前面有多少個字符不用移動//
while(a[k]!='/0')
{
b[j]=a[k]; j++; k++;
} //因爲這時k=i-m,a[k]表示需要循環移動的第一個字符,這裏是把需要循環右移的字符串賦值到數組b中;b[ ]="ijk"。//
b[j]='/0';
m--;k--; //因爲要用m調節下面的循環但是要從0開始所以比實際的多了一次;k--是爲了要留着數組a中的結束符,不出現亂碼;//
while(m>=0)
{
a[k]=a[m]; m--; k--;
} // 原來a[k]=“abcdefghijk",a[m]="abcdefgh",賦值之後a[k]="abcabcdefgh";//
for(i=0;b[i]!='/0';i++)
{ a[i]=b[i]; } //把數組b中調整好的字符串重新賦給數組a。b[i]="ijk";a[i]="abcabcdefgh"。賦值之後a[i]="j//
}