第三章:數組和字符串
2018-10-21-18:37:41
隨學筆記
小計
<1>:比較大的數組一般定義在main函數外面,否則程序很容易出錯。
<2>:memset 函數:
原型:void *memset(void *s, int ch, unsigned int n); //將s中當前位置後面的n個字節 用 ch 替換並返回 s。
<3>:memcpy函數:
原型:void *memcpy(void *dest, const void *src, unsigned int n);//從源src所指的內存地址的起始位置開始拷貝n個字節到目標dest所指的內存地址的起始位置中。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 6 int main() 7 { 8 char s[20]="I ‘ m cruel king "; 9 char cpy[20]; 10 memcpy(cpy,s,(strlen(s)+1)); 11 printf("%s\n",cpy); 12 return 0; 13 }
<4>:sprinrf函數:
原型:int sprintf(char *buffer, const char *format, [argument]...)
參數:
(1)buffer:是char類型的指針,指向寫入的字符串指針;
(2)format:格式化字符串,即在程序中想要的格式;
(3)argument:可選參數,可以為任意類型的數據;
函數返回值:buffer指向的字符串的長度;
用法:
①:連接字符串
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 5 int main() 6 { 7 char buffer[10]; 8 char *a = "i‘m "; 9 char*b = "cruel king !"; 10 sprintf(buffer, "%s%s", a, b); 11 printf("%s\n", buffer); 12 return 0; 13 }
②:將int型數字格式化為字符型
1 sprintf(buffer, "%d", 123456);執行後buffer即指向字符串“123456”
③:連接結尾沒有‘\0‘的字符數組或字符串緩沖區:
1 #include<cstdio> 2 #include <iostream> 3 using namespace std; 4 5 int main() 6 { 7 char a[] = {‘1‘, ‘2‘, ‘3‘, ‘4‘}; 8 char b[] = {‘5‘, ‘6‘, ‘7‘, ‘8‘}; 9 char buffer[10]; 10 sprintf(buffer, "%.4s%.4s", a, b); 11 printf("%s\n", buffer); 12 return 0; 13 }
/*在本例中,%.4s是指字符串的前四個字符。
For example
用scanf讀取字符串時可以限制一次性讀入的字符數 scanf("%.5f",str);前5個字符以後的輸入留在輸入緩沖區裏
④:如果想動態獲取要處理的字符緩沖區長度時可以采用 sprintf(buffer, "%.*s%.*s", sizeof(a), a, sizeof(b), b);
⑤:strchr 函數:
函數原型:char *strchr(const char* _Str,char _Val) 頭文件:#include <cstring> 功能:查找字符串_Str中首次出現字符_Val的位置 說明:返回首次出現字符_Val的位置的指針,返回的地址是被查找字符串指針開始的第一個與Val相同字符的指針,如果Str中不存在Val則返回NULL。 返回值:成功則返回要查找字符第一次出現的位置,失敗返回NULL。 ⑥:isalpha函數: 函數原型:int isalpha( int ch ); 頭文件:#include <cctype> 功能:判斷ch是否為字母,若為英文字母,返回非0(小寫字母為2,大寫字母為1),若不是字母,返回0。 ⑦:輸入輸出函數中:%o為八進制,%d為十進制,%x為十六進制。 %i表示有符號十進制整數,它與%d相比較的優點:%i可以自動將輸入的八進制或十六進制轉換為十進制。 ⑧:移位運算符:在C語言中,"乘以2"也可以寫為"<<1",意思就是左移一位。類似的左移四位就是乘以2的四次方。"除以2"也可以寫為">>1"。若要表示2的八次方也可以寫為(1<<8)-1。移位運算符的優先級沒有減法高。 ⑨:原碼,反碼,補碼。 原碼:規定正數的符號為0,負數的符號為1,其他位為真值的絕對值的二進制表示。 反碼:正數的原碼與反碼相同,負數的反碼為符號位不變其他位按位取反。 補碼:正數的補碼與原碼相同,負數的補碼為在其反碼的基礎上加一。 計算機中數值廣泛采用補碼的形式來保存和計算。課內練習:
蛇形填數:先利用memset函數將地圖初始化為零,接著找到蛇頭,設置一個遞增器按照邏輯一 一循環填入即可。
循環條件中避開蛇碰到身體和自身的情況即可,當蛇走完全程退出總循環。
總體思路就和智能貪吃蛇一樣,每次都按照上一次的方向前進,當判斷出下一步會撞墻或者撞到自己時轉向即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 6 int main() 7 { 8 int length,width,flag,x,y; 9 scanf("%d %d",&length,&width); 10 int snack[width][length]; 11 memset(snack,0,sizeof(snack)); 12 flag=snack[x=0][y=length-1]=1; 13 while(flag<length*width){ 14 while(x+1<width&&!snack[x+1][y]) snack[++x][y]=++flag; 15 while(y-1>=0&&!snack[x][y-1]) snack[x][--y]=++flag; 16 while(x-1>=0&&!snack[x-1][y]) snack[--x][y]=++flag; 17 while(y+1<length&&!snack[x][y+1]) snack[x][++y]=++flag; 18 } 19 for(int i =0;i<width;i++){ 20 for(int j=0;j<length;j++) 21 printf("%d\t",snack[i][j]); 22 printf("\n"); 23 } 24 return 0; 25 }
豎式問題:
從小到大依次枚舉如果符合條件就按照相應格式輸出。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 6 int main() 7 { 8 int count=0; 9 char s[20],buf[99]; 10 scanf("%s",s); 11 for(int abc=111;abc<=999;abc++){ 12 for(int de =11;de<=99;de++){ 13 int x=abc*(de%10),y=abc*(de/10),z=abc*de; 14 sprintf(buf,"%d%d%d%d%d",abc,de,x,y,z); 15 int flag=1; 16 for(int i=0;i<strlen(buf);i++) 17 if(strchr(s,buf[i])==NULL) 18 flag=0; 19 if(flag){ 20 printf("<%d>\n",++count); 21 printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n",abc,de,x,y,z); 22 } 23 } 24 } 25 printf("The number of solutions = %d\n",count); 26 return 0; 27 }
競賽題目選學:
<1>:需要讀入一連串連續的字符時可以采用while((c=getchar())!=EOF)讀入。
For example
例題3-2 QWERTU
本題思路:利用常量數組儲存所有字符,接著一次性讀入字符串然後對單個字符依次處理。
1 #include<cstdio> 2 #include <iostream> 3 using namespace std; 4 char s[]="1234567890-=QWERTYUIOP[]\\ASDFGHJKL;‘ZXCVBNM,./"; 5 int main() 6 { 7 int i,c; 8 while((c=getchar())!=EOF){ 9 for(i=1;s[i]&&s[i]!=c;i++); 10 if(s[i]) putchar(s[i-1]); 11 else putchar(c); 12 } 13 return 0; 14 }
例題3-3 回文詞
本題思路:利用常量數組儲存每個字母所對應的鏡像字符,只需對應位置的鏡像字符是否相等即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cctype> 5 using namespace std; 6 const char*rev="A 3 HIL JM O 2TUVWXY51SE Z 8 "; 7 const char*msg[]={"not a palindrome","a regular palindrome","a mirrored string","a mirrored palindrome"}; 8 char re(char ch){ 9 if(isalpha(ch)) return rev[ch-‘A‘]; 10 return rev[ch-‘0‘+25]; 11 } 12 13 int main() 14 { 15 char s[30]; 16 while(scanf("%s",s)==1){ 17 int len=strlen(s); 18 int p=1,m=1; 19 for(int i=0;i<(len+1)/2;i++){ 20 if(s[i]!=s[len-1-i]) p=0;//判斷是否回文 21 if(re(s[i])!=s[len-i-1]) m=0;//判斷是否鏡像 22 } 23 printf("%s -- is %s.\n\n",s,msg[m*2+p]); 24 } 25 return 0; 26 }
例題3-4 猜數遊戲的提示
水題,註意輸入輸出即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int maxn=1010; 6 int ques[maxn],ans[maxn]; 7 8 int main() 9 { 10 int n,Case=0; 11 while(scanf("%d",&n)==1&&n){ 12 for(int i=0;i<n;i++) 13 scanf("%d",&ques[i]); 14 printf("Game %d:\n",++Case); 15 while(true){ 16 int a=0,b=0; 17 for(int i=0;i<n;i++){ 18 scanf("%d",&ans[i]); 19 if(ques[i]==ans[i]) a++;//統計位置正確的元素個數 20 } 21 if(ans[0]==0) break; 22 for(int i=0;i<10;i++){ 23 int c1=0,c2=0; 24 for(int j=0;j<n;j++){ 25 if(i==ques[j]) c1++;//統計各個數字在答案和猜測中出現的次數 26 if(i==ans[j]) c2++; 27 } 28 c1>=c2? b+=c2:b+=c1; 29 } 30 printf(" (%d,%d)\n",a,b-a); 31 } 32 } 33 return 0; 34 }
例題3-5 生成元
本題思路:將規定範圍內所有數的最小生成元打表,接著直接查表輸出即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int maxnumber=100000; 6 int ans[maxnumber]; 7 8 int main() 9 { 10 int n,T; 11 //將表所有元素初始化為零 12 memset(ans,0,sizeof(ans)); 13 //將1-100000以內所有最小生成元打表 14 for(int i=1;i<=maxnumber;i++){ 15 int y=i,x=i; 16 while(x>0){ 17 y+=x%10; 18 x/=10; 19 } 20 if(ans[y]==0||ans[y]>i) 21 ans[y]=i; 22 } 23 scanf("%d",&T); 24 while(T--){ 25 scanf("%d",&n); 26 printf("%d\n",ans[n]); 27 } 28 return 0; 29 }
例題3-6 環狀序列
本題思路:所謂字典序,就是字符串在字典中的順序。推廣到任意序列時,例如序列1,2,4,7比1,2,5的小。本題先假設第零個位置為字典序最小的位置,接著從第一個開始遍歷字符串,當遇到以
s[i]開頭的子串小於s[ans]開頭的子串時讓ans=i,當i=n-1時結束循環。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int maxn=105; 6 char s[maxn]; 7 int lessc(char*s,int p,int q,int n); 8 9 int main() 10 { 11 int T; 12 scanf("%d",&T); 13 while(T--){ 14 scanf("%s",s); 15 int n=strlen(s),ans=0; 16 for(int i=1;i<n;i++) 17 if(lessc(s,i,ans,n)) ans=i; 18 for(int i=0;i<n;i++) 19 putchar(s[(i+ans)%n]); 20 putchar(‘\n‘); 21 } 22 return 0; 23 } 24 int lessc(char*s,int p,int q,int n){ 25 for(int i=0;i<n;i++) 26 if(s[(p+i)%n]!=s[(q+i)%n]) 27 return s[(p+i)%n]<s[(q+i)%n]; 28 return 0; 29 }
第三章:數組和字符串