Linux C 编程学习第七天_字符串和多维数组_多维字符数组应用-剪刀石头布游戏

字符串

说实话我以前一直搞不懂这个玩意和字符还有数组之间的关系,每次串口通信的时候都要调试很久,各种接收发送乱码,都是因为数据不匹配或者转换出错。

字符串可以看作一个数组," hello world ! \n "

存储方式就像数组一样,也可以使用角标单独访问某个字符,如:

1 char a = "Hello world ! \n "[2];

虽然可以进行访问,但是不允许通过角标更改字符。

因为字符是只读的,不允许修改,这是和数组完全不同的。但是我们可以定义一个字符数组:

初始化方式:

char str[] = "Hello World ! "

 这是一个数组,里面元素为 一个个字符,这样的字符数组是可以进行更改的,并且以 '\0' 结尾,也可以叫做字符串。

其实硬要解释的话,字符串和以字符为元素的数组都可以称为字符串。

可以使用printf函数输出:

 

多维数组

 结构体可以嵌套,数组也一样,我们可以定义一个数组的元素是数组,这样就获得了多维数组。

定义一个二维数组:

 

这里说明,3 表示该数组有 3 个元素,2表示、每一个元素是大小为 2 的数组,没有被初始化的数字为0

所以这个二维数组有3个数组,a[0] a[1] a[2],每个数组都有2个元素,分别是{ 1,2 }、{ 3,4 }、{ 5,0 }

 

 

 

 这六个元素在存储器中依然是连续存储的,像一维数组一样,这种存储方式称为Row-major方式,另外有些语言是;一列一列接起来拼起一串存储的,称为Column-major方式。

二位数组初始化也可以这样,这样看的更加好区分

 

 

 第一维度的长度可以不指定,但是其余的长度都必须指定。

 1 #include <stdio.h>
 2 
 3 char str[] = "Hello World !";
 4 char a[][15] = {
 5                 "",
 6                 "Hello World !",
 7                 "yes!",
 8                 "no",
 9                         };
10 
11 int main(int argc, char const *argv[])
12 {
13     printf("%s\n", a[1]);
14     printf("%s\n", str);
15     return 0;
16 }

先前说的字符数组,在这里同样适用。

这样的方法可以代替 switch 语句,用下标访问数组,可以节省很多case分支,尤其事case分支里有重复操作的情况,这样做可以提取公因式。

这种方法称为数据驱动的编程(Data-driven Programming)。

 

尝试写一个剪刀石头布的代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <time.h>
 4 
 5 char str[] = "Hello! let's paly !";
 6 char a[][15] = {"you lose !", "you win !", "Draw !"};
 7 char str1[][20] = {"剪刀", "石头", ""};
 8 int b[] = {1, 0, 2, 1, 0};
 9 
10 int player = 0,cumputer = 0;
11 
12 void windows_cmd_support_utf8(void)
13 {
14 #ifdef WIN32
15     system("chcp 65001 & cls"); //cls 用来清除 chcp 的输出
16 #endif
17 }
18 
19 int main(int argc, char const *argv[])
20 {
21     windows_cmd_support_utf8();
22     srand(time(NULL));
23     printf("%s\n", str);
24     int goon = 0;
25 
26     while(1)
27     {    
28         cumputer = rand() % 3;
29         printf("请输入0,1,2分别代表剪刀,石头,布:\n");
30         scanf("%d", &player);
31         int i =b[(player - cumputer)+2];
32         printf("电脑出的是:%s\n你出的是:%s\n", str1[cumputer], str1[player]);
33         printf("%s\n", a[i]);
34     }
35     
36     return 0;
37 }

我尽力避免使用了 if 这样的语句,疯狂调用数组,突然发现,数组真的是太好玩了,不过相对的这样的写法就比 if 不直观,先看看运行,然后我在解释:

 

 

 首先我定义了几个字符串数组,用来存储输出的字符串:

 

 

 这样输出的时候就可以直接调用字符串数组,为了把一样的类型存储在一起,我将它们列成二维字符串数组。

接着先对石头剪刀布进行分析,我和机器人最多只能出 3 种可能,分别是:0,1,2,用我的输入数字减去计算机的输入。

分别列举出来:

 

 

 赢的情况有:1,-2,平局:0;输:-1,2

给所有数值加上2得到:赢:3,0;平局:2;输:1,4;

刚好复合一个数组的角标,0,1,2,3,4,那么我就创建一个数组,用来对应字符串数组的输出:

这里的1,0,2,1,0,实际上是为了对应字符串数组:

 

 我用 b[ ] 数组的值作为了 a[ ][ ] 数组的角标,那么就可以得到对应输出:

 

 同样,我将玩家输入的数,和电脑生成的伪随机数也坐为字符串数组str1[ ] 的角标,顺便输出对应的情况,看的更加直观。

要是我一个一个去定义字符串是十分麻烦的,但是采用字符串多维数组,就十分方便,同时上述代码没有使用 if 语句坐为判断,其实还是有点不严谨的,因为如果在程序中输入了其他非0,1,2的字符,就会出现奇奇怪怪的结果,或者卡死,应该在代码前加上判断输入的语句的,看了还是避免不了 if 啊~

扯远了,其实在这边是想说一个有意思的东西,那就是“(man - computer + 4) % 3 - 1”思路。

借用流浪的牙膏皮的博客:

man 和computer的取值只能是0 1 2,那么
man - computer 的结果可以是1,-2 0 -1,2
(man赢的取值是1,-2 平的取值是0,输的取值是-1,2)
加上4之后可以是 5,2(赢) 4(平) 3,6(输)
对3进行取余后只有 2(赢) 1(平) 0(输)
再减1 最后只有 1(赢) 0(平) -1 (输)
我认为编此程序 首先分析出 man - computer 的结果可以是1,-2 0 -1,2
其中(man赢的取值是1,-2 平的取值是0,输的取值是-1,2)
利用一些数学表达式运算 把这三类区别开就可以,不一定拘泥在“(man - computer + 4) % 3 - 1”之上。
http://blog.sina.com.cn/s/blog_3eb222740100krz3.html,若有侵权,实属抱歉,马上删除。

我是在研究这个思路的时候,突然想到加 2 刚好是角标,才那么写的,所以其实有很多方法,像上述,加4并且给3取余数之后,省下了0,1,2,这样更好,又可以写成一个新的数组角标,比我前面写的1 0 2 1 0数组更小了,也可以达到同样的效果。

这章更多是学习了字符数组,和多维字符数组的应用。

 

posted @ 2021-06-16 16:15  哿与银冰  阅读(345)  评论(0)    收藏  举报