c语言-数组+字符串处理函数
一、构造类型
基本概念:
(1)在C语言中,变量类型除了几种基本类型之外,还有另外一些复杂类型,合称为构造类型。
(2)构造类型:是由基本类型构造而成的(如数组、结构体、共同体、枚举型)。
(3)构造类型的每一个分量是一个变量,它可以是一个简单类型或者构造类型。
(4)构造类型的分量的使用方法与简单变量相同
(5)构造类型的分量占用相邻的存储空间。
(6)对于构造类型的变量来说,重点是访问其分量的方法。
二、数组
数组概念:按序排列的具有相同类型的变量的集合
(1)用一符号名(数组名)来表示这一组数
(2)用数组名后跟下标来唯一地确定数组中的元素
(3)数组的首地址、数组元素的类型和个数(数组长度)
1、一维数组
(1)一维数组的定义
定义方式: 数据类型 数组名[常量表达式]
【1】数组的命名规则和简单变量名相同
【2】数组名后只能用方括弧括起来的常量表达式(常量和符号常量)
【3】常量表达式的值确定数组元素的个数(数组尺寸)
(2)一维数组的存储
c编译程序中用连续的内存单元存放 各个元素
保存数组所需内存量与数组元素的基本类型和数组大小有关
总字节数 = sizeof (基本类型) * 数组元素个数
(3)一维数组的引用
数组必须先定义,后引用
只能逐个引用数组元素,不能一次引用整个数组。
引用一维数组元素的一般形式: 数组名 [下标]
其中:下标可以是整型常量或整型表达式
int a[10]; printf(“%d”,a); //(错误) for(j=0;j<10;j++) printf(“%d\t”,a[j]); //(正确)
#include <stdio.h> void main() { int i,a[10]; for(i=0;i<=9;i++) a[i]=i; for(i=9;i>=0;i- -) printf(“%d”,a[i]); } //运行结果:9 8 7 6 5 4 3 2 1 0
eg:
(4)一维数组的初始化
【1】在定义数组时对数组元素赋初值
static int a[5]={1,2,3,4,5}; int a[5]={1,2,3,4,5}; //等价于:a[0]=1; a[1]=2; a[2]=3; a[3]=4; a[4]=5;
在定义数组时对数组元素赋初值
注:标准C只有静态存储(static)数组和外部存储(extern)数组才能初始化,但Turbo C和Microsoft C的编译系统中,中的数组与外部存储数组均可以进行初始化。
【2】给一部分元素赋初值
int a[5]={6,2,3}; //等价于: a[0]=6; a[1]=2;a[2]=3; a[3]=0; a[4]=0;
给一部分元素赋初值
注:对static数组不赋初值,系统会对所有数组元素自动赋以0值
【3】若对全部数组元素赋初值时,可以不指定数组长度
int a[]={1,2,3,4,5,6}; //自动定义数组长度为6
对全部数组元素赋初值
注意:编译系统根据初值个数确定数组大小,若被定义数组长度与提供初值的个数不相同,则数组长度不能省略。
【4】数组元素值全部为0
int a[5]={0,0,0,0,0}; int a[5]={0};
(5)相关例题
#include <stdlib.h> #include <stdio.h> void main() { int a[5] = { 1, 2, 3, 4, 5 }; int b[5] = { 1, 2, 3 }; int c[] = { 1, 2, 3, 4, 5 }; static int d[5]; int e[5]; int i; for (i = 0; i < 5; i++) printf("%d", a[i]);printf("\n"); for (i = 0; i < 5; i++) printf("%d", b[i]);printf("\n"); for (i = 0; i < 5; i++) printf("%d", c[i]);printf("\n"); for (i = 0; i < 5; i++) printf("%d", d[i]);printf("\n"); for (i = 0; i < 5; i++) printf("%d", e[i]);printf("\n"); system("pause"); }
数组的初始化
#include <stdlib.h> #include <stdio.h> void main() { int i; long int f1=1, f2=1; printf("%16ld%16ld", f1, f2); for (i = 2; i <= 0; i++) { f1 = f1 + f2; f2 = f2 + f1; printf("%16ld%16ld", f1, f2); if (i % 2 == 0) printf("\n"); } system("pause"); } //用数组方法 void main() { int i; static int f[20] = { 1, 1 }; for (i = 2; i <= 20; i++) f[i] = f[i - 2] + f[i - 1]; for (i = 0; i < 20; i++) { if (i % 4 == 0) printf("\n"); printf("%6d", f[i]); } system("pause"); }
用数组来求Fibonacci数列问题
#include <stdlib.h> #include <stdio.h> #define N 5 //简单变量实现 void main() { int i, sum = 0, high = 0,score; float average; printf("input everyone‘s scbre.\n"); for (i = 0; i < N; i++) { scanf_s("%d", &score); sum += score; if (score>high) high = score; } average = (float)sum / N; printf("average=%f\n", average); printf("highest=%d\n", high); system("pause"); } //用数组实现 void main() { int i, sum = 0, high, score[N]; float average; printf("input everyone‘s scbre.\n"); for (i = 0; i < N; i++) scanf_s("%d", &score[i]); for (high = score[0], i = 0; i < N; i++) { sum += score[i]; if (score[i]>high) high = score[i]; } average = (float)sum / N; printf("average=%f\n", average); printf("highest=%d\n", high); system("pause"); }
统计全班某门功课期末考试的平均分数和最高分数
#include <stdlib.h> #include <stdio.h> void main() { int x, n1=0, n2=0, n3=0, n4=0; printf("input number:"); scanf_s("%d",&x); while (x) { if (x == 1) n1 += 1; if (x == 2) n2 += 1; if (x == 3) n3 += 1; if (x == 4) n4 += 1; printf("input number:"); scanf_s("%d", &x); } printf("n1=%d n2=%d n3=%d n4=%d", n1, n2, n3, n4); system("pause"); } //用数组方法 void main() { static int x, n[9]; printf("input no.:"); scanf_s("%d", &x); while (x) { n[x] += 1; printf("input no.:"); scanf_s("%d", &x); } for (x = 1; x <= 8; x++) printf("\tno.%d= %d(票)\n", x, n[x]); if (x % 2 == 0) printf("\n"); system("pause"); }
统计选票,设候选人有4人,其编号1-4,约定0为统计结束标志
#include <stdlib.h> #include <stdio.h> #define N 10 void main() { int a[N + 1]; int i, j, t; printf("input 10 numbers: "); for (i = 1; i <= N; i++) scanf_s("%d", &a[i]); printf("\n"); for (j = 1; j < N;j++) for (i = 1; i <= N-j;i++) if (a[i]>a[i + 1]) { t = a[i]; a[i] = a[i + 1]; a[i + 1] = t; } printf("the sorted numbers:\n"); for (i = 1; i <= N; i++) printf("%d ", a[i]); system("pause"); }
用起泡法对6个数排序(由小到大)
ps:起泡法的思路是:将相邻两个数比较,将小的调到前头
1.要排序的数必须放入数组中
2.用二重循环控制排序过程
1)外循环j控制比较趟数(n-1趟)
2)内循环i控制一趟比较的次数(n-j次)
2、二维数组
在C语言中,数组的元素还可以是数组,这样就构成二维数组,所以二维数组可以看成是“数组的数组”,依此类推,还可以构成三维数组,思维数组(称多维数组)等等,二维数组是多维数组中最简单,最常用的数组,它代表多维数组的基本特征。
(1)二维数组的定义
定义方式: 类型说明符 数组名[常量表达式][常量表达式]
int a[3][4],b[4][M]; //M是符号常量 //注意不能写成下面情况 int a[3,4],b(4,M) //<--错误概念上可理解二维数组a[3][4]是一个3行4列的矩阵
(2)二维数组的存储
二维数组从概念上可理解为行-列矩阵,但存储器是一维的,需按一定规则转换,在内存中:二维数组中元素排列的顺序是——按行存放。
数组元素的实际存放顺序是右边下标比左边下标变化的快
(3)二维数组的引用
形式: 数组名[下标][下标]
注意:
【1】下标是整型或字符型的常量,变量或表达式。(定义时不能使用变量)如: a[1][2] a[i][j]
【2】数组元素可出现在表达式中,如: a[1][2]=a[2][2]/2
【3】使用数组元素时,应注意不要超出其定义的范围,即要注意数组定义和数组元素引用的区别。
如: int a[2][3]; a[2][3]=5; -->a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
(4)二维数组的初始化
【1】按存放顺序赋植
int x[2][3] = {1,2,3,4,5,6}; /*结果: x[0][0] =1 x[0][1] = 2 x[0][2] = 3 x[1][0] =4 x[1][1] = 5 x[1][2] = 6 */
【2】按行赋值
int x[2][3] = {{1,2,3},{4,5,6}}; /*结果: x[0][0] =1 x[0][1] = 2 x[0][2] = 3 x[1][0] =4 x[1][1] = 5 x[1][2] = 6 */
【3】部分赋值
static int x[2][3] = {1,2,4}; //以存放顺序赋值 /*结果: x[0][0] =1 x[0][1] = 2 x[0][2] = 4 x[1][0] =0 x[1][1] = 0 x[1][2] = 0 */ static int x[2][3] = {{1,2},{4}}; //以行赋值 /*结果: x[0][0] =1 x[0][1] = 2 x[0][2] = 0 x[1][0] =4 x[1][1] = 0 x[1][2] = 0 */ static int x[2][3] = {{6,2},{5,0,6}}; //以行赋值 /*结果: x[0][0] =6 x[0][1] = 2 x[0][2] = 0 x[1][0] =5 x[1][1] = 0 x[1][2] = 6 */
【4】省略第一维长度
static int x[][3] = {1,2,3,4,5,6,7}; /*结果: x[0][0] =1 x[0][1] = 2 x[0][2] = 3 x[1][0] =4 x[1][1] = 5 x[1][2] = 6 x[2][0] =7 x[2][1] = 0 x[2][1] = 0 */
注:不能省略第二维的长度
(5)二维数组程序举例
一般二维数组的处理用二重循环来实现,用循环变量的值控制数组元素的下标,外循环控制行,内循环控制列。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void main1() { int a[3][3], i, j; for (i = 0; i <= 2; i++) for (j = 0; j <= 2; j++) scanf("%d", &a[i][j]); for (i = 0; i <= 2; i++) { for (j = 0; j <= 2; j++) printf("%5d", a[i][j]); printf("\n"); } system("pause"); } /* 1 2 3 4 5 6 7 8 9 */ void main2() { int a[3][3], i, j; for (i = 0; i <= 2; i++) for (j = 0; j <= 2; j++) scanf("%d", &a[j][i]); for (i = 0; i <= 2; i++) { for (j = 0; j <= 2; j++) printf("%5d", a[i][j]); printf("\n"); } system("pause"); } /* 1 4 7 2 5 8 3 6 9 */ void main3() { int a[3][3], i, j; for (i = 0; i <= 2; i++) for (j = 0; j <= 2; j++) scanf("%d", &a[i][j]); for (i = 0; i <= 2; i++) { for (j = 0; j <= 2; j++) if ((i+j)%2) //2 4 6 8 //if ((i+j)%2==0) //1 3 5 7 9 printf("%5d", a[i][j]); printf("\n"); } system("pause"); } void main4() { int a[3][3], i, j; for (i = 0; i <= 2; i++) for (j = 0; j <= 2; j++) scanf("%d", &a[i][j]); for (i = 0; i <= 2; i++) { printf("%5d", a[i][i]); //1 5 9 //printf("%5d", a[i][i]); //7 5 3 } system("pause"); } //下三角 void main5() { int a[3][3], i, j; for (i = 0; i <= 2; i++) for (j = 0; j <= 2; j++) scanf("%d", &a[i][j]); for (i = 0; i <= 2; i++) { for (j = 0; j <= i; j++) printf("%5d", a[i][j]); printf("\n"); } system("pause"); }
1、二维数组的输入与输出
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void main() { static int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; static int b[3][2], i, j; printf("array a:\n"); for (i = 0; i <= 1; i++) { for (j = 0; j <= 2; j++) { printf("%5d", a[i][j]); b[j][i] = a[i][j]; } printf("\n"); } printf("array b:\n"); for (i = 0; i <= 2; i++) { for (j = 0; j <= 1; j++) { printf("%5d", b[i][j]); } printf("\n"); } system("pause"); } /* //对于n*n的二维数组,可以在同一个数组进行矩阵转置操作 #define N 3 void main() { static int a[N][N] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} }; int i, j; printf("原矩阵:\n"); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%5d", a[i][j]); } printf("\n"); } //进行转置操作 int t; for (i = 0; i < N; i++) for (j = 0; j < i; j++) { t = a[i][j]; a[i][j] = a[j][i]; a[j][i] = t; } printf("转置后的矩阵:\n"); //打印转置后的矩阵 for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%5d", a[i][j]); } printf("\n"); } system("pause"); } //对称于主对角线的元素进行两两交换 void main() { static int a[N][N] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; int i, j; printf("原矩阵:\n"); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%5d", a[i][j]); } printf("\n"); } //对称于主对角线的元素进行两两交换 int t; for (i = 0; i < N; i++) for (j = 0; j < i; j++) { if (i > j) { t = a[i][j]; a[i][j] = a[j][i]; a[j][i] = t; } } printf("转置后的矩阵:\n"); //打印转置后的矩阵 for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%5d", a[i][j]); } printf("\n"); } system("pause"); } */
2、将一个二维数组行和列元素互换,存到另一个二位数组中(转置)
转置的算法:
1.a数组初始化(或赋值)并输出
2.用二重循环进行转置
b[j][i]=a[i][j]
3.输出b数组
3、字符数组
(1)字符数组的定义
在C语言中,没有专门的字符串变量,而是将字符串存入字符数组来处理,即用一个一维数组来存放一个字符串,每个元素存放一个字符,字符数组是数组的一个特殊情况,它的定义方法与一般的数组类似,引用方法可以相同,但也有其独特的引用方法。
形式: char 数组名[常量表达式] 一维字符数组:存放一个字符串(每个数组元素存放一个字符)
char 数组名[常量表达式][常量表达式] 二维字符数组:存放多个字符串(行数是字符串的个数)
常量表达式:整数、字符、符号常量
注:可以用整型数组存放字符型数据,但浪费存储空间
(2)字符数组的初始化
【1】按元素赋值
static char c[10]={‘s‘,‘t‘,‘o‘,‘r‘,‘e‘}; //c[0] c[1] c[2] c[3] c[4] c[5] c[6] c[7] c[8] c[9]
注:
[1] static char c[10]; 则c[0]……c[9]初值均为‘\0’。 但若 char c[10]; 则c[0]……c[9]初值是未知的
[2] 在C语言中,将字符串作为字符数组来处理,即用一个一维数组来存放一个字符串。
[3] 为了测定实际字符串长度,C语言规定了一个“字符串结束标志”,即‘\0’。即遇到字符 ‘\0’时,表示字符串结束。
【2】使用字符串常量给字符数组赋初值
char c[6]={"china"}; char c[6]="china"; char c[]="china"; //结果 c[0] c[1] c[2] c[3] c[4] c[5]
注:以字符串方式赋值时,必须保证数组元素个数>=字符个数+1(字符串后面自动加上一个‘\0’)
数组初始化后,剩余的元素均为\0
数组未初始化,则static数组 元素的值为\0,否则元素值是随机的
#define _CRT_CECRUE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void main() { char a[7] = { ‘a‘, ‘p‘, ‘p‘, ‘l‘, ‘e‘ }; char b[7] = { "apple" }; char c[7]; static char x[7]; int i; for (i = 0; i < 7; i++) printf("%5d %5d %5d %5d\n", a[i], b[i], c[i], x[i]); system("pause"); } /* 97 97 -52 0 112 112 -52 0 112 112 -52 0 108 108 -52 0 101 101 -52 0 0 0 -52 0 0 0 -52 0 */
字符数组初始化
#define _CRT_CECRUE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void main() { char str[] = "This is a string!"; int i = 0; while (str[i] != ‘\0‘) { printf("%c=%d\n", str[i], str[i]); i++; } printf("%c=%d\n", str[i], str[i]); system("pause"); } /* T=84 h=104 i=105 s=115 =32 i=105 s=115 =32 a=97 =32 s=115 t=116 r=114 i=105 n=110 g=103 !=33 =0 */
用一字符串给字符数组赋初值,然后打印出各元素的ASCII编码值
注:[1] 用字符串给字符数组赋初值,系统自动加上空字符‘\0’(终结符)
[2] ‘ ’——空格字符,ASCII编码值为32
[3] ‘\0’——空字符,ASCII编码值为0
[4] 两者均无法直接打印
(3)字符串的引用与输入输出
对于字符数组,在程序中既可以逐个引用字符串中的单个字符(数组元素),也可以一次引用整个字符串(数组)
【1】逐个字符数组元素输入输出:用%c格式符描述
scanf("%c",&a[i]); printf("%c%c%c",a[0],a[1],a[2]);
【2】整个字符串(数组)输入输出:用%s格式符描述
char a[]="china"; scanf("%s",a); printf("%s",a); //用%s输出,无论数组元素有多少个只要遇到"\0"便结束。
char star[3][4]={{"*"},{"**"},{"***"}}; print("%s\n%s\n%s\n",star[0],star[1],star[2]); /*运行结果: * ** *** */ //%s要求的是地址:对一维数组,数组名就是地址,对二维数组,只写行下标时是地址。
其它注意事项:
0_1>数组中有多个‘\0’时, 遇第一个结束
#include <stdio.h> void main() { char a[ ]={‘h‘,‘e‘,‘l‘,‘\0‘,‘l‘,‘o‘,‘\0‘}; printf("%s",a); } //输出:hel
0_2>scanf中%s输入时,用字符数组名,不要加&,遇空格或回车结束,自动加‘\0’
输入数据:how are you? char str1[5],str2[5],str3[5]; scanf("%s%s%s",str1,str2,str3); //注:用%s输入时,遇空格或回车便认为一个字符结束 等价于《==》 char s[3][5]; scanf("%s%s%s",&s[0][1],&[1][0],&[2][0]); printf("%s\t%s\t%s\n",s[0],s[1],s[2]);
#include <stdio.h> void main() { char a[15],b[5],c[5]; scanf("%s%s%s",a,b,c); printf("a=%s\nb=%s\nc=%s\n",a,b,c); scanf("%s",a); printf("a=%s\n",a); } /* 运行情况: 输入:How are you? 输出:a=How b=are c=you? 输入:How are you? 输出:a=How */
三、字符串处理函数
1、gets(字符数组名)
从键盘输入一个字符串(以回车结束)放到数组中,并且得到一个函数值,该函数值是字符数组的起始地址
如:get (str)
2、puts(字符数组名/字符串)
将数组中的字符串(以‘\0’结束的字符序列)输出到终端上,输完换行
puts (str); <=> printf("%s\n",str); puts("ok!"); <=> printf("%s\n","ok!"); <=> printf("ok!\n");
3、strcpy(字符数组1,字符串 / 字符数组2)
将字符串 / 字符数组2的字符串拷贝到字符数组1中
注:
(1)字符数组1的长度 >= 字符数组2(字符串)的长度
(2)拷贝时连同‘ \0 ’一起拷贝
(3)不能把字符串或字符数组直接赋给一个字符数组
char str[6]; str[0]=‘c‘; str[1]=‘i‘; strcpy(str,"china"); //用strcpy可以把一个数组赋给另一个数组
4、strcat(字符数组1,字符串/字符数组2)
将字符串或字符数组2,连接到字符串1的后面,并放在字符数组1中
main() { char str1[40],str2[10],str3[10]; gets(str1); gets(str2); gets(str3); strcat(str1,str2); strcat(str1,str3); printf(str1); }
注:数组1要足够大
5、strcmp(字符数组1 / 字符串1,字符数组2 / 字符串2)
功能:比较两个字符串,1>2->正数,1=2->0,1<2->负数
注意:对两个字符串的比较,不能用以下形式(str1==str2或str1>str2或str1<str2)
只能用 strcmp(str1,str2) >0 或 ==0 或 <0来判断
#define _CRT_CECRUE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> void main() { char s1[40], s2[40]; int i; printf("输入字符串s1:"); gets(s1); printf("输入字符串s2:"); gets(s2); i = strcmp(s1, s2); if (i == 0)printf("输入的两字符串相等。"); else if (i > 0)printf("输入的字符串s1大于s2。"); else printf("输入的字符串s1小于s2。"); system("pause"); }
strcmp
# 字符串的拷贝、连接、比较都必须用函数
6、strlen(字符数组名 / 字符串)
测试字符串长度(不含 ‘ \0 ’)
strlen("china"); //值为5
#define _CRT_CECRUE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> void main() { char s[40]; int i; printf("enter a string!\n"); gets(s); i = strlen(s); printf("string length=%d\n",i); for (; i >= 0; i--) putchar(s[i]); system("pause"); } /* 输入:abcdefg12345 输出:string length=12 54321gfedcba */
测字符串长度,并倒序输出
7、strlwr(字符串)
将字符串中大写字母转换成小写字母
8、strupr(字符串)
将字符串中小写字母转换成大写字母
四、字符数组应用举例
/*设:字符串用str【100】存放,单词计数器位num 算法: 1、输入字符串 2、找第一个非空字符串 3、记数 4、跳过本单词,即寻找空格或 ‘\0‘ 5、未结束则转 2 6、否则打印个数 */ #define _CRT_CECRUE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> void main() { int num = 0, i = 0; char str[100], c; gets(str); do { while ((c = str[i]) == ‘ ‘) i++; if (c != ‘\0‘) num++; while ((c = str[i]) != ‘ ‘ && c != ‘\0‘) i++; } while(c!=‘\0‘); printf("number of word:%d\n", num); system("pause"); }
1、输入一行字符,统计其中有多少个单词(空格分隔)
/* 算法: 1、输入str1和str2 2、找到str1的结束标志\0 3、将str2的字符逐个放入str1当前位置开始的地方 */ #define _CRT_CECRUE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> void main() { int i = 0, j = 0; char str1[100], str2[100]; puts("输入两个字符串:"); gets(str1); gets(str2); while (str1[i] != ‘\0‘) i++; while ((str1[i++] = str2[j++]) != ‘\0‘) ; printf("结果为:%s\n", str1); system("pause"); } /* 输入两个字符串: ABC 12345 xyz 结果为:ABC 12345xyz */
2、编程实现strcat功能
#define _CRT_CECRUE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #define NUM 10 void main() { int i, j; char name[NUM][10], stmp[10]; float score[NUM], tmp; printf("输入姓名和成绩:\n"); for (i = 0; i < NUM; i++) scanf("%s%f", name[i], &score[i]); for (i = 0; i < NUM-1;i++) for (j = i+1; j < NUM;j++) if (score[i] < score[j]) { tmp = score[i]; score[i] = score[j]; score[j] = tmp; strcpy(stmp, name[i]); strcpy(name[i], name[j]); strcpy(name[j], stmp); } printf("排序为:\n"); for (i = 0; i < NUM; i++) printf("%-10s%f\n", name[i], score[i]); system("pause"); }
3、选修某课程的学生共10人,按成绩高低输出学生名单(用比较法排序)