第三章:数组和字符串

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 }
时间并不会因为你的迷茫和迟疑而停留,就在你看这篇文章的同时,不知道有多少人在冥思苦想,在为算法废寝忘食,不知道有多少人在狂热地拍着代码,不知道又有多少提交一遍又一遍地刷新着OJ的status页面…… 没有谁生来就是神牛,而千里之行,始于足下!
原文地址:https://www.cnblogs.com/bianjunting/p/9826185.html