C语言教程笔记
十九. 初识数组
1. 什么是数组?
数组由一系列类型相同的数据对象依次排列组成。 组成数组的数据对象被称作数组的元素。
数组的两个重要注意点:
- 依次排列:每个数组元素都是相邻的,从第一个数组元素到最后一个数组元素依次摆放。
- 类型相同:数组的元素都是类型相同的数据对象,不同的数据对象不能组成数组。
2. 如何声明数组
我们可以用如下的代码,声明各种类型的单个变量。
char c;
int n;
long l;
float f;
double df;
既然数组是由一系列类型相同的数据对象依次排列组成。那么声明数组至少要提供三类参数。
- 数组名。
- 数组元素的类型。
- 数组元素的数量。
数组声明的公式:
数组的声明由数组名、元素类型、元素数量组成,例如:
char c[5];
int n[10];
long l[3];
float f[2];
double df[1];
3. 数组内容的初始化
3.1 初始化与赋值的区别
在变量声明的时候,我们讨论过初始化和赋值的区别。
int n = 100; // 初始化为100
n = 100; // 赋值为100
第一行代码为声明int类型的变量n,并初始化为100。第二行代码为n赋值为100。
初始化与赋值的区别在于:
初始化时,等号的左边为变量的声明,等号的右边为值。
赋值时,等号的左边为变量,等号的右边为值。
初始化中的等号并不是赋值运算符,只是写作等号而已。
不能对一个变量多次初始化,会被认为变量被重复定义。
int n =100;
int n = 123; // 错误,会引发变量重定义
对一个变量重复赋值却没有问题。
int n;
n = 123;
n = 456;
对于基础类型,似乎赋值与初始化都是将一个值装入变量,没有特别明显的差异。而对于我们接下来要讨论的数组,却有一些差异。
3.2 数组的初始化
数组初始化如同基础数据类型初始化一样,也是在变量声明时加上等号,在等号右边写需要为数组初始化的值。
例如:
int arr[10] = {1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 0};
上面的代码能声明一个由 10 个 int 数据对象组成的数组,并且将它们分别初始化为1,2,3,4,5, 6,7,8,9,0。
3.3 初始化列表
数组初始化时,等号右边被称作初始化列表。 初始化列表写明数组的元素分别需要被初始化为何值,用逗号隔开,最后用花括号包括起来。
int arr[10] = {1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 0};
上面这样将10个元素分别初始化为1,2,3,4,5,6,7,8,9,0。
3.3.1 初始化列表短于数组长度
int arr[10] = {1, 2 ,3 ,4 ,5};
现在数组有10个元素,而初始化列表只指定了5个元素的值。那么剩下的元素将被填0。
int arr[10] = {};
初始化列表什么都没有,所有数组元素将被填0。
3.3.2 初始化列表长于数组长度
int arr[10] = {1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 10, 11};
初始化列表长于数组长度,剩下的11将不知道初始化给哪个元素,代码将无法编译通过。
3.3.3 让初始化列表决定数组长度
int arr[] = {1726, 838, 938, 138, 58, 82, 83, 343, 456, 534, 645, 8938, 9382, 83, 343};
如果你有多个数值需要初始化给数组,但是你懒得数清楚到底有多少个。可以在数组声明的方括号里什么都不填,这样将会让初始化列表决定数组的长度。
4. 访问数组的元素
4.1 访问数组元素的公式
数组被初始化好了,现在我们想访问这个数组的各个元素了。
访问数组指定元素的公式如下:
使用 数组名[下标] 的形式可以访问数组内的元素。
请特别注意,下标从0开始。
0为下标,访问到的是数组的第一个元素。目前请先把下标从0开始看做一个规则。
#include <stdio.h>
int main()
{
int arr[10] = { 1, 2 ,3 ,4 ,5 ,6, 7, 8, 9, 0 };
printf("%d\n", arr[0]); // 第1个元素
printf("%d\n", arr[1]); // 第2个元素
printf("%d\n", arr[2]); // 第3个元素
printf("%d\n", arr[3]); // 第4个元素
printf("%d\n", arr[4]); // 第5个元素
printf("%d\n", arr[5]); // 第6个元素
printf("%d\n", arr[6]); // 第7个元素
printf("%d\n", arr[7]); // 第8个元素
printf("%d\n", arr[8]); // 第9个元素
printf("%d\n", arr[9]); // 第10个元素
return 0;
}
4.2 使用循环遍历数组元素
由于数组下标是递增的,使用 for 循环将更加便利地访问每一个元素。
for(int i = 0; i < 10; i++)
{
printf("%d\n", arr[i]); // 访问下标为i的元素
}
在for循环中, i 将从0递增到9。使用 arr[i] ,即可访问下标从0到9的元素。
当然,while循环也同样能做到,不过for循环代码将更加紧凑一些。
int i = 0;
while(i < 10)
{
printf("%d\n", arr[i++]); // 访问下标为i的元素
}
这里特别将 i++ 放入了函数调用当中。表达式 i++ 的结果为 i 当前的值,所以第一次求 i++ 的结果为 0。而后缀自增表达式会在稍后为 i 加1。这样写也能达到访问下标0到9的元素的效果。
如果你想, i++ 写在单独的一行也没问题的。
int i = 0;
while(i < 10)
{
printf("%d\n", arr[i]); // 访问下标为i的元素
i++;
}
4.3 修改数组元素的值
怎样修改数组元素呢?
int arr[10] = {}; // 所有元素均初始化为0
printf("%d\n", arr[5]); // 打印第6个元素的值
arr[5] = 123; // 将第6个元素赋值为123
printf("%d\n", arr[5]); // 打印第6个元素的值
使用赋值表达式:
数组名[下标] = 表达式;
可以为数组元素赋值为一个新值。
4.4 小心数组越界
如果数组只有10个元素,我们访问或修改了这10个元素以外的元素,那么结果是未定义的。这意味着程序看上去可以运行,但是运行的结果很怪,或异常终止。
警告:千万不要越界访问或修改数组元素。
C语言编译器不会检查数组是否越界了,所以在编译时无法发现这样的问题。
int arr[10] = {}; // 所有元素均初始化为0
printf("%d\n", arr[10]); // 下标为0到9,访问下标10的元素属于越界访问。
如果使用循环来遍历数组,请特别注意循环条件。
for(int i = 0; i <= 10; i++)
{
printf("%d\n", arr[i]); // 访问下标为i的元素
}
循环条件为 i <= 10 ,这意味着 i 可以为10。这样也将导致数组越界访问。
4.5 如果不初始化会怎样
#include <stdio.h>
int main()
{
int arr[10];
for(int i = 0; i < 10; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}
程序打印的结果均是一些奇怪的值,未初始化的数组里面都是一些无意义的数值。
数组不一定要初始化,就像不初始化变量一样。如果不初始化变量,我们往往会在其后为其赋值。数组也是一样的,其后为其元素赋值,避免使用到无意义的数值。
#include <stdio.h>
int main()
{
int arr[10];
int n = 0;
for(int i = 0; i < 10; i++)
{
arr[i] = n;
n = n + 2;
}
for(int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
5. 数组所占用的空间大小
char arr1[10];
short arr2[10];
int arr3[10];
long long arr4[10];
float arr5[10];
double arr6[10];
printf("%d\n", sizeof(arr1));
printf("%d\n", sizeof(arr2));
printf("%d\n", sizeof(arr3));
printf("%d\n", sizeof(arr4));
printf("%d\n", sizeof(arr5));
printf("%d\n", sizeof(arr6));
数组所占的空间 = 单个元素所占空间大小 * 数组元素个数
sizeof(arr1) = sizeof(char) * 10 = 10
sizeof(arr2) = sizeof(short) * 10 = 20
sizeof(arr3) = sizeof(int) * 10 = 40
sizeof(arr4) = sizeof(long long) * 10 = 80
sizeof(arr5) = sizeof(float) * 10 = 40
sizeof(arr6) = sizeof(double) * 10 = 80
6. 数组能整体赋值吗
int arr1[5] = {};
int arr2[5] = {1, 2, 3, 4, 5};
arr1 = arr2;
第一个数组元素全部初始化为0,第二数组元素初始化为1,2,3,4,5。 我们可以使用赋值运算符让arr1赋值为arr2吗?
答案是不行的,这种写法无法通过编译。
那么重新初始化呢?
arr1 = {1, 2, 3, 4, 5};
这样也是不行的,初始化列表只能存在于初始化中。
这里也是赋值与初始化区别的一个体现,在数组初始化中可以使用初始化列表,而赋值不行。
6.1 使用循环,单个为元素赋值
虽然无法整体为数组赋值,但是使用循环,单个为元素赋值确是可以的。
int arr1[5] = {};
int arr2[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++)
{
arr1[i] = arr2[i];
}
6.2 内存复制
#include <stdio.h>
#include <memory.h>
int main()
{
int arr1[5] = {};
int arr2[5] = {1, 2, 3, 4, 5};
memcpy(arr1, arr2, sizeof(arr1));
for (int i = 0; i < 5; i++)
printf("%d ", arr1[i]);
return 0;
}
另外,我们还可以借助 memcpy函数 (memory copy的简写),将arr2数组的数据复制到arr1数组。
memcpy的第一个参数是目标数组名。
memcpy的第二个参数是原始数组名。
memcpy的第三个参数指明需要复制多少字节数据。
memcpy函数将会把arr2数组的数据复制到arr1数组,复制多少字节数据取决于第三个参数。
注意事项:设第三个参数,需要复制的字节数为N。
- sizeof(arr2)不能小于N,否则复制完arr2的数据后,将复制到无意义内容。
- sizeof(arr1)不能小于N,否则将没有足够空间存放数据。
- 要使用memcpy函数,需要包含头文件 memory.h 。
#include <stdio.h>
#include <memory.h>
int main()
{
int arr1[3] = {};
int arr2[5] = {1, 2, 3, 4, 5};
memcpy(arr1, arr2, sizeof(int) * 2);
for (int i = 0; i < 3; i++)
printf("%d ", arr1[i]);
return 0;
}
上面的代码没有问题,将仅复制arr2中的sizeof(int) * 2字节数据到arr1。 也就是说,仅会将arr2中前2个int元素的数据复制到arr1。 而arr1可以容纳3个int,有足够的空间存放数据。
二十. 多维数组
1. 数组作为数组的元素
有一个数组A,它的元素为 int 类型,元素数量为10个。 另外有一个数组B,它的元素类型为包含10个int元素的数组,元素数量为5个。
数组A已经在上一节中充分讨论过了, int A[10] 可以声明一个这种类型的数组。 但是,怎样声明数组B这种类型的数组呢?
让我们再回顾一下数组声明的公式:
数组的声明由数组名、元素类型、元素数量组成。 下面我们来尝试写一个数组B的声明。
- 数组名:B
- 元素类型:int[10]
- 元素数量: 5 组合这3个要素,写出如下声明
int[10] B[5];
数组名左边的方括号都移到最右边来。
int B[5][10];
这样就是B数组的声明了。B数组含有5个元素,而每个元素都是含有10个int元素的数组。
2. 二维数组
访问数组指定元素的公式如下:
使用 数组名[下标] 的形式可以访问数组内的元素。
例如: B[0] ,而数组B的每一个元素都是一个 int[10] 类型的数组。
再进一步访问,访问数组元素中的int元素。 例如: B[0][0] ,访问了第一个元素中的第一个元素。
可以发现,数组构成了一个二维的矩阵。并且,可以通过下标轻松地访问到它的每一个元素。
2.1 二维数组初始化
我们这样初始化一个一维数组
int A[10] = {0, 1, 2, 3, 4, 5 ,6 ,7 ,8 ,9};
而对于一个二维数组,它的每一个元素都是一个数组。
int B[5][10] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
{20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
{30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
{40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
}
类似于一维数组,初始化列表中的常量个数少于元素个数,将使用0初始化元素。
int B[5][10] = {
{0, 1, 2, 3, 4, 5},
{10, 11, 12, 13, 14, 15},
{20, 21, 22},
{30},
{}
}
另外,也可以省略里面的花括号。
int B[5][10] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49
}
省略内层花括号时,如果元素的个数不足。那么后续的将元素将使用0初始化。
int B[5][10] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19
}
对于一维数组代码:
#include <stdio.h>int main()
{
int B[5][10] = {
{0},{1},{2},{3},{4}
};
for(int i = 0; i<5; i++)
{
for(int j = 0; j<10;j++)
{
printf( "%d ",B[i][j]);
}
printf( "\n");
}
return 0;
}
2.2 访问或修改二维数组元素
2.2.1 访问二维数组元素
对于二维数组代码:
因为有两个下标,所以使用嵌套循环来遍历二维数组
#include <stdio.h>
int main()
{
int B[5][10] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
{20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
{30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
{40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
};
for (int i = 0; i < 5; i++) //遍历二维数组 查看所有元素
{
for (int j = 0; j < 10; j++)
{
printf("%d ", B[i][j]);
}
printf("\n");
}
return 0;
}
2.2.2 修改二维数组元素
可以使用赋值运算符修改二维数组元素
B[i][j] = B[i][j] * 2; // 修改二维数组值
下面的代码将二维数组每个元素都设置为原来的2倍。
#include <stdio.h>
int main()
{
int B[5][10] = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
{20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
{30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
{40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
};
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 10; j++)
{
B[i][j] = B[i][j] * 2; // 修改二维数组值
}
}
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < 10; j++)
{
printf("%d ", B[i][j]);
}
printf("\n");
}
return 0;
}
3. 更高维度的数组
如果将二维数组作为数组的元素,那么可以实现三位数组。依次类推,可以实现更高维度的数组。
int C[2][5][10];
数组C,有两个元素,每个元素是一个int[5][10]类型的二维数组。 对于三维数组,我们会使用三重循环来访问或修改元素值。
#include <stdio.h>
int main()
{
int B[2][5][10] = {
{
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
{10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
{20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
{30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
{40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
},
{
{-0, -1, -2, 3, -4, -5, -6, -7, -8, -9},
{-10, -11, -12, -13, -14, -15, -16, -17, -18, -19},
{-20, -21, -22, -23, -24, -25, -26, -27, -28, -29},
{-30, -31, -32, -33, -34, -35, -36, -37, -38, -39},
{-40, -41, -42, -43, -44, -45, -46, -47, -48, -49}
}
};
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 5; j++)
{
for(int k = 0; k < 10; k++)
{
printf("%d ", B[i][j][k]);
}
printf("\n");
}
printf("\n");
}
return 0;
}
二十一. 字符串与字符数组
在探究字符数组之前,来复习一下字符串相关的知识点吧。
1. 字符串常量
#include <stdio.h>
int main()
{
printf("sizeof HelloWorld = %d\n",
sizeof("HelloWorld"));
return 0;
}
字符串常量 “HelloWorld” 占用11个字节。
字符串常量在内存中,由每个字符的ASCII码按照顺序排列构成,每个字符仅占一个字节,并且末尾会附上一个数值0,指示字符串结尾。
字符’0’对应的ASCII码为十进制48。而标记字符串结尾的数值0,为了不与字符’0’冲突,使用转义序列’\0’表示。
2. 用字符数组存储字符串
既然字符串满足数组的类型相同且顺序排列的特点。那么元素为 char 的数组可以用于存储字符串。
2.1 初始化字符数组
我们声明一个数组,且把它初始化为"HelloWorld"
char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};
由于数组有20个元素,而初始化列表中仅有10个元素。数组大小大于初始化列表长度,数组后10个将会被初始化为0。也就相当于已经帮我们标记了字符串结尾了。
还有一种更加便捷的字符数组初始化方式。将初始化列表直接写成一个字符串常量,可以用于初始化字符数组。
char str[20] = "HelloWorld";
由于字符串常量末尾会自动添加’\0’为字符串结尾标识,所以当用字符串常量初始化字符数组时,代码等价于:
char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0'};
2.2 省略数组大小
有时候我们希望一个数组被初始化为某个字符串,但是又不想数清楚到底有多少个字符。我们可以在数组声明时,省略数组大小,初始化列表中的元素个数即为数组的大小。
char str1[] = "HelloWorld";
char str2[] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0'};
上面两种写法是等价的,数组的大小为初始化列表中元素的个数,即11。
2.3 打印字符数组
接下来,我们想让这串字符串被打印在控制台上。 printf的第一个参数可以接收一串字符串。所以我们可以直接把数组作为printf的第一个参数。
printf("HelloWorld"); //使用数组 printf(str);
另外,转换规范 %s ,可以作为字符串的占位符。
printf("%s", str);
将字符数组打印在控制台:
#include <stdio.h>
int main()
{
char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};
printf(str);
printf("\n");
printf("%s", str);
printf("\n");
return 0;
}
3. 字符串结尾标记’\0’
在使用字符串常量时,系统会自动为我们在字符串末尾添加 ‘\0’ 标记字符串结束。 而在使用字符数组时,有些情况不能保证字符串末尾有 ‘\0’,需要格外注意。
3.1 初始化列表长度小于数组长度
char str[20] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};
初始化列表长度小于数组长度,数组前10个元素被初始化为HelloWorld,后10个元素和普通数组一样后,被填充为0。
既然第11个元素为0,因此字符数组中的字符串正常结尾。
3.2 初始化列表长度等于数组长度
char str[10] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};
初始化列表长度小于数组长度,数组前10个元素被初始化为HelloWorld。第11个元素在数组外,也不能预知这个元素的值。字符数组中的字符串无法结尾。
程序运行后,正常打印出了数组中的10个元素HelloWorld。但是,由于数组中的字符串缺少结尾标 记 ‘\0’。因此,printf将继续打印数组外的元素,这样将导致数组越界访问。直到遇到一个 ‘\0’ ,才停止打印。
3.3 初始化列表长度大于数组长度
char str[5] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};
初始化列表长度大于数组长度将无法通过编译。
3.4 省略数组大小的情况
char str[] = "HelloWorld";
使用字符串常量初始化数组,由于系统会为字符串常量结尾添加’\0’。所以字符串常量大小为11。 使用该字符串初始化数组,数组大小为11,且最后一个字符为’\0’。字符数组中的字符串正常结尾。
char str[] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd', '\0'};
使用初始化列表初始化数组,初始化列表中有11个字符常量,且最后一个字符常量为’\0’。 使用该初始化列表初始化数组,数组大小为11,且最后一个字符为’\0’。字符数组中的字符串正常结尾。
char str[] = {'H', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd'};
使用初始化列表初始化数组,初始化列表中有10个字符常量,最后一个字符常量为’d’。 使用该初始化列表初始化数组,数组大小为10,且最后一个字符为’d’。字符数组中的字符串无法结尾。
4. 字符数组的大小及长度
char str[20] = "HelloWorld";
我们声明了一个长度为20的字符数组str,并将它使用字符串常量"HelloWorld"进行初始化。 这样,字符数组的前10个元素为HelloWorld,第11个元素为’\0’。
我们使用sizeof关键词,测试一下str的大小。
结果为20个字节,和我们声明的大小一致。
4.1 使用循环测量字符串长度
那么怎样知道这个字符数组中存储的字符串的长度呢。
事实上,一个字符串用 ‘\0’ 来标记结尾,只要知道在 ‘\0’ 之前,有多少个字符,就能知道字符数组中的字符串的长度了。
#include <stdio.h>
int main()
{
char str[20] = "HelloWorld";
int len = 0;
while(str[len] != '\0')
{
len++;
}
printf("%d", len);
return 0;
}
声明一个len变量,用于统计字符串长度。 while循环从第一个元素开始,检查元素是否为 ‘\0’ ,如果不是长度len加一,直到元素为 ‘\0’ 为止。 循环结束时, len 的值即为字符串的长度。
4.2 使用strlen测量字符串长度
另外,还可以使用 strlen 函数来计算字符串长度。 strlen为 string(字符串)与 length(长度)的合成词。 strlen 的使用范式:
- strlen可以接受一个字符串作为参数。
- strlen返回值为这个字符串的长度。
- 使用strlen函数,需包含头文件string.h。
#include <stdio.h>
#include <string.h>
int main()
{
char str[20] = "HelloWorld";
int len1;
len1 = strlen(str);
printf("len1 = %d\n", len1);
int len2;
len2 = strlen("HelloWorld");
printf("len2 = %d\n", len2);
printf("sizeof str %d\n", sizeof(str));
printf("sizeof helloworld %d\n", sizeof("HelloWorld"));
return 0;
}
len1为strlen函数测量字符数组 str 内字符串的长度。
len2为strlen函数测量字符串常量 “HelloWorld” 的长度。
后续,再用sizeof分别测量字符数组str和字符串常量"HelloWorld"所占空间大小。
HelloWorld有10个字符,所以字符串长度为10,len1、len2均为10。
而字符数组有20个元素,所以占用20字节空间。
字符串常量为字符串长度加结尾标记,所以占用11字节空间。
4.3 strlen与sizeof的区别
strlen(str)测量从第一个元素开始直到元素值为’\0’的字符串长度。 sizeof(str)测量数组本身占用空间的大小。
5. 字符数组可以被修改
字符串常量不能被修改,但是字符数组却是可以被修改的。 下面的代码中,数组被初始化为"abcde",我们让小写字符变为大写。小写字母ASCII码减32即为对应的大写字母。
#include <stdio.h>
#include <string.h>
int main()
{
char str[20] = "abcde";
// 修改前
printf(str);
printf("\n");
// 每个元素减32
for(int i = 0; i < strlen(str); i++)
{
str[i] = str[i] - 32;
}
// 修改后
printf(str);
return 0;
}
6. 从键盘输入一串字符串到字符数组
对应于printf,scanf中字符串的占位符为"%s"。使用scanf配合"%s"占位符,可以将键盘输入的一串字符串存储到字符数组。
char str[20]; scanf("%s", str); // 将键盘输入的一串字符串存储到字符数组str
下面的代码使用scanf将一串字符串存储到字符数组,其后将小写字母转为大写字母再输出。
#include <stdio.h>
#include <string.h>
int main()
{
char str[20];
// 输入一串字符到str
scanf("%s", str);
// 修改前
printf(str);
printf("\n");
// 每个元素减32
for(int i = 0; i < strlen(str); i++)
{
str[i] = str[i] - 32;
}
// 修改后
printf(str);
return 0;
}
scanf会帮我们在输入的字符串后加上’\0’,输入的字符串可以正常结尾。
7. putchar与getchar函数
putchar 与 getchar 函数可以单独输出或输入一个字符。 putchar 输出单个字符:
putchar('A');
getchar输入单个字符:
char c; c = getchar();
我们使用getchar与putchar,输入一个小写字符,将它转换为大写再输出。 小写字母ASCII码减32即为对应的大写字母。
#include <stdio.h>
int main()
{
char c;
c = getchar();
c = c - 32;
putchar(c);
return 0;
}
使用getchar函数输入小写字符’a’,将它转换为大写后,使用putchar函数输出。
结合上循环,使用putchar输出一串字符串。
#include <stdio.h>
int main()
{
char str[] = "HelloWorld";
int i = 0;
while(str[i] != '\0')
{
putchar(str[i++]);
}
return 0;
}
点个赞吧 😃