本专栏为个人在华清远见嵌入式linux学习期间的笔记,希望能与各位读者共同进步!
前言
控制语句:
本次课对C语言中的重要知识数组、字符串及字符串的处理进行了系统和深入的讲解,继续对学员进行编程的强化训练。
一、数组
1.数组定义
构造数据类型之一
数组是具有一定顺序关系的若干个变量的集合,组成数组的各个变量称为数组的元素
数组中各元素的数据类型要求相同,用数组名和下标确定。数组可以是一维的,也可以是多维的。
所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。
数组中的特定元素可以通过索引访问,第一个索引值为 0。
2.一维数组的定义
所谓一维数组是指只有一个下标的数组。它在计算机的内存中是连续存储的。
C语言中,一维数组的说明一般形式如下:
<存储类型> <数据类型 > <数组名>[<表达式>];
例:
int a[10];
数组名表示内存首地址,是地址常量
sizof(数组名)是数组占用的总内存空间
编译时分配连续内存
内存字节数=数组维数*sizeof(元素数据类型)
注意事项
C语言对数组不作越界检查,使用时要注意!
int a[5];
a[5] = 10;//数组a只有a[0]到a[4]5个元素,但是给a[5]赋值,编译器不报错
关于用变量定义数组维数
int i = 15;
int a[i];
3.一维数组的引用
数组必须先定义,后使用
只能逐个引用数组元素,不能一次引用整个数组
数组元素表示形式:
数组名[下标]
其中:下标可以是常量或整型表达式
例
int a[10];
printf("%d", a);//错误,没有下标
for(j=0;j<10;j++)
printf("%d\t", a[j]); //正确
4.一维数组的初始化
初始化方式:在定义数组时,为数组元素赋初值
int a[5]={1,2,3,4,5};
说明
数组不初始化,其元素值为随机数
对static数组元素不赋初值,系统会自动赋以0值
只给部分数组元素赋初值
例子
static int a[5];
等价于:a[0]=0; a[1]=0; a[2]=0; a[3]=0; a[4]=0;
int a[5]={6,2,3};
等价于:a[0]=6; a[1]=2;a[2]=3; a[3]=0; a[4]=0;
int a[3]={6,2,3,5,1}; //错误 超出数组范围
int a[]={1,2,3,4,5,6};//编译系统根据初值个数确定数组维数
5.程序举例
冒泡排序
它重复地走访过要排序的数列,一次比较两个元素,如果顺序错误就交换。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
参考程序
#include <stdio.h>
int main(int argc, char *argv[])
{
int a[] = {3, 4, 17, 8, 31, 2, 9, 15}, n, i, j;
int t;
n = sizeof(a) / sizeof(int);
for (i = 0; i < n-1; i++) {
for (j = 0; j < n-1-i; j++) {
if (a[j] > a[j+1]){//0---
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
for (i = 0; i < n; i++)
printf("%d ", a[i]);
puts("");
return 0;
}
二、二维数组
1.二维数组的定义
定义方式:(声明时列数不能省略,行数可以)
数据类型 数组名[常量表达式][常量表达式];
例
int a[3][4];
float b[2][5];
int c[2][3][4];
元素个数=行数*列数
2.数组元素的存放顺序
原因:内存是一维的
二维数组:按行序优先存储
3.二维数组的理解
4.二维数组元素的引用
形式:
数组名[下标][下标]
5.二维数组元素的初始化
两种完整初始化形式:
1.分行初始化
int a[2][3] = {{1, 6, 9}, {2, 8, 5}};
2.按元素排列顺序初始化
int a[2][3] = {{1, 6, 9, 2, 8, 5};
不完整初始化形式:
6.多维数组
定义:具有两个或两个以上下标的数组称为多维数组。
int c[2][3][4];
7.程序举例
打印杨辉三角的前十行
杨辉三角,是二项式系数在三角形中的一种几何排列。
顶端为1,视为第0行;第1行两个1。除每行两端的数字,每个数字等于它左上方的数字加上右上方的数字。
例子
#include <stdio.h>
int main(int argc, char *argv[])
{
int a[10][10] = {{0}};
int i, j;
for (i = 0; i < 10; i++) {
a[i][0] = 1;
for (j = 1; j <= i; j++)
a[i][j] = a[i-1][j-1] + a[i-1][j];
}
for (i = 0; i < 10; i++) {
for (j = 0; j <= i; j++)
printf("%-8d ", a[i][j]);
putchar('\n');
}
return 0;
}
运行结果为
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
三、字符数组和字符串
1.字符数组
字符数组是元素的数据类型为字符类型的数组
char c[10],ch[3][4];
2.字符数组的初始化
字符数组的初始化有两种方式:
1.逐个字符赋值
char arr1[] = {'a', 'b', 'c'};
2.用字符串常量
char arr[] = "welcome";
注意!字符串常量赋值,会自动在最后一个元素加\0;
逐个字符赋值时,如果字符数组的元素个数大于赋给的元素个数,会在不够的元素位置赋值\0;
3.字符串
C语言中无字符串变量,用字符数组处理字符串
字符串结束标志:'\0'
拓展
'\0' NULL 0 都是0 只是用在不同的地方
'\0' 用在字符串
NULL 用在指针
0 用在数据
4.程序举例
输入一个字符串,然后将其逆序输出
字符串不便,逆序打印
#include <stdio.h>
#include <string.h> //strlen
#define N 20
int main(int argc, char *argv[])
{
//char arr[] = "welcome";
char arr[N] = {0};
int i, n;
printf("Please input a string:");
gets(arr);
n = strlen(arr); //计算字符串长度
for (i = n-1; i >= 0; i--)
putchar(arr[i]);
putchar('\n');
return 0;
}
字符串逆序存储,正序打印
#include <stdio.h>
#include <string.h>
#define N 20
int main(int argc, char *argv[])
{
char arr[N] = {0};
int i, j, n, ch;
printf("Please input a string:");
gets(arr);
n = strlen(arr);
i = 0;
j = n-1;
while (i < j) {
ch = arr[i];
arr[i] = arr[j];
arr[j] = ch;
i++;
j--;
}
puts(arr);
return 0;
}
四、字符串函数
1.字符串处理函数
C库中实现了很多字符串处理函数
#include <string.h>
几个常见的字符串处理函数
1.求字符串长度的函数 strlen
2.字符串拷贝函数 strcpy
3.字符串连接函数 strcat
4.字符串比较函数 strcmp
2.字符串长度函数strlen
格式:strlen(字符数组)
功能:计算字符串长度
返值:返回字符串实际长度,不包括‘\0’在内
\xhh表示十六进制数代表的符号
\ddd表示8进制的
例:对于以下字符串,strlen(s)的值为:
char s[10]={'A','\0','B','C','\0','D'};
char s[ ]="\t\v\\\0will\n";
char s[ ]="\x69\141\n";
答案:1 3 3
程序举例
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char s1[] = "\tab\nc\vd\\e";
char s2[]= "\x69\141";
printf("%d\n", strlen(s1));
printf("%d\n", sizeof(s1)/sizeof(char));
printf("\n%d\n", strlen(s2));
printf("%d\n", sizeof(s2)/sizeof(char));
puts(s2);
return 0;
}
运行结果
9
10
2
3
ia
3.字符串拷贝函数strcpy
格式:strcpy(字符数组1,字符串2)
功能:将字符串2,拷贝到字符数组1中去
返值:返回字符数组1的首地址
说明:
1.字符数组1必须足够大
2.拷贝时‘\0’一同拷贝
程序举例
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[])
{
char src[] = "makeru";
char dest[N];
strcpy(dest, src);
puts(src);
puts(dest);
return 0;
}
运行结果
makeru
makeru
4.字符串连接函数strcat
格式:strcat(字符数组1,字符数组2)
功能:把字符数组2连到字符数组1后面
返值:返回字符数组1的首地址
说明:
1.字符数组1必须足够大
2.连接前,两串均以’\0’结束;连接后,串1的’\0’取消,新串最后加’\0’
程序举例
#include <stdio.h>
#include <string.h>
#define N 100
int main(int argc, char *argv[])
{
char dest[] = "www.makeru";
char src[N] = ".com.cn";
strcat(dest, src);
puts(src);
puts(dest);
return 0;
}
运行结果
.com.cn
www.makeru.com.cn
5.字符串比较函数strcmp
格式:strcmp(字符串1,字符串2)
功能:比较两个字符串
比较规则:对两串从左向右逐个字符比较(ASCII码),直到遇到不同字符或‘\0’为止
返回值:返回int型整数
a. 若字符串1< 字符串2, 返回负整数
b. 若字符串1> 字符串2, 返回正整数
c. 若字符串1== 字符串2, 返回零
程序举例
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char s1[] = "ab";
char s2[] = "abc";
printf("%d\n", strcmp(s1, s2));
return 0;
}
运行结果
-1
五、字符串函数拓展
1.指定长度拷贝函数strncpy
strncpy(p, p1, n) 复制指定长度字符串
例子
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[])
{
char src[] = "makeru";
char dest[N] = ".com.cn";
strncpy(dest, src, 4);
puts(src);
puts(dest);
return 0;
}
运行结果
makeru
make.cn
2.指定长度连接函数strncat
strncat(p, p1, n) 附加指定长度字符串
例子
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[])
{
char src[] = "makeru";
char dest[N] = ".com.cn";
strncat(dest, src, 4);
puts(src);
puts(dest);
return 0;
}
运行结果
makeru
.com.cnmake
3.指定长度比较函数strncmp
strcasecmp(p, p1) 忽略大小写比较字符串
strncmp(p, p1, n) 比较指定长度字符串
例子
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[])
{
char s1[] = "QUIT";
char s2[] = "quit";
printf("%d\n", strncmp(s1, s2, 4));
printf("%d\n", strcasecmp(s1, s2));
return 0;
}
运行结果
-32
0
4.指定字符查找函数strchr与strrchr
C 库函数 char *strchr(const char *str, int c) 在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置。
char *strchr(const char *str, int c)
C 库函数 char *strrchr(const char *str, int c) 在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。
char *strrchr(const char *str, int c)
例子
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char s1[] = "abas$f$sf";
int ch;
ch = '$';
//printf("%p %p \n", s1, strchr(s1, ch));
//printf("%p %p \n", s1, strrchr(s1, ch));
printf("%d\n", strchr(s1, ch)-s1);
printf("%d\n", strrchr(s1, ch)-s1);
return 0;
}
运行结果
4
6
5.字符串查找函数strstr
C 库函数 char *strstr(const char *haystack, const char *needle) 在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 ‘\0’。
char *strstr(const char *haystack, const char *needle)
例子
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char s[] = "how are you";
char subs[] = "are";
printf("%d\n", strstr(s, subs)-s);
return 0;
}
运行结果
4
6.是否为字母检查函数isalpha
C 库函数 void isalpha(int c) 检查所传的字符是否是字母。
int isalpha(int c);
返回值
如果 c 是一个字母,则该函数返回非零值,否则返回 0。
7.是否为大写字母检查函数isupper
C 库函数 int isupper(int c) 检查所传的字符是否是大写字母。
int isupper(int c);
返回值
如果 c 是一个大写字母,则该函数返回非零值(true),否则返回 0(false)。
8.是否为小写字母检查函数islower
C 库函数 int islower(int c) 检查所传的字符是否是小写字母。
int islower(int c);
返回值
如果 c 是一个小写字母,则该函数返回非零值(true),否则返回 0(false)。
9.是否为数字检查函数isdigit
C 库函数 int isdigit(int c) 检查所传的字符是否是十进制数字字符。
十进制数字是:0 1 2 3 4 5 6 7 8 9
int isdigit(int c);
返回值
如果 c 是一个数字,则该函数返回非零值,否则返回 0。
例子
#include <stdio.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
int ch;
while ((ch = getchar()) != EOF) {
if (isalpha(ch)) {
if (isupper(ch))
printf("Upper:%c\n", ch);
if (islower(ch))
printf("Lower:%c\n", ch);
}
if (isdigit(ch))
printf("Digit:%d %c\n", ch-'0', ch);
putchar(ch);
}
return 0;
}
运行结果
输入7
7
Digit:7 7
7
输入c
c
Lower:c
c
输入大写Z
Z
Upper:Z
Z
输入ctrl + z
^Z //EOF
程序退出