案例ex01: 将字符串转换为一个整数
1 题目
函数:fun()
功能:将字符串转换为一个整数
描述:【不能使用C语言提供的字符串函数】
输入:字符串"-1234"
输出:整型 -1234
2 思路
思路:将字符串每个位置的字符进行对应的ASCII码转换
例如:字符 ‘0’-‘9’ 对应的十进制整数是48~57,那么,将对应的整数减去48就得到了对应的整数
二进制 | 十进制 | 十六进制 | 字符 |
---|---|---|---|
0011 0000 | 48 | 30 | 0 |
0011 0001 | 49 | 31 | 1 |
0011 0010 | 50 | 32 | 2 |
0011 0011 | 51 | 33 | 3 |
0011 0100 | 52 | 34 | 4 |
0011 0101 | 53 | 35 | 5 |
0011 0110 | 54 | 36 | 6 |
0011 0111 | 55 | 37 | 7 |
0011 1000 | 56 | 38 | 8 |
0011 1001 | 57 | 39 | 9 |
3 代码
#include<stdio.h>
#include<string.h>
/**
函数:fun()
功能:将字符串转换为一个整数
描述:
【不能使用C语言提供的字符串函数】
输入:字符串"-1234"
输出:整型 -1234
**/
long fun(char *p) {
int r = 0; //数字个数
long res = 0L; // 转化后的数字
int pos = 1; // 位数*10 *100 ...
int size = strlen(p); // 字符串长度
if (p[0] == '-'){
r = size - 1;
} else {
r = size;
}
// 从前往后转换的话,需要分情况去计算。即:不是负数的话从p[0] 和 如果是负数的话需要从p[1]开始
// 所以,可以从后往前计算,循环次数是 r
for (int i = 0; i < r; ++i) {
res += (p[size-1-i]-48)*pos;
pos *= 10;
}
return p[0]=='-'?-res:res;
}
int main(int argc, char const *argv[]) {
char s[6];
printf("Enter a string: ");
gets(s);
long res = fun(s);
printf("Convert Result: %ld\n", res);
return 0;
}
示例结果:
$ gcc ex1.c -o demo
$ ./demo
Enter a string: -1234
Convert Result: -1234
$ ./demo
Enter a string: 9089
Convert Result: 9089
案例ex02: 将M行N列的二维数组中的字符数据,按列的顺序依次放到一个字符串中
1 题目
编写:fun()
功能:将M行N列的二维数组中的字符数据,按列的顺序依次放到一个字符串中
例如:
二维数组中的数据为:
W W W W
S S S S
H H H H
则字符串中的内容是:WSHWSHWSH
2 思路
第一层循环按照列数进行,第二层循环按照行数
然后依次提出每一列的字符
3 代码
为了熟悉二维数组的指针表示,部分代码给出了数组表示和指针表示
#include<stdio.h>
#include<string.h>
#define M 3
#define N 4
/**
编写:fun()
功能:将M行N列的二维数组中的字符数据,按列的顺序依次放到一个字符串中
例如:
二维数组中的数据为:
W W W W
S S S S
H H H H
则字符串中的内容是:WSHWSHWSH
**/
// 0 1 2 3
// 0 W W W W
// 1 S S S S
// 2 H H H H
char *fun(char s[M][N], char *res) {
int t = 0;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < M; ++j) {
res[t++] = s[j][i];
// res[t++] = *(*(a*i)+i); // 指针表示
}
}
res[t] = '\0';
return res;
}
int main(int argc, char const *argv[]) {
char a[M][N] = {
'M', 'M', 'M', 'M', 'S', 'S', 'S', 'S', 'H', 'H', 'H', 'H'};
int size_res = M*N;
char res[size_res];
printf("二维数组中元素:\n");
for (int i = 0; i < M; ++i) {
for (int j = 0; j < N; ++j) {
printf("%c\t", a[i][j]);
// printf("%c\t", *(*(a*i)+j)); // 指针表示
}
printf("\n");
}
printf("按列的顺序依次:\n%s\n", fun(a, res));
}
示例结果:
$ gcc ex002.c -o demo
$ ./demo
二维数组中元素:
M M M M
S S S S
H H H H
按列的顺序依次:
MSHMSHMSHMSH
案例ex03: 统计一行字符串单词的个数,作为函数值返回
1 题目
函数:fun()
功能:统计一行字符串单词的个数,作为函数值返回
一行字符串在主函数中输入,规定所有单词都是由小写字母组成,单词之间由若干空格隔开,一行的开始没有空格
2 思路
逐个字符进行判断是否为空
下面“空开处”指的是一个空格或者若干空格隔开单词的说法
- 开头无空格,故需要判断结尾有没有空开出,如果有,直接计算空开出就是单词数,如果没有需要单词数加1
- 上述1中的空开出需要做处理,由于单词间由若干空格隔开,故判断一个空格的前一个是否为空格,如果不是,数量加1;如果是,不做处理
3 代码
#include<stdio.h>
#include<string.h>
#define M 3
#define N 4
/**
函数:fun()
功能:统计一行字符串单词的个数,作为函数值返回
一行字符串在主函数中输入,规定所有单词都是由小写字母组成,单词之间由若干空格隔开,一行的开始没有空格
**/
int fun(char *s) {
int cnt = 0; // 单词个数
int i = 0;
while(*(s+i)!='\0') {
if (*(s+i) == ' ' && *(s+i-1) != ' ') {
cnt += 1;
}
++i;
}
if (*(s+i-1) != ' '){
// 如果单词结尾没有空格,则单词数需要空开数+1
return cnt + 1;
}
return cnt;
}
int main(int argc, char const *argv[]) {
char s[] = "hello world i am c language";
printf("字符串内容:%s\n", s);
printf("单词个数为:%d\n", fun(s));
}
示例结果:
$ gcc ex003.c -o demo
$ ./demo
字符串内容:hello world i am c language
单词个数为:6
案例ex04: 统计各个年龄阶段的人数
1 题目
函数:fun()
功能:统计各个年龄阶段的人数
描述:
N个年龄通过调用随机函数获得,并存放在主函数的age中
要求函数把0-9岁年龄段的放在d[0]中,把10-19岁年龄段的放在d[1]中,依次类推。把100岁及以上的放在d[10]中结果在主函数中输出
2 思路
随机使用 rand() 函数,头文件为#include <stdlib.h>
rand()函数是按指定的顺序来产生整数,因此每次执行上面的语句都打印相同的两个值,所以说C语言的随机并不是真正意义上的随机,有时候也叫伪随机数,使用 rand() 生成随机数之前需要用随机发生器的初始化函数 srand(unsigned seed)(也位于 stdlib.h 中) 进行伪随机数序列初始化,seed 又叫随机种子,通俗讲就是,如果每次提供的 seed 是一样的话,最后每一轮生成的几个随机值也都是一样的,因此叫伪随机数,所以需要每次提供不同的 seed 达到完全的随机,我们通常用时间函数 time(NULL) 作为 seed ,因为时间值每秒都不同,但是在此题中使用不到time这个工具
3 代码
#include <stdio.h>
#include <stdlib.h>
#define M 11
#define N 100
/**
函数:fun()
功能:统计各个年龄阶段的人数
描述:
N个年龄通过调用随机函数获得,并存放在主函数的age中
要求函数把0-9岁年龄段的放在d[0]中,把10-19岁年龄段的放在d[1]中,依次类推。把100岁及以上的放在d[10]中
结果在主函数中输出
**/
void fun(int *age, int *d) {
for (int i = 0; i < N; ++i) {
if (*(age+i)<100) {
d[(*(age+i))/10] += 1;
} else {
d[M-1] += 1;
}
}
}
int main(int argc, char const *argv[]) {
int age[N]; // 100个用户
int d[M]={
0}; // 11个年龄段
for (int i = 0; i < N; ++i) {
*(age+i) = rand()%121; // 设定年龄的范围是0-120
}
fun(age, d);
printf("各年龄阶段人数数量:\n");
for (int i = 0; i < M; ++i) {
printf("%d ", d[i]);
}
printf("\n");
}
示例结果:
$ gcc ex004.c -o demo
$ ./demo
各年龄阶段人数数量:
10 9 8 4 10 8 7 7 6 11 20
案例ex05: 删除一维数组中所有相同的数,使之只剩一个。
1 题目
函数:fun()
功能:删除一维数组中所有相同的数,使之只剩一个。
描述:数组中的数据已经按照从小到大排列,函数返回删除后数组中元素的个数
举例:一维数组中的数据是:2,2,2,2,3,3,4,4,5,6,6,6,7,7,8,9,9,9,10,10
删除后数组中的内容是:2,3,4,5,6,7,8,9,10
2 思路
初始化没有重复元素最右方的指针 a
当前元素与前一个元素进行比较,如果相同,则调到下一个,否则指针a+1
3 代码
#include <stdio.h>
#include <stdlib.h>
#define N 20
/**
函数:fun()
功能:删除一维数组中所有相同的数,使之只剩一个。
描述:数组中的数据已经按照从小到大排列,函数返回删除后数组中元素的个数
举例:
一维数组中的数据是:2,2,2,2,3,3,4,4,5,6,6,6,7,7,8,9,9,9,10,10
删除后数组中的内容是:2,3,4,5,6,7,8,9,10
**/
int fun(int *s) {
int a = 1;
for (int i = 1; i < N; ++i) {
if (*(s+i) != *(s+i-1)) {
// 当前元素与前一个元素进行比较,如果相同,则调到下一个,否则a+1
*(s+a) = *(s+i);
a++;
}
}
return a;
}
int main(int argc,char const *argv[]) {
int s[N] = {
2,2,2,2,3,3,4,4,5,6,6,6,7,7,8,9,9,9,10,10};
int cnt = fun(s);
printf("删除后的数组元素个数为:%d\n",cnt);
}
示例结果:
$ gcc ex005.c -o demo
$ ./demo
删除后的数组元素个数为:9
案例ex06: 移动字符串中内容
1 题目
函数:fun()
功能:移动字符串中内容
描述:移动规则如下:把第1到第m个字符,平移到字符串的最后,把m+1到最后的字符移到字符串的前部
举例:字符串原有内容为ABCDEFGHIJK,m的值为3,则移动后,字符串中的内容应该是DEFGHIJKABC
2 思路
为了不产生额外的空间复杂度,本次解决将一位一位移动
将数组第一个位置的元素保存到一个临时变量temp中,从第二位开始集体向左移动,最后将temp元素保存到最后一位
循环 m 次,从而达到最后的效果
3 代码
#include <stdio.h>
#include <string.h>
#define N 10
/**
函数:fun()
功能:移动字符串中内容
描述:移动规则如下:把第1到第m个字符,平移到字符串的最后,把m+1到最后的字符移到字符串的前部。
举例:字符串原有内容为ABCDEFGHIJK,m的值为3,则移动后,字符串中的内容应该是DEFGHIJKABC
**/
void fun(char *s, int m) {
int temp;
for (int i = 0; i < m; ++i) {
temp = s[0];
for (int j = 1; j < N; ++j) {
s[j-1] = s[j];
}
s[N-1] = temp;
}
}
int main(int argc, char const *argv[]) {
char s[N] = "ABCDEFGHIJ";
int m = 3;
printf("移动前的字符串:%s\n", s);
fun(s, m);
printf("移动后的字符串:%s\n", s);
}
示例结果:
$ gcc ex006.c -o demo
$ ./demo
移动前的字符串:ABCDEFGHIJ
移动后的字符串:DEFGHIJABC
案例ex07: 求数字的低n-1位的数
1 题目
函数:unsigned fun(unsigned w)
功能:求数字的低n-1位的数
描述:w 是一个大于10的无符号整数,若 w 是 n(n>=2)位的整数,函数求出来w的低n-1位的数作为函数值返回
举例:w 值为5923,则函数返回 923
2 思路
两步走:
- 先判断当前无符号整数的位数,记录位数*10。例如:如果有三位,那么记录time=100
- 根据time计算后 n-1 位,即:w-((w/time)*time)
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
函数:unsigned fun(unsigned w)
功能:求数字的低n-1位的数
描述:w 是一个大于10的无符号整数,若 w 是 n(n>=2)位的整数,函数求出来w的低n-1位的数作为函数值返回
举例:w 值为5923,则函数返回 923
**/
unsigned fun(unsigned w) {
// 先判断数字的位数
int temp_w = w;
int time = 1; // 位数10的指数次
while(temp_w > 0) {
time*=10;
temp_w = temp_w/10;
}
time = time/10;
// 计算返回
return w-((w/time)*time);
}
int main(int argc, char const *argv[]) {
int w;
printf("请一个大于10的无符号整数:");
scanf("%d", &w);
printf("无符号整数低n-1位的数为:%d\n", fun(w));
}
示例结果:
$ gcc ex007.c -o demo
$ ./demo
请一个大于10的无符号整数:12345
无符号整数低n-1位的数为:2345
$ ./demo
请一个大于10的无符号整数:765432
无符号整数低n-1位的数为:65432
案例ex08: 使数组的左下三角元素中的值乘以n
1 题目
函数:fun(int a[][N], int n)
功能:使数组的左下三角元素中的值乘以n
描述:程序定义了 N*N 的二维数组,并在主函数中自动赋值。
举例:
若 n 的值为3,a数组中的值为
1 9 7
3 9 7
2 3 8
则返回主程序后 a 数组中的值应该为
3 9 7
9 27 7
6 9 24
2 思路
利用二重循环解决
在第二层需要进行一点注意的地方
3 代码
# include <stdio.h>
# include <stdlib.h>
# define N 3
/**
函数:fun(int a[][N], int n)
功能:使数组的左下三角元素中的值乘以n
描述:程序定义了 N*N 的二维数组,并在主函数中自动赋值。
举例:
若 n 的值为3,a数组中的值为
1 9 7
3 9 7
2 3 8
则返回主程序后 a 数组中的值应该为
3 9 7
9 27 7
6 9 24
*/
void fun(int a[][N], int n) {
for (int i = 0; i < N; ++i) {
for (int j = 0; j <= i; ++j) {
a[i][j] = a[i][j] * n;
}
}
}
int main(int argc, char const *argv[]) {
int a[N][N] = {
{
1,9,7}, {
3,9,7}, {
2,3,8}};
int n = 3;
printf("原数组为:\n");
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
printf("%d\t", a[i][j]);
}
printf("\n");
}
fun(a, n);
printf("计算后数组:\n");
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
printf("%d\t", a[i][j]);
}
printf("\n");
}
}
示例结果:
$ gcc ex008.c -o demo
$ ./demo
原数组为:
1 9 7
3 9 7
2 3 8
计算后数组:
3 9 7
9 27 7
6 9 24
案例ex09: 移动一维数组的内容
1 题目
函数:fun()
功能:移动一维数组的内容
描述:若数组中有n个整数,要求把下标从0到p(含p,p<=n-1)的元素平移到数组的最后
举例:一维数组:1,2,3,4,5,6,7,8,9,10,p的值为3
移动后:5,6,7,8,9,10,1,2,3,4
2 思路
循环 p 次:
将下标为0的数字进行临时存放,然后将后面的数字平移到前面,最后将临时存放的数字放到最后一位
3 代码
#include <stdio.h>
#include <stdlib.h>
#define N 10
/**
函数:fun()
功能:移动一维数组的内容
描述:若数组中有n个整数,要求把下标从0到p(含p,p<=n-1)的元素平移到数组的最后
举例:
一维数组:1,2,3,4,5,6,7,8,9,10,p的值为3
移动后:5,6,7,8,9,10,1,2,3,4
**/
void fun(int *a, int p) {
int temp;
for (int i = 0; i <= p; ++i) {
temp = a[0]; // 临时存放第一个数字
for (int j = 1; j < N; ++j) {
// 循环将后续数字进行平移
a[j-1] = a[j];
}
a[N-1] = temp; // 临时数字存放到最后一位
}
}
int main(int argc, char const *argv[]) {
int a[10] = {
1,2,3,4,5,6,7,8,9,10};
int p = 3;
printf("原始数组内容:\n");
for (int i = 0; i < N; ++i) {
printf("%d ", a[i]);
}
printf("\n");
fun(a, p);
printf("平移后数组内容:\n");
for (int i = 0; i < N; ++i) {
printf("%d ", a[i]);
}
printf("\n");
}
示例结果:
$ gcc ex009.c -o demo
$ ./demo
原始数组内容:
1 2 3 4 5 6 7 8 9 10
平移后数组内容:
5 6 7 8 9 10 1 2 3 4
案例ex10: 删除字符串中所有的空格
1 题目
函数:fun()
功能:删除字符串中所有的空格
举例:
主函数中输入“fds afadsf adf d dsf 67d”
则输出:“fdsafadsfadfddsf67d”
2 思路
设置两指针,begin 和 end
begin 和 end 同时从头开始向后移动:
- 当遇到空格的时候,end 向后移动,begin不变
- 当 end 位置不为空格的时候,将 end 位置的字符填充到 begin 的位置
最后,在完成去除空格的操作后,在最后添加 ‘\0’
3 代码
#include <stdio.h>
#include <stdlib.h>
#define N 30
/**
函数:fun()
功能:删除字符串中所有的空格
举例:
主函数中输入“fds afadsf adf d dsf 67d”
则输出:“fdsafadsfadfddsf67d”
**/
void fun(char *s) {
int begin = 0, end = 0;
while(s[end]!='\0') {
if (s[end] != ' ') {
s[begin] = s[end];
begin++;
end++;
} else {
end++;
}
}
s[begin] = '\0'; // 去除空格后,在最后一位加 '\0'
}
int main(int argc, char const *argv[]) {
char s[N] = "fds afadsf adf d dsf 67d";
printf("原始字符串:%s\n", s);
fun(s);
printf("去空格后字符串:%s\n", s);
}
示例结果:
$ gcc ex010.c -o demo
$ ./demo
原始字符串:fds afadsf adf d dsf 67d
去空格后字符串:fdsafadsfadfddsf67d
案例ex11: 使用指针实现整数逆序排序
1 题目
函数:fun()
功能:使用指针实现整数逆序排序
描述:在main函数中实现,输入三个数字,使用指针实现三个数字的逆序排序
2 思路
使用指针实现数字的操作
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
函数:fun()
功能:使用指针实现整数逆序排序
描述:在main函数中实现,输入三个数字,使用指针实现三个数字的逆序排序
**/
void swap(int *p1, int *p2) {
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void fun(int *p1, int *p2, int *p3) {
if (*p1 < *p2)
swap(p1, p2);
if (*p1 < *p3)
swap(p1, p3);
if (*p2 < *p3)
swap(p2, p3);
}
int main(int argc, char const *argv[]) {
int a, b, c;
int *q1, *q2, *q3;
printf("请输入三个数字:");
scanf("%d, %d, %d", &a, &b, &c);
q1 = &a;
q2 = &b;
q3 = &c;
printf("逆序前的数字:%d, %d, %d\n", *q1, *q2, *q3);
fun(q1, q2, q3);
printf("逆序后的数字:%d, %d, %d\n", *q1, *q2, *q3);
}
示例结果:
$ gcc ex011.c -o demo
$ ./demo
请输入三个数字:3,9,1
逆序前的数字:3, 9, 1
逆序后的数字:9, 3, 1
$ ./demo
请输入三个数字:1,2,3
逆序前的数字:1, 2, 3
逆序后的数字:3, 2, 1
案例ex12: 指向结构体变量的指针
1 题目
功能:指向结构体变量的指针
描述:通过结构体指针变量实现显示学生信息
2 思路
熟悉结构体的使用
熟悉指针和结构体的混合使用
3 代码
#include <stdio.h>
/**
功能:指向结构体变量的指针
描述:通过结构体指针变量实现显示学生信息
**/
struct student {
int num;
char name[20];
char sex;
int age;
float score;
};
int main(int argc, char const *argv[]) {
struct student stu = {
1001, "计算广告生态", 'M', 28, 98.5
};
struct student *s = &stu;
printf("No.\t%d\n", s->num);
printf("Name.\t%s\n", s->name);
printf("Sex.\t%c\n", s->sex);
printf("Age.\t%d\n", s->age);
printf("Score.\t%d\n", s->score);
}
示例结果:
$ gcc ex012.c -o demo
$ ./demo
No. 1001
Name. 计算广告生态
Sex. M
Age. 28
Score. 73896
案例ex13: 使用指针输出数组元素
1 题目
目标:熟悉指针和数组的底层逻辑
功能:使用指针输出数组元素
描述:通过指针将数组中你那个各个元素值进行打印输出
2 要点
a. 指向数组的指针实现输出数组元素,定义一个指向数组的指针用来灵活操作数组
int a[10];
int *p;
// 指针 p 指向数组的方法,下面两种都是可以的.
// a 本身就是数组的其实地址,&a[0] 也是数组的起始地址
p = a;
p = &a[0];
b. 指针既是指向变量地址的又是决定指向变量地址的位数的。例如
int p = &a[0];
既是指向数组a的首地址 又是说明了每次指向都int类型的数据,即 4 个字节。
所以,在指定 p 的基类型后,通过指针指向数组,每次 p++ 都是会跳动4个字节,到达下一个位置a[1]。
即:*(p+1) 即取得 a[1] 的数据
3 代码
#include <stdio.h>
#define N 10
/**
目标:熟悉指针和数组的底层逻辑
功能:使用指针输出数组元素
描述:通过指针将数组中你那个各个元素值进行打印输出
**/
int main(int argc, char const *argv[]) {
int a[N];
int *p;
printf("请输入 10 个数字: \n");
for (int i = 0; i < N; ++i) {
scanf("%d", &a[i]);
}
printf("\n");
for (p = a; p < a+10; ++p) {
// 指针指向进行数组内容打印
printf("数组中的内容:\n%d\n", *p);
}
return 0;
}
示例结果:
$ gcc ex013.c -o demo
$ ./demo
请输入 10 个数字:
1
2
3
4
5
6
7
8
9
10
数组中的内容:
1
2
3
4
5
6
7
8
9
10
案例ex14: 找出数列中的最大值和最小值
1 题目
函数:max_min()
功能:找出数列中的最大值和最小值
描述:使用指针查找数列中的最大值和最小值(使用指针从而避免使用返回值)
2 思路
使用指针从而避免使用返回值
在主函数中定义最大值 max 和最小值 min,将 max 和 min 的地址传递给函数处理,计算结果直接放到主函数中定义的 max 和 min 的地址中
这样做代码执行高效并且思路清晰
3 代码
#include <stdio.h>
#include <stdlib.h>
#define N 10
/**
函数:max_min()
功能:找出数列中的最大值和最小值
描述:使用指针查找数列中的最大值和最小值
**/
void max_min(int *a, int *max, int *min) {
*max = *a; // 将数组下标为 0 的数字初始化给max
*min = *a; // 将数组下标为 0 的数字初始化给min
for (int i = 0; i < N; ++i) {
if(*max < *(a+i)) // 将大于max的值赋值给max
*max = *(a+i);
}
for (int i = 0; i < N; ++i) {
if(*min > *(a+i)) // 将小于min的值赋值给min
*min = *(a+i);
}
}
int main(int argc, char const *argv[]) {
int i, a[N];
int max, min;
printf("请输入 10 个数字:\n");
for (int i = 0; i < N; ++i) {
scanf("%d", a+i);
// scanf("%d", &a[i]);
}
max_min(a, &max, &min);
printf("输入的 10 个数字为: ");
for (int i = 0; i < N; ++i) {
printf("%d ", *(a+i));
}
printf("\n最大值为:%d\n", max);
printf("\n最小值为:%d\n", min);
}
示例结果:
$ gcc ex014.c -o demo
$ ./demo
请输入 10 个数字:
3
2
1
10
9
8
7
6
5
4
输入的 10 个数字为: 3 2 1 10 9 8 7 6 5 4
最大值为:10
最小值为:1
案例ex15: 使用指针的指针输出字符串
1 题目
功能:使用指针的指针输出字符串
描述:
使用指针的指针输出字符串。
首先要使用指针数组创建一个字符串数组,然后定义指向指针的指针,使其指向字符串数组,并使用其输出数组的字符串
2 思路
char **p;
这里指向指针的指针,表示指针变量 p 是指向一个指针变量。*p 就表示 p 指向另外一个指针变量,即一个地址。
**p 表示 p 指向指针变量指向的对象的值。 例如:* (p+1) 表示 accounts[1] 的内容,指向 accounts[1] 的首地址
3 代码
#include <stdio.h>
#define N 5
/**
函数:fun()
功能:使用指针的指针输出字符串
描述:使用指针的指针输出字符串。
首先要使用指针数组创建一个字符串数组,然后定义指向指针的指针,使其指向字符串数组,并使用其输出数组的字符串
**/
int main(int argc, char const *argv[]) {
char *accounts[] = {
"你好 C语言 1",
"你好 C语言 2",
"你好 C语言 3",
"你好 C语言 4",
"你好 C语言 5"
}; // 指针数组创建字符串数组
char **p;
p = accounts; // 注意这里一定是二重指针来指向accounts
for (int i = 0; i < N; ++i) {
printf("%s\n", *(p+i)); // 使用指针将字符串数组中的字符串打印出来
}
}
示例结果:
$ gcc ex015.c -o demo
yaojianguodeMacBook-Pro:ex100 yaojianguo$ ./demo
欢迎关注公众号, 计算广告生态1
欢迎关注公众号, 计算广告生态2
欢迎关注公众号, 计算广告生态3
欢迎关注公众号, 计算广告生态4
欢迎关注公众号, 计算广告生态5
案例ex16: 使用指向指针的指针对字符串排序
1 题目
函数:sort()
功能:使用指向指针的指针对字符串排序
描述:
使用指向指针的指针对字符串排序,输出是按照字母顺序进行排序
2 思路
a. 熟悉指向指针的指针的使用
char *nums[]={
"", ""};
char **p;
p = nums;
熟悉 *p 指向的是 nums[0] 的首地址
b. 引用模块#include <string.h>
使用函数 int strcmp(const char *str1, const char *str2) 进行字符串的比较
该函数返回值如下:
- 如果返回值小于 0,则表示 str1 小于 str2。
- 如果返回值大于 0,则表示 str1 大于 str2。
- 如果返回值等于 0,则表示 str1 等于 str2。
3 代码
#include <stdio.h>
#include <string.h>
#define N 10
/**
函数:fun()
功能:使用指向指针的指针对字符串排序
描述:
使用指向指针的指针对字符串排序,输出是按照字母顺序进行排序
**/
void sort(char **p) {
char *temp; // 排序交换时的临时变量
for (int i = 0; i < N; ++i) {
for (int j = i+1; j < N; ++j) {
if (strcmp(*(p+i), *(p+j)) > 0) {
// 使用strcmp进行字符串的比较
temp = *(p+i);
*(p+i) = *(p+j);
*(p+j) = temp;
}
}
}
}
int main(int argc, char const *argv[]) {
int n = 5;
char **p;
char *nums[] = {
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"
};
p = nums; // 使用指向指针的指针指向字符串数组
printf("排序前的数组内容为:\n");
for (int i = 0; i < N; ++i) {
printf("%s ", *(p+i));
}
printf("\n");
sort(p);
printf("排序后的数组内容为:\n");
for (int i = 0; i < N; ++i) {
printf("%s ", *(p+i));
}
printf("\n");
}
示例结果:
$ gcc ex016.c -o demo
$ ./demo
排序前的数组内容为:
one two three four five six seven eight nine ten
排序后的数组内容为:
eight five four nine one seven six ten three two
案例ex17: 使用指针连接两个字符串
1 题目
函数:connect()
功能:使用指针连接两个字符串
描述:
实现两个已知字符串的连接,放到另外一个字符串数组中,然后将连接好的字符串进行打印显示
2 思路
使用字符型指针变量和指向字符串的指针做函数的参数来实现字符串的连接
注意初始化 char *conn来存储新字符串的时候,必须先分配存储空间
char *conn = (char *)malloc(strlen(str1)+strlen(str2)+1);
memset(conn, strlen(str1)+strlen(str2)+1, 0); // 可选,初始化填充内存空间
另外,使用指针的特性,使得 conn 不断被赋值, str1 和 str2 指向的存储地址,达到字符串的连接
3 代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/**
函数:connect()
功能:使用指针连接两个字符串
描述:
实现两个已知字符串的连接,放到另外一个字符串数组中,然后将连接好的字符串进行打印显示
**/
void connect(char *str1, char *str2, char *conn) {
while(*str1 != '\0') {
*conn = *str1;
conn++;
str1++;
}
*conn = ','; // 两个字符串直接添加逗号
conn++;
while(*str2 != '\0') {
*conn = *str2;
conn++;
str2++;
}
*conn = '\0';
}
int main(int argc, char const *argv[]) {
char *str1 = "技术分享园子";
char *str2 = "计算广告生态";
char *conn = (char *)malloc(strlen(str1)+strlen(str2)+1); // 为 conn 分配空间,否则是无效地址
memset(conn, strlen(str1)+strlen(str2)+1, 0); // 初始化 conn 指向的存储地址
printf("第一个字符串:%s\n", str1);
printf("第二个字符串:%s\n", str2);
connect(str1, str2, conn);
printf("连接后的字符串是:\n");
printf("%s\n", conn);
}
示例结果:
$ gcc ex017.c -o demo
$ ./demo
第一个字符串:技术分享园子
第二个字符串:计算广告生态
连接后的字符串是:
技术分享园子,计算广告生态
案例ex18: 用指针实现逆序存放数组元素的值
1 题目
函数:invert()
功能:用指针实现逆序存放数组元素的值
描述:使用指针将数组中的元素值逆序放置,并且将结果打印出来
2 思路
1. 程序变量中两个数字进行交换的三种方法
第一种:引入一个中间量
temp=a;
a=b;
b=temp;
第二种:要注意的是a+b可能会超过int的范围,这个是该方法的缺点
a=a+b;
b=a-b;
a=a-b;
第三种:这种方法效率最高,推荐使用
a=a^b;
b=a^b;
a=a^b;
2. 指针的使用
使用指针对数组内容进行操作,数组 a, a 指向数组首位置,a+N-1 指向最后一位。从而利用循环对数组的首尾数字逐个替换
3 代码
#include <stdio.h>
#include <stdlib.h>
#define N 10
/**
函数:invert()
功能:用指针实现逆序存放数组元素的值
描述:使用指针将数组中的元素值逆序放置,并且将结果打印出来
**/
void invert(int *a) {
int *begin, *end, mid; // 定义首尾指针
begin = a;
end = a+N-1;
mid = (N-1)/2; // 中间位置
int temp;
for (int i = 0; i <= mid; ++i){
// 循环,首尾指针内容变换
// temp = *begin;
// *begin = *end;
// *end = temp;
*begin = *begin ^ *end;
*end = *begin ^ *end;
*begin = *begin ^ *end;
++begin;
--end;
}
}
int main(int argc, char const *argv[]) {
int a[N] = {
1,2,3,4,5,6,7,8,9,10};
printf("当前数组中的值为:");
for (int i = 0; i < N; ++i) {
printf("%d ", *(a+i));
}
printf("\n");
invert(a);
printf("使用指针逆序后数组中的值为:");
for (int i = 0; i < N; ++i) {
printf("%d ", *(a+i));
}
printf("\n");
}
示例结果:
$ gcc ex018.c -o demo
$ ./demo
当前数组中的值为:1 2 3 4 5 6 7 8 9 10
使用指针逆序后数组中的值为:10 9 8 7 6 5 4 3 2 1
案例ex19: 用指针数组构造字符串数组
1 题目
功能:用指针数组构造字符串数组
描述:实现输入一个星期中对应的第几天,可以显示其英文名
目标:熟悉对字符串数组对应的指针的使用
2 思路
-
要点:通过构造一个字符串数组来指定数组中元素的元素值。
-
指针数组:即数组中都是指针类型的数据,指针数组中的每个元素都是一个指针
定义:
类型名 *数组名[数组长度];
例如:
char *[5];
其中 p 是一个指针数组,该数组是由 5 个数据元素组成,每个元素相当于一个指针变量,都可以指向一个字符串变量
- 注意点:*p[4] 与 (*p)[4] 的区别要知道, (*p)[4] 中的 p 是一个指向一维数组的指针变量
3 代码
#include <stdio.h>
/**
功能:用指针数组构造字符串数组
描述:实现输入一个星期中对应的第几天,可以显示其英文名
目标:熟悉对字符串数组对应的指针的使用
**/
int main(int argc, char const *argv[]) {
char *week[] = {
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
};
int w; // 用来记录周几
printf("请输入星期几(输入阿拉伯数字):");
scanf("%d", &w);
printf("Today is %s.\n", *(week+w-1));
return 0;
}
示例结果:
$ gcc ex019.c -o demo
$ ./demo
请输入星期几(输入阿拉伯数字):5
Today is Friday
案例ex20: 用指针函数输出学生成绩
1 题目
函数:search()
功能:用指针函数输出学生成绩
描述:指针函数的使用,输入学生的序号,将在窗口输出该序号对应的学生的成绩
2 思路
-
指向函数的指针变量的形式如下:
数据类型 (*指针变量名)()
例如;
int * search()
-
*§() 表示定义一个指向函数的指针变量,用来存放函数入口地址。在程序设计过程中,将一个函数地址赋值给它,它就指向那个函数。函数指针变量赋值写法:
p = min;
在赋值的时候,只给出函数名即可**,函数名即地址**
在使用函数指针调用函数的时候,要写出函数的参数,例如:
m = (*p)(a,b);
3 代码
#include <stdio.h>
/**
函数:search()
功能:用指针函数输出学生成绩
描述:指针函数的使用,输入学生的序号,将在窗口输出该序号对应的学生的成绩
**/
int * search(int (*p)[4], int n) {
int *pt = *(p+n);
return pt;
}
int main(int argc, char const *argv[]) {
int score[][4] = {
{
98,56,89,87},
{
88,56,87,80},
{
92,56,84,82},
{
78,56,90,67}
}; // 声明数组,对应四个学生的各科成绩
int no; // 保存学生编号
printf("输入学生编号:");
scanf("%d", &no);
int *p = search(score, no);
printf("学生编号为 %d 的学生成绩为:\n", no);
for (int i = 0; i < 4; ++i) {
printf("%d\t", *(p+i));
}
putchar('\n');
}
示例结果:
$ gcc ex020.c -o demo
$ ./demo
输入学生编号:3
学生编号为3的学生成绩为:
78 56 90 67
案例ex21: 寻找相同元素的指针
1 题目
函数:find()
功能:寻找相同元素的指针
描述:比较两个有序数组的元素,输出两个数组中第一个相同的值
2 思路
利用有序数组有序的特点
建立一个指针函数,这个函数返回值为指针类型,即一个地址。定义如下:
int * find(int *a, int *b, int m, int n);
在程序中调用该函数:
int * p = find(a, b, sizeof(a)/sizeof(a[0]), sizeof(b)/sizeof(b[0]));
返回一个指向整型变量的指针
3 代码
#include <stdio.h>
#include <stdlib.h>
/**
函数:find()
功能:寻找相同元素的指针
描述:比较两个有序数组的元素,输出两个数组中第一个相同的值
**/
int * find(int *a, int *b, int m, int n) {
int *pa = a;
int *pb = b;
while(pa < a+m && pb < b+n) {
if (*pa < *pb) {
pa++;
}
else if(*pa > *pb) {
pb++;
}
else {
return pa;
}
}
}
int main(int argc, char const *argv[]) {
int *p;
int a[] = {
2,5,7,9,11,34,56}; // 声明两个数组
int b[] = {
3,6,8,10,12,34,59}; // 声明两个数组
printf("两个数组的内容分别是:\n");
for (int i = 0; i < sizeof(a)/sizeof(a[0]); ++i) {
// 打印数组