C程序设计(第5版)——谭浩强(2)
参考:https://blog.csdn.net/qq_50696399/article/details/141574823
ch8 指针
在对程序进行编译时,系统会给变量分配内存单元。(int分配4个字节,float分配4个字节,char分配1个字节)。内存区中的每一个字节有一个编号,称为地址。
地址指向变量单元,
地址 = 指针
C语言的地址包括位置信息(内存编号,或称纯地址)和它所指向的数据的类型信息,或者说它是带类型的地址。
int i;
编译时,系统为变量i分配了4个字节的内存单元,建立了变量名和地址的对应表。
printf(“%d\n”,i);
通过变量名找到相应的地址,从该4个字节中按照整型数据的存储方式读出i的值。
直接访问:通过变量名找到对应的值;
间接访问:变量名对应的地址放在指针变量,通过地址找到对应的值;
//例8.1
int main()
{
int a = 100, b = 10;
int * p1 = &a, * p2 = &b;
printf("a = %d b = %d", *p1, *p2);
return 0;
}
//例8.2
int main()
{
int a,b;
int *p = &a, *q = &b;
scanf("%d %d", p, q);
if (*p >= *q)
printf("%d", *p);
else
printf("%d", *q);
return 0;
}
//例8.3
int main()
{
void swap(int* p, int* q);
int a,b;
int *p = &a, *q = &b;
scanf("%d %d", p, q);
if (*p <= *q)
swap(p, q);
printf("max = %d, min = %d\n", a, b);
return 0;
}
void swap(int* p, int* q)//直接改了地址所指向的内容,如果是形参在改,上面的值不会变
{
int t = *p;
*p = *q;
*q = t;
}
//例8.4
void swap(int* p, int* q)//直接改了地址所指向的内容,如果是形参在改,上面的值不会变
{
int* t = p;
p = q;
q = t;
}
//例8.5
int main()
{
void exchange(int* p, int* q, int* r);
void swap(int* p, int* q);
int a, b, c;
int *p = &a, *q = &b, *r = &c;
scanf("%d %d %d", p, q, r);
exchange(p, q, r);
printf("max = %d, mid = %d, min = %d\n", a, b, c);
return 0;
}
void swap(int* p, int* q)//直接改了地址所指向的内容,如果是形参在改,上面的值不会变
{
int t = *p;
*p = *q;
*q = t;
}
void exchange(int* p, int* q, int* r)
{
if (*p < *q)//确保*p最大
swap(p, q);
if (*p < *r)//确保*p最大
swap(p, r);
if (*q < *r)//确保*q第二最大
swap(q, r);
}
指针变量p
p+1不是将p的值简单加1,而是p的值加指针类型所占用的字节数
指针变量p1和p2都指向同一数组的元素时,p2-p1的结果是两个地址差再除以数组元素长度
//例8.6
int main()
{
int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
for (int i = 0; i < 10; i++)
printf("%d ", a[i]);
return 0;
}
int main()
{
int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
for (int i = 0; i < 10; i++)
printf("%d ", *(a+i));//a是元素首地址,地址是指针,指针+i不是简单地加i
return 0;
}
int main()
{
int a[10] = { 0,1,2,3,4,5,6,7,8,9 }, *p = a;
for (; p < a+10; p++)//p址是指针,指针+i不是简单地加i
printf("%d ", *p);
return 0;
}
//例8.7
int main()
{
int a[10] = { 0,1,2,3,4,5,6,7,8,9 }, *p = a;
for (int i = 0; i < 10;i++, p++)//p址是指针,指针+i不是简单地加i
printf("%d ", *p);
return 0;
}
//例8.8
int main()
{
void inv(int* x, int n);
int a[10] = {3,7,9,11,0,6,7,5,4,3 }, *p = a;
inv(a, 10);
for (; p < a + 10; p++)//p址是指针,指针+i不是简单地加i
printf("%d ", *p);
return 0;
}
void inv(int* x, int n)
{
int* len = x + n / 2;
int* y = x + n - 1;//指向尾
for (; x < len; x++, y--)
{
int t = *x;
*x = *y;
*y = t;
}
}
//例8.10
int main()
{
void sort(int* x, int n);
int a[10] = {12,34,5,689,-43,56,-21,0,24,65}, *p = a;
sort(a, 10);
for (; p < a + 10; p++)//p址是指针,指针+i不是简单地加i
printf("%d ", *p);
return 0;
}
void sort(int* x, int n)
{
for (int i = 0; i < n - 1; i++)
{
int max_val = *(x + i), max_ind = i, t;
for (int j = i + 1; j < n; j++)
if (*(x + j) > max_val)
{
max_val = *(x + j);
max_ind = j;
}
t = *(x + max_ind);
*(x + max_ind) = *(x + i);
*(x + i) = t;
}
}
通过指针引用多维数组
int a[3][4];
a是二维数组名;a数组包含3个元素a[0],a[1],a[2];
a[0]是一维数组名,a[0]数组包含4个元素a[0][0],a[0][1],a[2][0],a[0][3];
a是二维数组,a[0]是一维数组,a[0]是数组的数组,这是二维数组的角度。
数组名是首元素地址
a含义:a二维数组的元素是每一行,首元素地址是第0行地址,值为&a[0],a指向a[0]
a+1含义:第1行地址,值为&a[1],a+1指向a[1]
a[0]含义:a[0]一维数组的元素是第0行的每一列,首元素地址是第0行 第0列地址,值为&a[0][0],a[0]指向a[0][0]
a[1]含义:第1行第0列地址,值为&a[1][0],a[1]指向a[1][0]
a[0]+1不是简单地加1,a[0]是地址,加的是a[0]类型的字节数;
a[0]+1含义:第0行第1个元素地址,值为&a[0][1],a[0]+1指向a[0][1]
a指向一维数组a[0],a[0]指向列元素a[0][0]。对不同的指针进行加1运算,得到的结果是不同的。
书本原文:从二维数组的角度来看,a代表二维数组首元素的址,现在的首元素不是一个简单的整型元素,而是由4个整型元素组成的一维数组,因此a代表的是首行的起始地址。如果二维数组的首行的起始地址为2000,a+1的值应该是2000+4*4=2016。(一行4个元素,每个元素4个字节)
重要:a[0]和*(a+0)等价;a[i]和*(a+i)等价;
则a[0]+1和*(a+0)+1的值都是&a[0][1];
a[1]+2和*(a+1)+2的值都是&a[1][2]
如果a是二维数组,则a[i]是一维数组名,它只是一个地址,并不是一个存储单元,进而也不是存储单元中的值。
得到地址后在地址前面再加一个解引用得到这个地址所指的值,即(a[0]+1)和*(*(a+0)+1)的值都是a[0][1]
说明:C语言的地址信息包含位置信息和指向数据的类型信息。a[0]是一维数组名,a是二维数组名,二者地址相同,但指向类型不同,一个指向整型数据,一个指向一维数组。用指针变量pt指向这个一维数组,应当这样定义:
int (*pt)[4];
pt指向类型:由4个int元素组成的一维数组;
对比int *p;
p指向类型:一个int元素
简单粗暴的理解:
假设p指向一维数组,那么定义pt时后面多了个[4],说明pt指向二维数组;
星p就是a[0]的值,星(星(pt+i) + j)就是a[i][j]的值
//例8.12
int main()
{
int a[3][4] = { 1,3,5,7,9,11,13,15,17,19,21,23 }, *p = a;
//p<a+12以a的行元素个数来加,地址的取值上为:a+(12*4*4)
//含义分别为:12为要加12次,4为一个int占4字节地址,4为一行4个元素
//要循环12*4次,因为p++每次只走一个元素的地址长度,而非一行的地址长度
//正常循环12次,地址的取值上为:a+(12*4)
for (p = a; p < a[0] + 12; p++)
{
printf("%d ", *p);
}
return 0;
}
//例8.13
int main()
{
int a[3][4] = { 1,3,5,7,9,11,13,15,17,19,21,23 }, (*p)[4] = a;
//p指向由4个int元素组成的一维数组
//*p指向由4个int元素组成的一维数组的第0个int
//*(p)+1为0行1列的地址,*(p+2)+1为2行1列的地址
//现在是a+3而不是a[0]+12,共有3行,大循环3次,p++每加一次地址加的是一行4个int元素的字节数(4*4)=16
for (p = a; p < a + 3; p++)
{
for (int i = 0; i < 4; i++)//小循环4次
printf("%d ", *(*(p) + i));
printf("\n");
}
return 0;
}
//例8.14
int main()
{
void average(float* p, int n);
void search(float (*p)[4], int n);
float score[3][4] = { 65,67,70,60,80,87,90,81,90,99,100,98 };
average(*score, 12);//score是首元素地址,首元素为一行float;*score是首元素地址,首元素为此行的一个float
search(score, 2);//score是首元素地址,首元素为一行float
return 0;
}
void average(float* p, int n)
{
float* p_end = p + n, ave = 0;
for (; p < p_end; p++)
{
ave += (*p) / 12;
}
printf("ave = %f\n", ave);
}
//*p指向一维数组,指向类型为一个float
//(*p)[4]指向二维数组,指向类型为一行float,p是首元素地址,p是数组名
void search(float (*p)[4], int n)
{
for (int i = 0; i < 4; i++)
{
printf("%f ", *(*(p+n)+i));
}
}
//例8.15
int main()
{
void search(float (*p)[4], int n);
float score[3][4] = {65,67,70,60,58,87,90,81,90,99,100,98};
search(score, 3);//(*p)[4]指向类型为4个float组成的数组
return 0;
}
void search(float (*p)[4], int n)
{
for (int i = 0; i < n; i++)
{
bool flag = true;
for (int j = 0;j < 4; j++)
{
if (*(*(p+i)+j) < 60)
{
flag = false;
}
}
if(!flag)
for (int j = 0; j < 4; j++)
printf("%f ", *(*(p + i) + j));
printf("\n");
}
}
//例8.17
int main()
{
//字符串实际为字符数组,有一个虚无的数组名,数组名是首元素地址赋给了string
char* string = "I love you";
printf("%s\n", string);
return 0;
}
//例8.18
int main()
{
char* a = "I love you", b[20];
int i = 0;
for (; *(a+i) != '\0'; i++)
b[i] = a[i];
b[i] = '\0';
for (int i = 0; *(b + i) != '\0'; i++)
{
printf("%c", b[i]);
}
return 0;
}
//例8.19
int main()
{
char* a = "I love you", b[20], *p1 = a, *p2 = b;
for (; *p1 != '\0'; p1++, p2++)
*p2 = *p1;
*p2 = '\0';
for (int i = 0; *(b + i) != '\0'; i++)
{
printf("%c", b[i]);
}
return 0;
}
//例8.20
int main()
{
void copy_string(char* from, char* to);
char* a = "teacher", b[] = "student", *from = a, *to = b;
copy_string(from, to);
printf("%s\n%s", a,b);
return 0;
}
void copy_string(char* from, char* to)
{
for (; *from!='\0'; from++,to++)
{
*to = *from;
}
*to = '\0';
}
指向函数的指针
函数名就是函数的指针,它代表函数的起始地址
定义:
int (*p)(int, int);指针p指向类型为有两个int参数的函数
int (*p)[4];指向类型为4个int组成的数组
int *p;指向类型为一个int元素
使用:(*p)看成函数名完事
//例8.23
int main()
{
int find_max(int x, int y);
int find_min(int x, int y);
int (*p)(int, int) = find_max;//定义指针变量p,它指向find_max的首地址
int (*q)(int, int) = find_min;
int a, b, choose;
scanf("%d %d %d", &a, &b, &choose);
if(choose == 1)
printf("max = %d", (*p)(a, b));
else if(choose == 2)
printf("min = %d", (*q)(a, b));
return 0;
}
int find_max(int x, int y)
{
if (x >= y)
return x;
else
return y;
}
int find_min(int x, int y)
{
if (x <= y)
return x;
else
return y;
}
//例8.24
int main()
{
int fun(int x, int y, int(*p)(int, int));
int find_max(int x, int y);
int find_min(int x, int y);
int add(int x, int y);
int a = 34, b = -21, choose;
scanf("%d", &choose);
if(choose == 1)
printf("max = %d", fun(a,b, find_max));
else if(choose == 2)
printf("min = %d", fun(a, b, find_min));
else if (choose == 3)
printf("sum = %d", fun(a, b, add));
return 0;
}
int fun(int x, int y, int(*p)(int, int))
{
return (*p)(x, y);
}
int find_max(int x, int y)
{
if (x >= y)
return x;
else
return y;
}
int find_min(int x, int y)
{
if (x <= y)
return x;
else
return y;
}
int add(int x, int y)
{
return x + y;
}
返回指针值的函数
int *a(int x, int y);
理解:标题的名词是函数,a(int x, int y)是一个函数,返回类型为int星
//例8.25
int main()
{
float score[][4] = { 60,70,80,90,56,89,67,88,34,78,90,66 };
float* search(float (*p)[4], int n), p;
int n;
scanf("%d", &n);
for (int i = 0; i < 4; i++)
printf("%5.2f\t", *(search(score, n)+i));
return 0;
}
float* search(float (*p)[4], int n)//返回第n个学生第0门成绩的地址
{
return *(p + n);//p是行地址,+n加到了第n行地址,再*解引用得到n行0列地址
}
//例8.26
int main()
{
float score[][4] = { 60,70,80,90,56,89,67,88,34,78,90,66 };
float* search(float (*p)[4]);
for (int i = 0; i < 3; i++)
{
if (search(score + i))
{
printf("No:%d\n", i);
for (int j = 0; j < 4; j++)
printf("%f ", *(search(score + i) + j));
printf("\n");
}
}
return 0;
}
float* search(float (*p)[4])//p指向类型为1行float
{
for (int i = 0; i < 4; i++)
{
if (*(*p + i) < 60)//当前行i列的值
return *p;//返回当前行i列的地址
}
return NULL;
}
指针数组:int* p[4]
理解:p[4]定义一个数组,这个数组类型为int*
对比:int (*p)[4];
理解:用星p定义一个 指针变量p,它指向类型为4个int
//例8.27
int main()
{
void sort(char* name[], int n);
char* name[] = { "Follow me","BASIC","Great Wall","FORTRAN","Computer design" };
sort(name, 5);
for (int i = 0; i < 5; i++)
{
printf("%s\n", name[i]);
}
return 0;
}
void sort(char* name[], int n)
{
for(int i =0;i<n-1;i++)//每排序一个数要一个大循环
for (int j = i + 1; j < n; j++)//排这个数要从剩下的数中找更小的
{
if (strcmp(name[j], name[i]) < 0)
{
char* t = name[j];
name[j] = name[i];
name[i] = t;
}
}
}
//例8.28
int main()
{
void sort(char* name[], int n);
char* name[] = { "Follow me","BASIC","Great Wall","FORTRAN","Computer design" };
char** p;//指针的指针,name已经是存放指针的一个东西了,再多一个*就指向name
for (int i = 0; i < 5; i++)
{
p = name + i;//p指向name,name+i指向name的第i个元素,
printf("%s\n", *p);//解引用得到第i个元素的值,就是第i个字符串的地址
}
return 0;
}
//例8.29
int main()
{
int a[5] = { 1,3,5,7,9 };
char* num[5] = { &a[0],&a[1] ,&a[2] ,&a[3] ,&a[4] };
char** p = num;
for (int i = 0; i < 5; i++)
{
printf("%d ", **p++);//先**P,再p++
}
return 0;
}
动态内存分配与指向它的指针变量
全局变量分配在内存的静态存储区;(静态区)
局部变量分配在内存的动态存储区;(栈stack区)
C语言可以动态分配内存,随时弃用;(堆heap区)
void* malloc(unsigned int size);
函数名为malloc,返回类型为指针,指针指向类型为void;
功能:开辟1个长度为size的连续空间
void* calloc(unsigned, unsigned int size);
函数名为calloc,返回类型为指针,指针指向类型为void;
功能:开辟n个长度为size的连续空间
void* realloc(void 星p, unsigned int size);
函数名为realloc,返回类型为指针,指针指向类型为void;
功能:改p指向的内存空间大小为size,成功返回p,不成功返回空指针NULL
void free(void* p)
功能:释放p指向的动态空间
使用:int 星p = (int星)malloc(100);
解释:int *p定义指针变量p,指向类型为int,指向一个动态空间,指针变量的值为动态空间的首地址
malloc函数返回的是void星类型,不能直接引用;强制转换成int星方便引用
//例8.30
int main()
{
void check(int* p);
int* p = (int*)malloc(5 * sizeof(int));
//p[5] = { 67, 98,59,78,57 };//不合法;
p[0] = 67; p[1] = 98; p[2] = 59; p[3] = 78; p[4] = 57;
check(p);
return 0;
}
void check(int *p)
{
for (int *p_end = p + 5; p < p_end; p++)
if (*p < 60)
printf("%d ", *p);
}
一个指针包含3个信息:
1、他是指针类型
2、它的指向类型
3、指针变量的值(地址)
指针是地址,指针变量的值是地址
习题8
//1.2.
int main()
{
void sort_num(int* p);
void sort_str(char (*p)[4]);
int num[3] = { 9,3,6 };
char str[][4] = {"abc", "abb", "aaa"};
sort_num(num);
printf("%d %d %d", num[0], num[1], num[2]);
sort_str(str);
printf("\n%s\n%s\n%s\n", str[0], str[1], str[2]);
return 0;
}
void sort_num(int* p)//p指向num的首元素
{
int t;
if (*p > *(p + 1))//最小的放第0位
{
t = *p; *p = *(p + 1); *(p + 1) = t;
}
if (*p > *(p + 2))//最小的放第0位
{
t = *p; *p = *(p + 2); *(p + 2) = t;
}
if (*(p + 1) > *(p + 2))//次小的放第1位
{
t = *(p + 1); *(p + 1) = *(p + 2); *(p + 2) = t;
}
}
void sort_str(char (*p)[4])//选择法排序
{
char t[4];
for(int i = 0; i < 2; i++)
for(int j = i + 1; j < 3; j++)
if (strcmp(*(p + i), *(p + j)) > 0)//*(p + i)=p[i]=i行0列地址=第i行数组的首地址=第i个字符串名
{
strcpy(t, p[i]);
strcpy(p[i], p[j]);
strcpy(p[j], t);
}
}
//3.
int main()
{
void input(int* p);
void sort(int* p);
void output(int* p);
int num[10], *p = num;
input(p);
sort(p);
output(p);
return 0;
}
void input(int* p)
{
printf("输入10个数\n");
for (int* p_end = p + 10; p < p_end; p++)
scanf("%d", p);
}
void sort(int* p)
{
int t;
for (int i = 1; i < 10 ;i++)
{
if (*p > *(p + i))
{
t = *p;
*p = *(p + i);
*(p + i) = t;
}
}
for (int i = 0; i < 9; i++)
{
if (*(p + 9) < *(p + i))
{
t = *(p + 9);
*(p + 9) = *(p + i);
*(p + i) = t;
}
}
}
void output(int* p)
{
printf("输出10个数\n");
for (int* p_end = p + 10; p < p_end; p++)
printf("%d ", *p);
}
//4.
int main()
{
void move(int* p, int m, int n);
int num[10] = {1,3,5,7,9,0,2,4,6,8}, * p = num;
move(p, 3, 10);
for (int i = 0; i < 10; i++)
printf("%d ", num[i]);
return 0;
}
void move(int* p, int m, int n)
{
for (int i = 0; i < m; i++)//移动m个数
{
int t = *(p + n -1);
for (int j = n - 2; j >= 0; j--)
{
*(p + j + 1) = *(p + j);
}
*p = t;
}
}
//6.
int main() {
int str_len(char* str);
char str[] = "I love you.", * p = str;
printf("字符串长度为%d\n", str_len(str) );
return 0;
}
int str_len(char* str)
{
return strlen(str);
}
//7.
int main() {
char* str_copy(char* str, int m);
char str[] = "I LOve you.520**", * p = str;
printf("%s\n", str_copy(p, 3));
return 0;
}
char* str_copy(char* str, int m)
{
char* str2 = (char*)malloc((strlen(str + m) + 1) * sizeof(char));
strcpy(str2, str + m);
return str2;
}
//8.
int main() {
char str[] = "I LOve you.520**", * p = str;
int big = 0, small = 0, space = 0, num = 0, other = 0;
for (int i = 0; i < strlen(str); i++, p++)
{
if (*p >= 'A' && *p <= 'Z')
big++;
else if (*p >= 'a' && *p <= 'z')
small++;
else if (*p >= '0' && *p <= '9')
num++;
else if (*p == ' ')
space++;
else
other++;
}
printf("big = %d, small = %d, num = %d, space = %d, other = %d, ", big, small, num, space, other);
return 0;
}
//9.
int main() {
void trasn(int (*p)[3]);
int num[][3] = {1,3,5,7,9,0,2,4,6}, (*p)[3] = num;
printf("Orignal:\n");
for(int i = 0;i < 3; i++)
{
for (int j = 0;j < 3;j++)
{
printf("%d\t", num[i][j]);
}
printf("\n");
}
trasn(num);
printf("trasn:\n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d\t", num[i][j]);
}
printf("\n");
}
return 0;
}
void trasn(int (*p)[3])
{
for (int i = 0; i < 3; i++)
{
int t;
for (int j = i; j < 3; j++)
{
t = p[i][j];
p[i][j] = p[j][i];
p[j][i] = t;
}
}
}
//11.
int main()
{
void sort(char (*p)[3]);
char str[10][3] = { "dd","xx", "zz","aa", "tt","yy", "gg","ff", "ww","qq" };
sort(str);
for (int i = 0; i < 10; i++)
{
printf("%s\n", str[i]);
}
return 0;
}
void sort(char (*p)[3])
{
for(int i = 0;i < 9; i++)
{
char* t = (char*)malloc(3);
for (int j = i + 1; j < 10; j++)
{
if (strcmp(*(p + i), *(p + j)) > 0)
{
strcpy(t, *(p + i));
strcpy(*(p + i), *(p + j));
strcpy(*(p + j), t);
}
}
}
}
//12.
int main()
{
void sort(char (*p)[10]);
char str[10][10] = { "ers","xc", "weqr","joa", "afvds","cxz", "hgeruy","aacas", "ab","babf" };
sort(str);
for (int i = 0; i < 10; i++)
{
printf("%s\n", str[i]);
}
return 0;
}
void sort(char (*p)[10])
{
for(int i = 0;i < 9; i++)
{
char* t = (char*)malloc(10);
for (int j = i + 1; j < 10; j++)
{
if (strcmp(*(p + i), *(p + j)) > 0)
{
strcpy(t, *(p + i));
strcpy(*(p + i), *(p + j));
strcpy(*(p + j), t);
}
}
}
}
//14.
int main()
{
void sort(int* p);
int num[5] = { 1,2,3,4,5 };
sort(num);
for (int i = 0; i < 5; i++)
{
printf("%d\n", num[i]);
}
return 0;
}
void sort(int* p)
{
int t;
for(int i = 0;i < 5 / 2; i++)
{
t = p[i];
p[i] = p[4 - i];
p[4 - i] = t;
}
}
//15.
int main()
{
void f1(int(*p)[5]);
void f2(int(*p)[5]);
void f3(int(*p)[5]);
float a[4][5] = { 90,99,92,94,90,88,86,58,98,40,90,89,87,85,85,67,55,60,51,67 }, i, j, * p = &a[0][0];
f1(a);
f2(a);
f3(a);
return 0;
}
void f1(float(*p)[5])
{
float ave = 0;
for(int i = 0;i < 4; i++)
{
ave += *(*(p + i)) / 4;
}
printf("第1门平均分:%f\n", ave);
}
void f2(float(*p)[5])
{
for (int i = 0; i < 4; i++)
{
int flag = 0;
for (int j = 0; j < 5; j++)
{
if (*(*(p + i) + j) < 60)
flag++;
}
if (flag >= 2)
{
printf("学号:%d\n", i);
printf("全部课程成绩:%f %f %f %f %f\n", *(*(p + i) + 0), *(*(p + i) + 1), *(*(p + i) + 2), *(*(p + i) + 3), *(*(p + i) + 4));
printf("平均成绩:%f\n", (*(*(p + i) + 0)+ *(*(p + i) + 1)+ *(*(p + i) + 2)+ *(*(p + i) + 3)+ *(*(p + i) + 4) ) / 5);
}
}
}
void f3(float(*p)[5])
{
for (int i = 0; i < 4; i++)
{
float ave = 0;
bool flag = true;
for (int j = 0; j < 5; j++)
{
ave += *(*(p + i) + j) / 5;
}
if (ave >= 90)
{
printf("平均成绩90以上学号:%d\n", i);
}
for (int j = 0; j < 5; j++)
{
if (*(*(p + i) + j) < 85)
flag = false;
}
if (flag)
{
printf("全部成绩85以上学号:%d\n", i);
}
}
}
//16.
int main()
{
void f(char* p);
float a[4][5] = { 90,99,92,94,90,88,86,58,98,40,90,89,87,85,85,67,55,60,51,67 }, i, j, * p = &a[0][0];
char* str = "A123x456 17960? 302tab5876";
f(str);
return 0;
}
void f(char* p)
{
char t[10];
int a[5];
bool num_flag = 0;
for (int i = 0, j = 0, k = 0; p[i] != '\0'; i++)
if (p[i] >= '0' && p[i] <= '9')
{
t[j++] = p[i];
if(p[i+1] < '0' || p[i + 1] > '9' || p[i + 1] == '\0')
{
t[j] = '\0';
a[k++] = atoi(t);
j = 0;
}
}
for (int i = 0; i < 5; i++)
printf("%d\n", a[i]);
}
//17.
int main()
{
int strcmp_diy(char* p1, char* p2);
char str1[] = "BOY";
char str2[] = "BOYY";
printf("%d\n", strcmp_diy(str1, str2));
return 0;
}
int strcmp_diy(char *p1, char *p2)
{
int i = 0;
for (; p1[i] != '\0' && p2[i] != '\0'; i++)
{
if (p1[i] > p2[i])
return 1;
if (p1[i] < p2[i])
return -1;
if (p1[i] == p2[i])
continue;
}
if (p1[i] == '\0' && p2[i] == '\0')
return 0;
else if (p1[i] == '\0')//前面一样,但是p1短
return -1;
else if (p2[i] == '\0')//前面一样,但是p2短
return 1;
}
//18.
int main()
{
int n;
char month[13][20] = { "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }, *p[13];
for (int i = 0; i < 13; i++)
{
p[i] = month[i];//i行0列地址给指针数组
}
scanf("%d", &n);
printf("%s\n", p[n]);
return 0;
}
//19.
int main()
{
char* new(int n);
char* p = new(2);
p[0] = 'B'; p[1] = 'B';
printf("%c %c %c\n", *p, *(p + 1), *(p + 2));//*(p + 2)为没开辟存储空间时的值
free(p);
printf("%c %c\n", *p, *(p + 1));//释放后指向这两个地方的值恢复成 没开辟存储空间时的值
return 0;
}
//20.
int main()
{
void sort(char** p);
char str[][10] = {"abcd", "aaa", "abbbb", "acde", "aabb"}, * p[5];
for (int i = 0; i < 5; i++)
p[i] = str[i];
char** q = &p;
sort(q);
for (int i = 0; i < 5; i++)
{
printf("%s\n", *(q+i));
}
return 0;
}
void sort(char** p)//p是指针的指针,*p是指针,指针是地址,*p是地址,是字符串首元素地址,是字符串名
{
for (int i = 0; i < 4; i++)
{
char t[10];
for(int j = 0; j < 4 - i; j++)
if (strcmp(*(p + j), *(p + j + 1)) > 0)//*(p+j)是第j个字符串名
{
strcpy(t, *(p + j));
strcpy(*(p + j), *(p + j + 1));
strcpy(*(p + j + 1), t);
}
}
}
//21.
int main()
{
void sort(int** p, int n);
int n;
printf("input n:\n");
scanf("%d", &n);
int* p = (int*)malloc(n * sizeof(int));
printf("input n numbers:\n");
for (int i = 0; i < n; i++)
scanf("%d", &p[i]);
int** q = &p;
sort(q, n);
printf("Sorted:\n");
for (int i = 0; i < n; i++)
{
printf("%d ", p[i]);
}
return 0;
}
void sort(int** p, int n)
{
for (int i = 0; i < n - 1; i++)
{
int t;
for(int j = 0; j < n - 1 - i; j++)
if ((*p)[j] > (*p)[j + 1])
{
t = (*p)[j];
(*p)[j] = (*p)[j + 1];
(*p)[j + 1] = t;
}
}
}