c语言之数组与字符串
一、概述
- 一维数组
- 多维数组
- 字符数组和字符串
- 字符串函数
二、一维数组
(一)数组概述
- 构造数据类型之一
- 数组是具有一定顺序关系的若干个变量的集合,组成数组的各个变量称为数组的元素
- 数组中各元素的数据类型要求相同,用数组名和下标确定。数组可以是一维的,也可以是多维的
(二)一维数组的定义
所谓一维数组是指只有一个下标的数组。它在计算机的内存中是连续存储的。C语言中,一维数组的说明一般形式如下:
<存储类型> <数据类型 > <数组名>[<表达式>]
例如:int a[6]

注意:
- lC语言对数组不作越界检查
int a[5]; a[5] = 10
- 关于用变量定义数组维数
int i = 15; int a[i]
(三)一维数组的引用
- 数组必须先定义,后使用
- 只能逐个引用数组元素,不能一次引用整个数组
- 数组元素表示形式:数组名[下标]
其中,下标可以是常量或整型表达式。
#include <stdio.h>
int main(int argc, char *argv[]) {
int a[] = {1, 2, 3, 4, 5};
// printf("%d\n", a); error
for(int i = 1; i < 5; i++ ) {
printf("%d\n", a[i]);
}
return 0;
}
(四)一维数组的初始化
初始化方式:在定义数组时,为数组元素赋初值
int a[5]={1,2,3,4,5};
说明:
- 数组不初始化,其元素值为随机数
- 对static数组元素不赋初值,系统会自动赋以0值
- 只给部分数组元素赋初值(其余元素为0)
1、数组不初始化,其元素值为随机数
#include <stdio.h>
int main(int argc, char *argv[]) {
int a[5] = {};
for(int i = 0; i < 5; i++) {
printf("%d-%d\n", i, a[i]);
}
return 0;
}
/*
0--1210312096
1-134513963
2-1
3--1075583164
4--1075583156
*/
2、对static数组元素不赋初值,系统会自动赋以0值
#include <stdio.h>
int main(int argc, char *argv[]) {
static int a[5];
for(int i = 0; i < 5; i++) {
printf("%d-%d\n", i, a[i]);
}
return 0;
}
/*
0-0
1-0
2-0
3-0
4-0
*/
3、只给部分数组元素赋初值
#include <stdio.h>
int main(int argc, char *argv[]) {
int a[5] = {};
int b[5] = {1,2,3};
for(int i = 0; i < 5; i++) {
printf("a数组-%d-%d\n", i, a[i]);
}
for(int i = 0; i < 5; i++) {
printf("b数组-%d-%d\n", i, b[i]);
}
return 0;
}
/*
a数组-0-0
a数组-1-0
a数组-2-0
a数组-3-0
a数组-4-0
b数组-0-1
b数组-1-2
b数组-2-3
b数组-3-0
b数组-4-0
*/
(五)程序举例
冒泡排序:
它重复地走访过要排序的数列,一次比较两个元素,如果顺序错误就交换。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

代码:
#include <stdio.h>
int main(int argc, char *argv[]) {
int a[] = {38, 49, 76, 13, 27, 30, 97};
int i, j, n, temp;
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]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
for(i = 0; i < n-1; i++) {
printf("%d\n", a[i]);
}
return 0;
}
二、多维数组
(一)二维数组
1、概述
数据类型 数组名[常量表达式][常量表达式]
例如:
int a[3][4]
float b[2][5]
元素个数:行数 * 列数
注意:声明时列数不能省略,行数可以
二维数组的存放顺序是按照行序优先,因为内存是一维的

2、理解

3、元素的引用
- 形式:数组名[下标][下标]
- 二维数组元素的初始化
分行初始化
按元素排列顺序初始化

(二)多维数组
具有两个或两个以上下标的数组称为多维数组,如:int c[2][3][4]

(三)程序举例
1、打印杨辉三角
打印杨辉三角的前十行
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
....
代码:
#include <stdio.h>
/*
思路:
1、打印正方形
2、打印出一半(col <= row)
1 0
1 1 0
1 2 1
*/
int main(int argc, char *argv[]) {
int row, col;
int triangle[10][10] = {{0}};
for(row = 0; row < 10; row++) {
triangle[row][0] = 1; // 第一列设置为1
for(col = 1; col <= row ; col++) {
triangle[row][col] = triangle[row-1][col-1] + triangle[row-1][col];
}
}
for(row = 0; row < 10; row++) {
for(col = 0; col <= row; col++) {
printf("%d\t",triangle[row][col]);
}
putchar('\n');
}
return 0;
}
2、求数组元素最大值
有一个3×4的矩阵,要求输出其中值最大的元素的值,以及它的行号和列号。
#include <stdio.h>
int main(int argc, char *argv[]) {
int a[3][4] = {{1,22,56,2},{33,89,9,25},{31,10,3,8}};
int n, m, i, j, row, col;
n = sizeof(a) / sizeof(a[0]);
m = sizeof(a[0]) / sizeof(int);
row = 0;
col = 0;
for(i = 0 ;i < n; i++) {
for(j = 0; j < m; j++) {
if(a[i][j] > a[row][col]) {
row = i;
col = j;
}
}
}
printf("%d-%d-%d\n", row, col,a[row][col]);
return 0;
}
三、字符数组和字符串
(一)概述
字符数组是元素的数据类型为字符类型的数组。
char c[10], ch[3][4];
字符数组的初始化:
- 逐个字符赋值
- 用字符串常量
C语言中无字符串变量,用字符数组处理字符串
字符串结束标志:‘\0’
例1:
char ch[6]={“Hello”}; char ch[6]=“Hello”; char ch[]=“Hello”;
例 “hello”共5个字符,在内存占6个字节,字符串长度5

