一、数组与指针
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=0
return 0;
}
}
}
if(found==0)
printf("no\n");
else
printf("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 7
int 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 7
int 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的阶乘为1
return 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=3
while (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的长度必须足够容纳str2
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;
}
法二:用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] = ' ';
else
s1[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 0001
int b=255;//0000 0000 1111 1111
if((a|b)==255){
printf("高位补0");
}
else{
printf("高位补1");
}
return 0;
}
将x=1文章来源:https://www.toymoban.com/news/detail-618525.html
可知:负数较短高位补1,正数较短高位补0文章来源地址https://www.toymoban.com/news/detail-618525.html
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') //除去前置0
flag = 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;
}
到了这里,关于厦大2021届大一小学期C语言作业1 数组+字符串+指针+位操作的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!