文章目录
一、数组与指针1.手搓冒泡排序(从大到小)2.矩阵的转置和打印3.判断矩阵是否对称4.最大元素与最后元素互换(用指针)5.首地址偏移法逆序排序6.指针移动法逆序排序7.用元素指针实现输出二维数组中全部元素8.用行指针输出二维数组9.1用有返回值的函数求n!(要求保留6位小数)9.2用无返回值函数求n!(要求保留6位小数)10.手写strcat11.求最短路径数12.有障碍求最短路径13.原地顺时针旋转矩阵90°14.螺旋输出矩阵二. 字符串与指针1.用字符指针变量输出字符串2.手写strcpy3.实现字符串拼接4.实现字符串的逆序输出5.统计字符串中数字的个数,并且输出数字6.统计字符串中单词个数7.字符替换。要求用函数replace将用户输入的字符串中的字符t(T)都替换为e(E),并返回替换字符的个数。8.编写一个程序,输入星期,输出该星期的英文名。用指针数组处理9.有5个字符串,首先将它们按照字符串中的字符个数由小到大排列, 再分别取出每个字符串的第三个字母合并成一个新的字符串输出(若少于三个字符的输出空格)。要求:利用字符串指针和指针数组实现。10.**长度为n的动态数组,用随机数给数组赋值,然后排序,定义swap函数交换数据,要求参数使用指针传递。**补充知识:C语言中随机数的生成三.位操作1.验证负数右移为高位补0或补12. 长度较短的负数整数与正整数逻辑位运算时,本系统为高位补0,还是高位补13. 输入一个十进制整数(正、负),转换为十六进制显示,即实现`printf(“%x”,x)`的功能,但不能用这个函数,也不能用算术运算符,只能用位操作符。4. 输入一个十进制整数(正、负),转换为二进制显示,不能用算术运算符,只能用位操作符。一、数组与指针
1.手搓冒泡排序(从大到小)
题目描述:
1.程序要求:实现对5个数(a[0]~a[4],数组元素从键盘读入)进行从大到小起泡法排序。输入第一组数据:1 2 3 4 5;输入第二组数据:3 5 4 1 2;验证程序的正确性。
#include<stdio.h>int main(){int a[5]={0};for(int i=0;i<5;i++)scanf("%d",&a[i]);int i,j,k;for(int k=0;k<=3;k++)//冒泡排序{for(i=3,j=4;i>=k;i--,j--){if(a[i]<a[j]){int t=a[i];a[i]=a[j];a[j]=t;}}}for(int i=0;i<5;i++)//打印printf("%d ",a[i]);return 0;}
2.矩阵的转置和打印
题目描述:
2.程序要求:实现三阶方阵转置,并打印转置后的方阵。
测试主函数为:
int main()
{
int a[3][3]={1,2,3,4,5,6,7,8,9};
…//实现三阶方阵a的转置,并打印出来
return 0;}
转置原理:
用k同时标记和a[k,0]
a[0,k]
,又因为对角线上的元素无需转置,即可以(k,0)(0,k)延长线的交点a[k,k]
为基准,从横向纵向同时逼近,即可保证指向的两个数组元素对称,再交换,即可完成转置。
#include<stdio.h>int main(){int a[3][3]={0};int k,i;for(k=0;k<3;k++)//输入矩阵{for(i=0;i<3;i++)scanf("%d",&a[k][i]);}for(k=1;k<3;k++)//转置操作{for(i=0;i<k;i++){int t=a[k][i];a[k][i]=a[i][k];a[i][k]=t;}}for(k=0;k<3;k++)//打印{for(i=0;i<3;i++)printf("%d ",a[k][i]);putchar('\n');}return 0;}
3.判断矩阵是否对称
程序要求:检查一个方阵是否关于主对角线对称。若不是,输出”no”;若是,输出”yes”。
测试主函数为:
int main()
{
int a[ ][4]={0,1,2,3,1,4,5,6,2,5,7,8,3,6,8,9};
int found=1;
…//判断方阵是否为对称阵,若不是,found置为0
if (found==0)
printf(“no\n”);
else
printf(“yes\n”);
return 0;}
与题2思路相同,对角线无需判断
#include<stdio.h>int main(){int n,found=1;scanf("%d",&n); int a[4][4]={0};int k,i;for(k=0;k<n;k++)//输入{for(i=0;i<n;i++)scanf("%d",&a[k][i]);}for(k=1;k<n;k++)//判断{for(i=0;i<k;i++){if(a[k][i]!=a[i][k]){found=0; //只要有一个不满足就令found=0return 0;}}}if(found==0)printf("no\n");elseprintf("yes\n");return 0;}
4.最大元素与最后元素互换(用指针)
题目描述:
4.程序要求:找到数组中最大的元素,将它和最后一个元素对调。并将元素对调后的数组打印出来。(以上功能均要求用指针实现)
测试主函数为:
int main()
{ int num[5]={1,3,5,4,2};
…
return 0;
}
#include<stdio.h>int main(){int num[5];for(int i=0;i<5;i++)scanf("%d",&num[i]);int max=-0x3f3f3f;int *p1,*p2;for(p1=num;p1<num+4;p1++)//选出最大元素{if(*p1>max){max=*p1;p2=p1;}}int t=*p2;*p2=*(num+4);*(num+4)=t;for(int i=0;i<5;i++)printf("%d ",num[i]);return 0;}
5.首地址偏移法逆序排序
题目描述:
用指针(首地址偏移法)实现将存放在数组中的一组数据按逆序重排,并打印重排后的数组。
测试主函数为:
#define N 7
int main( )
{int a[N]={1, 2, 3, 4, 11, 12, 13};
…
return 0;
}
*(a+1)
#include<stdio.h>#define N 7int main(){int a[N]={0};int i,j;for(int i=0;i<N;i++){scanf("%d",&a[i]);}for(i=0,j=N-1;i<j;i++,j--)//首地址偏移法 {int t=*(a+i);*(a+i)=*(a+j);*(a+j)=t;}for(int i=0;i<N;i++){printf("%d ",a[i]);}return 0;}
6.指针移动法逆序排序
题目描述:
用指针移动法实现将存放在数组中的一组数据按逆序重排,并打印重排后的数组。
测试主函数为:
#define N 7
int main( )
{int a[N]={1, 2, 3, 4, 11, 12, 13};
…
return 0;
}
int *p
p=a
#include<stdio.h>#define N 7int main(){int a[N]={0};int i;int *p1,*p2;for(int i=0;i<N;i++){scanf("%d",&a[i]);}for(p1=a,p2=a+6;p1<p2;p1++,p2--){int t=*p1;*p1=*p2;*p2=t;}for(int i=0;i<N;i++){printf("%d ",a[i]);}return 0;}
7.用元素指针实现输出二维数组中全部元素
题目描述:
用元素指针实现输出二维数组中的全部元素。
测试主函数为:
int main( )
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
…
return 0;}
#include<stdio.h>int main(){int a[3][4];int i,j;for(i=0;i<3;i++){for(j=0;j<4;j++){scanf("%d",&a[i][j]);}}int *p=a[0];//指针指向第0行第一个元素for(;p<=&a[2][3];p++){printf("%d ",*p);}return 0;}
8.用行指针输出二维数组
题目描述:
用行指针实现输出二维数组中的全部元素。
测试主函数为:
int main( )
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
…
return 0;}
#include<stdio.h>int main(){int a[3][4];int i,j;for(i=0;i<3;i++){for(j=0;j<4;j++){scanf("%d",&a[i][j]);}}int (*p)[4]=&a[0];//或=a;for(;p<=a+2;p++){for(int i=0;i<4;i++)printf("%d ",*(*p+i));}return 0;}
9.1用有返回值的函数求n!(要求保留6位小数)
题目描述:
程序功能:fac函数通过指针返回n!,主函数定义指针,调用fac函数,打印结果。分别用两种方法实现fac,程序要求如下:
(1)定义fac为有返回值函数,结果通过return语句返回主函数;
(2)定义fac为无返回值函数,结果通过指针间接访问法访问主函数中的变量。
测试主函数为:
void main( )
{ int m;
float k;
printf(“input m:”);
scanf(“%d”,&m);
…fac(…);//要求fac函数实现k=m!
printf(“result=%f”,k);
}
#include<stdio.h>float fac(int n);int main(){int m;float k;printf("input m:");scanf("%d",&m);k=fac(m);printf("result=%f\n",k);/*int n;float l;printf("input n:");scanf("%d",&n);l=fac(n);printf("result=%f\n",l);*///测试是否能在int中重复使用 return 0;}float fac(int n){if(n<0){printf("Erro!");return 0;}if(n==0)//0的阶乘为1 return 1;else{return n*fac(n-1);}}
9.2用无返回值函数求n!(要求保留6位小数)
#include<stdio.h>void fac(int n,float *x);int main(){int m;float k;printf("input m:");scanf("%d",&m);k=m;fac(m,&k);printf("result=%f",k);/*int n;float l;printf("input n:");scanf("%d",&n);l=n;fac(n,&l);printf("result=%f\n",l);*///测试是否能在int中重复使用 return 0;}void fac(int n,float *x){if(n!=1){*x=(*x)*(n-1);fac(n-1,x);}}
10.手写strcat
题目描述:
编写函数strcat,实现两个字符串的连接,返回值为连接后字符串的首地址。
测试主函数为:
void main()
{ char str1[30] = “I learn “, *str2 = “C language.”;
char *s;
s = strcat(str1,str2);//strcat函数的返回值是指针 printf(”%s\n”, s); }
#include<stdio.h>char *strcat(char *s1,char *s2);int main(){char str1[30]={0}, *str2="C language.";gets(str1);char *s;s=strcat(str1,str2);printf("%s\n",s);return 0;}char *strcat(char *s1,char *s2){char *p1=s1,*p2=s2;while(*p1!='\0')p1++;while((*p1++=*p2++)!='\0'){;}return s1;}
11.求最短路径数
题目描述:
一个机器人位于一个 m x n 网格的左上角(起始点在下图中标记为“Start”)。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。问总共有多少条不同的路径?
示例 :
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
向右 -> 向右 -> 向下向右 -> 向下 -> 向右向下 -> 向右 -> 向右
测试主函数:
int uniquePaths(int m, int n) {
…//补充函数,返回路径数
}
int main(){
int m=3,n=2;
int k=uniquePaths(m,n);
printf(“共有%d条路径”,k);
return 0;
}
共有m行n列,机器人一共需要向由移动n-1步,向下移动m-1步,故最短路径数为
=(m+n-2)!/((m-1)!*(n-1)!)
#include<stdio.h>int fac(int n);int uniquePaths(int x,int y); int main(){int m,n;scanf("%d%d",&m,&n);int k=uniquePaths(m,n);printf("共有%d条路径",k);return 0;}int uniquePaths(int x,int y){return fac(x+y-2)/(fac(x-1)*fac(y-1));}int fac(int n){if(n<0){printf("Erro!");return 0;}if(n==0)//0的阶乘为1 return 1;else{return n*fac(n-1);}}
12.有障碍求最短路径
题目描述:
一个机器人位于一个 m x n 网格的左上角,机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角。现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
说明:m 和 n 的值均不超过 100。
示例 1:
输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
向右 -> 向右 -> 向下 -> 向下
向下 -> 向下 -> 向右 -> 向右
参考答案:
int uniquePathsWithObstacles(int* obstacleGrid, int obstacleGridRowSize, int obstacleGridColSize){
…//补充函数,返回路径数
}
int main(){
int a[3][3]={0,0,0,0,1,0,0,0,0};
int k=uniquePathsWithObstacles(a[0],3,3);
printf(“共有%d条路径”,k);
return 0;
}
k1:从起点到终点路径数
k2:从起点到障碍路径数
k3:从障碍到终点路径数
k2*k3:机器人若经过障碍的路径数
k1-k2*k3:机器人不经过障碍的路径数
#include<stdio.h>int uniquePathsWithObstacles(int* obstacleGrid, int obstacleGridRowSize, int obstacleGridColSize);int uniquePaths(int x, int y);int fac(int n);int main(){int a[3][3];for(int i=0;i<3;i++){for(int j=0;j<3;j++){scanf("%d",&a[i][j]);}}int k=uniquePathsWithObstacles(a[0],3,3);printf("共有%d条路径",k);return 0;}int uniquePathsWithObstacles(int* obstacleGrid, int obstacleGridRowSize, int obstacleGridColSize){int p,q;int k1,k2,k3;for(int i=0;i<obstacleGridColSize*obstacleGridRowSize;i++){if(*(obstacleGrid+i)==1){p=(i/obstacleGridRowSize);q=i%obstacleGridRowSize;break;}}k1=uniquePaths(obstacleGridRowSize,obstacleGridColSize);k2=uniquePaths(p+1,q+1);k3=uniquePaths(obstacleGridRowSize-p,obstacleGridColSize-q);return k1-(k2*k3);}int uniquePaths(int x, int y) {//路径数int z = x + y - 2;return fac(z) / (fac(x - 1) * fac(y - 1));}int fac(int n) {//n的阶乘if (n < 0) {printf("Error!");return 0;}if (n == 0) //0的阶乘为1return 1;else {return n * fac(n - 1);}}
13.原地顺时针旋转矩阵90°
题目描述:
给定一个 n × n 的二维矩阵表示一个图像,将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
示例 1:
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
参考答案:
void rotate(int* matrix, int matrixRowSize, int matrixColSize){
…//补充函数,实现原地旋转功能
}
int main(){
int a[3][3]={1,2,3,4,5,6,7,8,9};
rotate(a[0],3,3);
int *p; for(p=a[0];p<a[0]+9;p++) { if((p-a[0])%3==0) printf("\n"); printf("%4d",*p); } return 0;
}
先将矩阵转置,后左右对称,即可使矩阵原地顺时针旋转90°
#include<stdio.h>int main() {int n, i, j, k;scanf("%d", &n);int a[n][n] = {0};for (int i = 0; i < n; i++) {//输入矩阵for (int j = 0; j < n; j++)scanf("%d", &a[i][j]);}for (int i = 1 ; i < n; i++) {//转置操作for (int j = 0; j < i; j++) {int t = a[i][j];a[i][j] = a[j][i];a[j][i] = t;}}for (int i = 0; i < n; i++) {//左右对称for (j = 0, k = n - 1; j < k; j++, k--) {int t = a[i][j];a[i][j] = a[i][k];a[i][k] = t;}}for (int i = 0; i < n; i++) {//打印矩阵for (int j = 0; j < n; j++)printf("%d ", a[i][j]);putchar('\n');}return 0;}
14.螺旋输出矩阵
题目描述:
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
示例:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]
参考答案:
int* spiralOrder(int* matrix, int matrixRowSize, int matrixColSize){
…//补充函数,返回结果(一维数组)的首元素指针
}
int main(){
int a[3][3]={1,2,3,4,5,6,7,8,9};
int matrixRowSize=3,matrixColSize=3;
int *returnnum=spiralOrder(a[0], matrixRowSize, matrixColSize);
int *p;
for(p=returnnum;p<returnnum+9;p++)
{
printf(“%4d”,*p);
}
return 0;
}
#include<stdio.h>int* spiralOrder(int matrix[50][50], int m, int n);int b[1000] = {0};//在全局命名。在自定义函数中命名的话,函数运行结束,数组空间就被释放了int main() {int a[50][50] = {0};int m, n;scanf("%d%d", &m, &n);int i, j;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {scanf("%d", &a[i][j]);}}int *returnnum = spiralOrder(a, m, n);int *p;for (p = returnnum; p < returnnum +m*n; p++) {printf("%4d", *p);}return 0;}int* spiralOrder(int matrix[50][50], int m, int n) {//顺时针螺旋输出函数int i, j;int p = n, q = m;int count = 0;//已输出个数int length;for (i = 0, j = 0; j < n; ++j) {//第一次向右b[count++] = matrix[i][j];}j -= 1; //for循环结束后j=3while (1) {i += 1; //转角避免重复输入for (length = 0; ; ++i) {//向下b[count++] = matrix[i][j];length++;if (length == q - 1)break;}if (count == m * n)break;q--;j -= 1;for (length = 0; ; j--) {//向左b[count++] = matrix[i][j];length++;if (length == p - 1)break;}if (count == m * n)break;p--;i -= 1;for (length = 0;; i--) {//向上b[count++] = matrix[i][j];length++;if (length == q - 1)break;}if (count == m * n)break;q--;j += 1;for (length = 0; ; j++) {//向右b[count++] = matrix[i][j];length++;if (length == p - 1)break;}if (count == m * n)break;p--;}return b;}
二. 字符串与指针
1.用字符指针变量输出字符串
#include<stdio.h>int main(){char str1[50]={0};//"I love China"gets(str1);char *p1=str1;printf("%s",p1);return 0;}
2.手写strcpy
#include<stdio.h>char* strcpy(char *y,char *x);int main() {char a[50] = {0};char b[50] = {0};gets(a);strcpy(b,a);printf("%s",b);return 0;}char* strcpy(char *y,char *x){char *p=y;while((*(y++)=*(x++))!='\0'){;}return p;}
3.实现字符串拼接
法一
#include<stdio.h>char *strcat(char *s1, char *s2);int main() {char str1[30] ="I love ",*str2= "China";//str1的长度必须足够容纳str2char *s;s = strcat(str1, str2);printf("%s\n", s);return 0;}char *strcat(char *s1, char *s2) {char *p1 = s1, *p2 = s2;while (*p1 != '\0')p1++;while ((*(p1++) = *(p2++)) != '\0') {;}return s1;}
法二:用malloc
4.实现字符串的逆序输出
#include<stdio.h>#include<string.h>int main(){char str[50]={0};gets(str);char *p=str+strlen(str)-1;while(*p!='\0'){putchar(*p);p--;}return 0;}
5.统计字符串中数字的个数,并且输出数字
#include<stdio.h>#include<ctype.h>#include<string.h>int main() {char s[50] = {0};gets(s);int sum = 0;for (int i = 0; i < strlen(s); i++) {if (isdigit(s[i])) {sum++;printf("%c ", s[i]);}}return 0;}
6.统计字符串中单词个数
#include<stdio.h>#include<string.h>int main(){char str[10001]={0};gets(str);int sum=0;for(int i=0;i<strlen(str);i++){if(str[i]==' ')sum++;}if(strlen(str)!=0)sum+=1;printf("%d",sum);return 0;}
7.字符替换。要求用函数replace将用户输入的字符串中的字符t(T)都替换为e(E),并返回替换字符的个数。
#include<stdio.h>#include<string.h>int repalce(char *st,int lenth);int main(){char s[10001]={0};gets(s);int change=repalce(s,strlen(s));puts(s);printf("\n%d",change);return 0;}int repalce(char *str,int lenth){char *p=str;int sum=0;for(;p<str+lenth;p++){if(*p=='t'||*p=='T'){*p-=15;//根据ASC码可知sum++;}}return sum;}
8.编写一个程序,输入星期,输出该星期的英文名。用指针数组处理
#include<stdio.h>int main() {char s[7][50] = {"Monday", "Tuesday", "Wednesday", "Thurday", "Friday", "Saturday", "Sunday"};int i;char (*p)[50] = &s[0];printf("请输入星期:\n");scanf("%d", &i);printf("%s\n", *(p + i - 1));}
9.有5个字符串,首先将它们按照字符串中的字符个数由小到大排列, 再分别取出每个字符串的第三个字母合并成一个新的字符串输出(若少于三个字符的输出空格)。要求:利用字符串指针和指针数组实现。
#include<stdio.h>#include<string.h>#include<stdlib.h>int cmp(const void *a, const void *b);int main() {char s[5][10] = {0};char s1[6] = {0};for (int i = 0; i < 5; i++)gets(s[i]);qsort(s, 5, sizeof(s[0]), cmp); //将二维数组看成,每一行为一个元素的一维数组for (int i = 0; i < 5; i++) {if (strlen(s[i]) < 3)s1[i] = ' ';elses1[i] = s[i][2];}for (int i = 0; i < 5; i++)puts(s[i]);puts(s1);return 0;}int cmp(const void *a, const void *b) {return strlen((char *)a) > strlen((char *)b); //原本无类型}
10.长度为n的动态数组,用随机数给数组赋值,然后排序,定义swap函数交换数据,要求参数使用指针传递。
补充知识:C语言中随机数的生成
#include<stdlib,h>#include<stdio.h>int main(){unsigned int seed;//随机数种子scanf("%d",&seed);srand(seed);int number=rand()%100;//产生一百以内的随机数}
#include<stdio.h>#include<stdlib.h>void array(int *s, int length);void swap(int m, int n);int main() {int n;unsigned int seed;scanf("%d", &n);int number[n];scanf("%d", &seed);for (int i = 0; i < n; i++) {//随机数赋值number[i] = rand() % 1000;//1000以内的随机数}array(number, n);for (int i = 0; i < n; i++) {//打印printf("%d ",number[i]);}return 0;}void array(int *s, int length) {//冒泡排序for (int i = 0; i < length - 1; i++) {for (int j = i + 1; j < length; j++) {if (*(s + j) < * (s + i))swap(*(s + j), *(s + i));}}}void swap(int m, int n) {//交换int t = m;m = n;n = t;}
三.位操作
1.验证负数右移为高位补0或补1
#include<stdio.h>int main(){short int x=-10;x>>2;short int y=63;if((x|y)==63){printf("系统为逻辑右移");//高位补0}else{printf("系统为算术右移");//高位补1}return 0;}
将x=10
可知:负数右移高位补1,正数右移高位补0
2. 长度较短的负数整数与正整数逻辑位运算时,本系统为高位补0,还是高位补1
#include<stdio.h>int main(){short int a=-1;//1000 0001int b=255;//0000 0000 1111 1111if((a|b)==255){printf("高位补0");}else{printf("高位补1");}return 0;}
将x=1
可知:负数较短高位补1,正数较短高位补0
3. 输入一个十进制整数(正、负),转换为十六进制显示,即实现printf(“%x”,x)
的功能,但不能用这个函数,也不能用算术运算符,只能用位操作符。
#include<stdio.h>int main() {long int a,b = 15;scanf("%ld", &a);char s[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};char s2[4] = {0};int flag = 0;for (int i = 0; i < 4; i++) {s2[i] = s[a & b]; //每次将a最后一个字节转为16进制a >>= 4;}for (int i = 4; i >= 0; i--) {//倒序输出if (s2[i] != '0') //除去前置0flag = 1;if (flag == 1)putchar(s2[i]);}return 0;}
4. 输入一个十进制整数(正、负),转换为二进制显示,不能用算术运算符,只能用位操作符。
#include<stdio.h>int main(){long int a;scanf("%ld",&a);char s[16]={0};char s2[2]={'0','1'};long int b=1;for(int i=0;i<16;i++){s[i]=s2[a&b];a>>=1;}for(int i=16;i>=0;i--){putchar(s[i]);}return 0;}