#include <stdio.h>
int main(int argc, char *argv[]) {
char arr1[] = {'a', 'b', 'c'};
char arr2[] = {'d', 'e', 'f'};
char arr3[] = {'a', 'b', 'c', '\0'};
char arr4[] = {'d', 'e', 'f', '\0'};
printf("arr1:%s %p\n", arr1, &arr1[2]);
printf("arr2:%s %p\n", arr2, arr2);
printf("arr3:%s %p\n", arr3, &arr3[2]);
printf("arr4:%s %p\n", arr4, arr4);
return 0;
}
/*
arr1:abcdefabc 0xbfff6730
arr2:defabc 0xbfff6731
arr3:abc 0xbfff6736
arr4:def 0xbfff6738
*/
例2:
char fruit[][7]={“Apple”,”Orange”,”Grape”,”Pear”,”Peach”};

#include <stdio.h>
int main(int argc, char *argv[]) {
char fruits[][20] = {"banana", "apple", "pear"};
int i, n;
n = sizeof(fruits) / sizeof(fruits[0]);
for(i = 0; i < n; i++) {
printf("%s\n", fruits[i]);
}
return 0;
}
/*
banana
apple
pear
*/
本质:
#include <stdio.h>
int main(int argc, char *argv[]) {
char fruits[][20] = {"banana", "apple", "pear"};
int i, j, n, m;
n = sizeof(fruits) / sizeof(fruits[0]);
m = sizeof(fruits[0]) / sizeof(char);
for(i = 0; i < n; i++) {
for(j = 0; j < m; j++) {
putchar(fruits[i][j]);
}
putchar('\n');
}
return 0;
}
(二)程序举例
逆序输出:输入一个字符串,然后将其逆序输出
- 方法1
#include <stdio.h>
#include <string.h>
#define N 20
int main(int argc, char *argv[]) {
char arr[N] = {0};
int i, n;
printf("Please input a string:");
// gets(arr);
scanf("%s", &arr);
n = strlen(arr);
for(i = n-1; i >= 0; i--) {
putchar(arr[i]);
}
putchar('\n');
return 0;
}
- 方法2
#include <stdio.h>
#include <string.h>
#define N 20
int main(int argc, char *argv[]) {
char arr[N] = {0};
int i, j, n, temp;
printf("Please input a string:");
// gets(arr);
scanf("%s", &arr);
n = strlen(arr);
i = 0;
j = n - 1;
while(i <= j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
printf("%s\n", arr);
return 0;
}
四、字符串函数
- 常用函数
- 其它函数
(一)常用函数
- 字符串长度的函数strlen
- 字符串拷贝函数strcpy
- 字符串连接函数strcat
- 字符串比较函数strcmp
1、字符串长度的函数strlen
- 格式:strlen(字符数组)
- 功能:计算字符串长度
- 返值:返回字符串实际长度,不包括‘\0’在内
- \xhh表示十六进制数代表的符号
- \ddd表示8进制的
例:对于以下字符串,strlen(s)的值为:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char s[10] = {'A','\0','B','C','D','\0','E'};
char s1[] = "\t\v\\\0we\n";
char s2[] = "\x69\141\n";
printf("s:%d,s1:%d,s2:%d\n", strlen(s), strlen(s1), strlen(s2));
return 0;
}
/*
s:1,s1:3,s2:3
*/
2、字符串拷贝函数strcpy
- 格式:strcpy(字符数组1,字符串2)
- 功能:将字符串2,拷贝到字符数组1中去
- 返值:返回字符数组1的首地址
说明:
- 字符数组1必须足够大
- 拷贝时‘\0’一同拷贝
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[]) {
char src[] = "hello";
char dest[N];
/*
strcpy(dest, src);
printf("%s\n", dest);
*/
int i, n;
i = 0;
n = sizeof(src) / sizeof(char);
while (i < n) {
dest[i] = src[i];
i++;
}
puts(dest);
return 0;
}
3、字符串连接函数strcat
- 格式:strcat(字符数组1,字符数组2)
- 功能:把字符数组2连到字符数组1后面
- 返值:返回字符数组1的首地址
说明:
- 字符数组1必须足够大
- 连接前,两串均以‘\0’结束;连接后,串1的 ‘\0’取消,新串最后加‘\0’
#include <stdio.h>
#include <string.h>
#define N 30
int main(int argc, char *argv[]) {
char s1[N] = {'A','B','\0'};
char s2[] = "Turbo", s3[]="";
strcpy(s1, s2);
strcat(s1, s3);
puts(s1);
return 0;
}
/*
Turbo
*/

4、字符串比较函数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[] = "abc";
char s2[] = "ad";
printf("%d\n", strcmp(s1, s2)); // -1
return 0;
}
(二)其它函数
- strncpy(p, p1, n) 复制指定长度字符串
- strncat(p, p1, n) 附加指定长度字符串
- strcasecmp(p, p1) 忽略大小写比较字符串
- strncmp(p, p1, n) 比较指定长度字符串
- strchr(p, c) 在字符串中查找指定字符
- strstr(p, p1) 查找字符串
#include <stdio.h>
#include <string.h>
#define N 10
int main(int argc, char *argv[]) {
char src[] = "world";
char dest[] = "HELLO";
// char usrc[] = "World";
//char ch = 'o';
char subs[] = "rld";
// strncpy(dest, src, 3);
// printf("%s\n", dest); // worLO
// strncat(dest, src, 3);
// puts(dest); // HELLOwor
// printf("%d\n", strcasecmp(src, usrc)); // 0
// printf("%d\n", strncmp(src, usrc, 3)); // 1
//printf("%d\n",strchr(src, ch)-src);
printf("%d\n",strstr(src, subs)-src);
return 0;
}