1. 程式人生 > >第三章:數組和字符串

第三章:數組和字符串

ans can 輸入 是否 讀取字符串 下一步 字符數組 lag getc

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 }

第三章:數組和字符串