经过再三思考觉得今天就写一篇关于数组与字符串相关的文章吧!其中字符串主要通过练习来巩固知识亦或是获得新知识。好接下来将进行我们的学习时刻了。
首先我们来思考一个问题,你真的了解数组的数组名吗?数组名真的就单单一个名字而已吗?接下来我们慢慢探索。
数组名的真正意义
我们看一段代码
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() { int arr[10] = { 1,2,33,44,55,66,7,8,99,0 }; int* p = arr; int* q = &arr; int* d = &arr[0]; printf("%p\n", p); printf("%p\n", q); printf("%p\n", d); return 0; }
大家可以思考一下打印的结果会一样的吗?结果如下:
打印的结果是一样的,那这代表着什么呢?
其实数组的一个数组地址也可以用,数组首元素地址来代表,所以上述中 q 和 d 的打印结果一样我们可以理解,那数组名呢?难道说数组名也是代表整个数组的地址吗?
我们再看一段代码。
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() { int arr[10] = { 1,2,33,44,55,66,7,8,99,0 }; int* p = arr; int* q = &arr; int* d = &arr[0]; printf("%d\n", sizeof(arr)); printf("%d\n", sizeof(&arr)); printf("%d\n", sizeof(arr[0])); return 0; }
现在咋一看是不是又发现他们的有所不同的呢?他们的字节大小是不一样的。其中sizeof(arr[0])4个字节很好理解就是int类型的整形占4个字节,那sizeof(&arr)我们也容易弄明白,&arr就是一个地址嘛,地址的大小在64位机器下占8个字节,所以这里打印8,那为啥sizeof(arr)的结果为40呢?仔细一想40个字节不就是整个数组的字节大小嘛,所以这里arr代表的是整个数组。
结论: 其实在C语言中数组名,一般情况下确实可以认作数组首元素的地址,除了在sizeof(数组名)中代表整个数组。
竟然这样那我们以前写冒泡排序都是传数组名,形参也用数组形式来接收,那现在直到数组名代表首元素地址,那是否可以用指针形式来接收呢,答案是可以的。
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> void Sort(int* p) { int tem = 0; int i = 0; int j = 0; for (i = 0; i < 10; i++) { for (j = 0; j < 10 - 1 - i; j++) { if (*(p + j) > *(p + j + 1)) { tem = *(p + j); *(p + j) = *(p + j + 1); *(p + j + 1) = tem; } } } } int main() { int arr[10] = { 1,2,33,44,55,66,5,3,90,10 }; Sort(arr); for (int i = 0; i < 10; i++) { printf("%d ", arr[i]); } return 0; }
数组与指针
我们看一段代码:
#include <stdio.h> int main() { char str1[] = "you are happy."; char str2[] = "you are happy."; char *str3 = "you are happy."; char *str4 = "you are happy."; if(str1 == str2) printf("str1 and str2 are same\n"); else printf("str1 and str2 are not same\n"); if(str3 == str4) printf("str3 and str4 are same\n"); else printf("str3 and str4 are not same\n"); return 0; }
仔细观察,你们觉得打印的结果又是怎样呢?
是不是看到答案又是一头雾水呢?
这里就要讲到数组和指针的关系了,经过上面的结论,你是不是觉得好像数组和指针也没啥区别嘛,其实不然。在这里我们要知道,数组和指针是有区别的。数组就是数组,指针就是指针。在上面的代码中,其实str1和str2是两个不同的数组,所以他们进行判断str1是否等于str2时,也是比较首元素地址是否相等,从结果上看显然是不相等的,因为两个数组都在栈区中有着属于自己的空间。但str3和str4为什么相等呢,其实str3和str4这样子赋值,就是将字符”y“的首地址放入str3和str4中,但要注意的是此时的他们相当于一个字符常量,是属于代码块中的常量,所以str3和str4共同指向代码块中代表首字符”y“的地址,故 str3 等于 str4 .
接下来就看一道数组题,巩固巩固吧。
写出一个杨辉三角形
毕竟练手,我这里就写了一个6行的杨辉三角。
#include <stdio.h> main() { static int a[6][6]; int i, j, k; for (i = 0; i < 6; i++) { for (k = 0; k < 12 - 2 * i; k++) printf(" "); for (j = 0; j <= i; j++) { if (j == 0 || j == i) a[i][j] = 1; else a[i][j] = a[i - 1][j - 1] + a[i - 1][j]; printf(" "); printf("%-3d", a[i][j]); } printf("\n"); } }
思路:
我们都知道杨辉三角的两边都是1,所以我们在这里只要控制在i==就,和j等于0时,打印1即可,到后面我们根据杨辉三角的特性得出 a[i][j] = a[i - 1][j - 1] + a[i - 1][j];,就很容易写出来了,唯一需要注意的是打印前方的空格需要根据打印的行数而改变。
————————————————
字符串练习巩固
来看一道开胃菜
写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串。
题目:给定s1 =AABCD和s2 = BCDAA,返回1
给定s1=abcd和s2=ACBD,返回0.
AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA
AABCD右旋一个字符得到DAABC
首先通过审题这里判断两个字符串中的一个,是否由另一个通过旋转得到,那意思就是它旋转的字符个数我们也是不知道的,那就需要我们一一尝试出来了。下面是展示参考答案:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> int Find(char* p, char* q,int n) { int i = 0; int j = 0; char tem = 0; for (i = 0; i < n; i++) { for (j = 0; j < n-1; j++) { tem = p[j]; p[j] = p[j + 1]; p[j + 1] = tem; } if (strcmp(p, q)==0) { return 1; } } return 0; } int main() { char str1[] = "abcdefg"; char str2[] = "cdefgab"; char str3[] = "qwehhrl"; char str4[] = "qwerrjl"; if (Find(str1,str2,7)) { printf("str2是str1通过旋转得到\n"); } else printf("str2不是str1通过旋转得到\n"); if (Find(str3,str4,7)) { printf("str4是str3通过旋转得到\n"); } else printf("str4不是str3通过旋转得到\n"); return 0; }
具体思路:
因为我们需要逐一排查第二个字符串是否是由第一个字符串旋转而来又或者旋转几位字符而来,所以我们的函数Find 中需要一个一个逐一去旋转,直到完成一次轮回,每旋转一次都对旋转后的p与q 进行比对是否是旋转得到。这里的 n 为 字符串中字符的个数-1(减去末尾的'\0') 。
如何得到旋转的字符串:
我们只需用辅助变量tem储存当前字符串中的第一个字符,然后将后面的字符往前推动一位,最后在最后一位在赋值为tem即可。
接下来我们看一下最后一道题:
题目:编写一个程序,从键盘接收一个字符串,然后按照字符顺
序从小到大进行排序,并删除重复的字符。
这么一看你是否有那么一点思路了呢?
接下来我们直接参考一下答案:
#include <stdio.h> #include <string.h> void main() { char str[100], * p, * q, * r, c; printf("输入字符串:"); gets(str); for (p = str; *p; p++) { for (q = r = p; *q; q++) if (*r > *q) r = q; if (r != p) { c = *r; *r = *p; *p = c; } } for (p = str; *p; p++) { for (q = p; *p == *q; q++); strcpy(p + 1, q); } printf("结果字符串:%s\n\n", str); }
具体思路:首先我们创建一个数组和几个指针 ,数组用来接收键盘的字符串,其余指针用作辅助作用,首先代码前面我们进行字符排序,就简单的比较字符大小后通过辅助变量进行交换。后半代码则是删除掉重复的代码,这里需要进行两次循环,我们重p中一个一个字符进行排查,注意这里的第二个for循环后直接接 分号,只是让找出*p==*q时的地址,在通过库函数strcpy进行拷贝即可。
今天文章到此结束。