不知道大家最近有没有被ChatGPT刷屏啊,作为一个语言模型,可以调教成你的形状…啊不对,调教成你想让它成为的样子,非常好玩。我有尝试着让它帮忙写咱的C语言作业,效果还是很不错的,可以看来看看。
目录
上机实验
6-11 统计字符出现次数
6-12 字符串逆序
6-13 字符串字母大小写转换
6-14 矩阵各行元素之和
6-15 阵运算
6-16 找鞍点
6-17 期末分数排序
6-18 选择法排序
6-19 找出不是两个数组共有的元素
6-20 打印杨辉三角
结语
上机实验
6-11 统计字符出现次数
本题要求编写程序,统计并输出某给定字符在给定字符串中出现的次数。
输入格式:
输入第一行给出一个以回车结束的字符串(少于80个字符);第二行输入一个字符。
输出格式:
在一行中输出给定字符在给定字符串中出现的次数。
输入样例:
programming is More fun!
m
输出样例:
2
很简单的题目,遍历字符串即可。这种题目丢给ChatGPT做会怎么样呢?我们试试:
结果非常的有趣,它完美地输出了这一个程序,并且使用了 string.h 内的函数 gets() !既然出现了gets()那我们就说说吧。这个函数输入一个char指针,即字符串头指针。函数会在输入缓冲区读一条字符串,存入这个指针的位置。详细的说明可以看这里。
直接回复没有缩进,看着难受,但是没关系,现在很多功能强大的IDE都能帮我们完成代码格式化。我们测试无误之后就能将这一段代码当作我们的作业了(
#include <stdio.h>
#include <string.h>int main()
{char a[100], b;int i, sum = 0;gets(a);scanf("%c", &b);for (i = 0; i < strlen(a); i++){if (a[i] == b)sum++;}printf("%d\n", sum);return 0;
}
好!很有精神!
6-12 字符串逆序
本题要求编写程序,输入一个字符串,对该字符串进行逆序,输出逆序后的字符串。
输入格式:
输入在一行中给出一个不超过80个字符长度的、以回车结束的非空字符串。
输出格式:
在一行中输出逆序后的字符串。
输入样例:
Hello World!
输出样例:
!dlroW olleH
也是很简单,只需要找到字符串的结尾就行了。同样的,我们再拿ChatGPT来试试:
#include <stdio.h>
#include <string.h>int main()
{char a[100];int i;gets(a);for (i = strlen(a) - 1; i >= 0; i--)printf("%c", a[i]);return 0;
}
可以看到,在这一段程序中,出现了另一个函数 strlen() 。这个函数是读取字符串长度。为防止混淆,在这里说一下strlen和sizeof的区别。
sizeof返回的是整个堆的长度,也就是已分配内存的长度。在这个例子内,sizeof(a)返回的值为100;而strlen计算的是从开始到字符串结束,也就是到‘\0’的长度。所以它们两个的返回值并不一样。
了解了strlen之后,我们很容易就明白,程序是倒序的单个字符打印。
6-13 字符串字母大小写转换
本题要求编写程序,对一个以“#”结束的字符串,将其小写字母全部转换成大写字母,把大写字母全部转换成小写字母,其他字符不变输出。
输入格式:
输入为一个以“#”结束的字符串(不超过50个字符)。
输出格式:
在一行中输出大小写转换后的结果字符串。
输入样例:
Hello World! 123#
输出样例:
hELLO wORLD! 123
这一题也是非常简单。在看到题目之后直接就能注意到,大写字母和小写字母的ASCII码的范围并不一样,并且遵循某种转化关系。只需要判断字符的大小,并计算即可。这部分的代码如下:
#include <stdio.h>
#include <string.h>int main()
{char a[100];int i;gets(a);for (i = 0; i < strlen(a) && a[i] != '#'; i++){if (a[i] >= 'a' && a[i] <= 'z')printf("%c", a[i] - 32);else if (a[i] >= 'A' && a[i] <= 'Z')printf("%c", a[i] + 32);elseprintf("%c", a[i]);}return 0;
}
但是,有没有更简单的方法呢?当然有!ChatGPT给出了这样的方法:
#include <stdio.h>
#include <string.h>
#include <ctype.h>int main()
{char a[100];int i;gets(a);for (i = 0; i < strlen(a) && a[i] != '#'; i++){if (isupper(a[i]))printf("%c", tolower(a[i]));else if (islower(a[i]))printf("%c", toupper(a[i]));elseprintf("%c", a[i]);}return 0;
}
可以注意到,这里多用了一个头文件<ctype.h>。尖括号表示这是C语言标准头文件,也就是正常的编译器都会自带的头文件。
这里有两对、四个新的函数"isupper" "tolower" "islower" "toupper"。
这四个函数的意思就和字面上一样,判断是否为大写字母、将大写字母转换成小写字母、判断是否为小写字母、将小写字母转换为大写字母。可以看到,用了这个函数能稍微简化一点点开始我们所写的代码。
6-14 矩阵各行元素之和
本题要求编写程序,求一个给定的m×n矩阵各行元素之和。
输入格式:
输入第一行给出两个正整数m和n(1≤m,n≤6)。随后m行,每行给出n个整数,其间以空格分隔。
输出格式:
每行输出对应矩阵行元素之和。
输入样例:
3 2
6 3
1 -8
3 12
输出样例:
9-7
15
这题也是并不复杂。首先将头两位数字保存,作为后续循环的循环次数;然后开始循环,每次循环只读一位,读完缓冲区为止。
代码如下:
#include <stdio.h>int main()
{int m, n, i, j, a[10][10], sum;scanf("%d%d", &m, &n);for (i = 0; i < m; i++){sum = 0;for (j = 0; j < n; j++){scanf("%d", &a[i][j]);sum = sum + a[i][j];}printf("%d\n", sum);}return 0;
}
6-15 阵运算
本题要求编写程序,给定一个n×n的方阵,计算该矩阵除副对角线、最后一列和最后一行以外的所有元素之和。副对角线为从矩阵的右上角至左下角的连线。
输入格式:
输入第一行给出正整数n(1<n≤10);随后n行,每行给出n个整数,其间以空格分隔。
输出格式:
在一行中给出该矩阵除副对角线、最后一列和最后一行以外的所有元素之和。
输入样例:
4
2 3 4 1
5 6 1 1
7 1 8 1
1 1 1 1
输出样例:
35
这一题也并不复杂,只需要遍历二维数组,再判断当前的数是否符合条件即可。代码如下:
#include <stdio.h>int main()
{int a[11][11], n, i, j, sum = 0;scanf("%d", &n);for (i = 1; i <= n; i++)//录入部分for (j = 1; j <= n; j++)scanf("%d", &a[i][j]);for (i = 1; i <= n; i++)//计算部分for (j = 1; j <= n; j++){if (i != n && j != n && j != n - i + 1)sum += a[i][j];}printf("%d", sum);return 0;
}
6-16 找鞍点
本题要求编写程序,求一个给定的n阶方阵的鞍点。一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。
输入格式:
输入第一行给出一个正整数n(1≤n≤6)。随后n行,每行给出n个整数,其间以空格分隔。
输出格式:
输出在一行中按照“行下标列下标”(下标从0开始)的格式输出鞍点的位置。如果鞍点不存在,则输出“NONE”。题目保证给出的矩阵至多存在一个鞍点。
输入样例1:
4
1 7 4 1
4 8 3 6
1 6 1 2
0 7 8 9
输出样例1:
2 1
输入样例2:
2
1 7
4 1
输出样例2:
NONE
这题的重点在于,如何固定二维数组的某一位而遍历另一位。一种实现方法如下:
#include <stdio.h>int main()
{int a[10][10], n, i, j, max, k, flag = 0;scanf("%d", &n);for (i = 0; i < n; i++)//数据录入for (j = 0; j < n; j++)scanf("%d", &a[i][j]);for (i = 0; i < n; i++){max = a[i][0];k = 0;for (j = 1; j < n; j++)if (a[i][j] > max){max = a[i][j];k = j;}for (j = 0; j < n; j++)if (a[j][k] < max)break;if (j == n){printf("%d %d", i, k);flag = 1;break;}}if (flag == 0)printf("NONE");return 0;
}
6-17 期末分数排序
本题要求编写程序,考试结束了,全班同学的分数都出来了。老师需要对分数做一次排序,看看从高到低,分数的排列是怎样的。
输入格式:
第一行是一个n,表示班级同学的人数,1<=n<=5000。第二行开始有n个分数,0<=分数<=100,分数都是整数,没有零点五分。
输出格式:
输出排序后的分数,按照从大到小排列,相同的分数排在一起,每两个分数之间间隔一个空格。
输入样例:
10
0 60 73 60 82 90 100 18 55 84
输出样例:
100 90 84 82 73 60 60 55 18 0
这题我们可以用冒泡排序。冒泡排序老师上课有讲过,咱便不再赘述了。直接看代码吧:
#include <stdio.h>#define SWAP(a, b) \{ \int temp = a; \a = b; \b = temp; \}int main()
{int a[5000], n, i, j;scanf("%d", &n);for (i = 1; i <= n; i++)scanf("%d", &a[i]);
//****************************************************冒泡排序本体for (i = 1; i <= n; i++)for (j = 1; j <= n - i; j++)if (a[j] < a[j + 1])SWAP(a[j], a[j + 1]);
//****************************************************for (i = 1; i <= n; i++)printf("%d%c", a[i], i == n ? '\n' : ' ');return 0;
}
可以看到这里有几行我们不曾见过的写法,我们来看看。
首先是第三行的define定义函数。这种写法的好处是,它可以直接完成一种类似函数的效果,但是却能调用外面一级函数内的局部变量。或者说,在C语言中,使用#define定义的宏是不占用内存空间的。在使用#define定义宏时,编译器会把宏展开为该宏定义的内容,但不会为宏开辟内存空间。例如:
#define SWAP(a,b) {int temp=a;a=b;b=temp;}
这个宏定义的作用是实现两个变量的交换,但在程序运行时,并不会为宏开辟内存空间。
那么如何完成多行的宏定义呢?很简单,在行尾加 '\' 即可。于是,就有了我们代码的3~8行。
这种实现过程不用宏定义则需要借助指针。例如:
void swap(int *a, int *b)
{int temp = *a;*a = *b;*b = temp;
}
上面的swap函数也实现了两个变量的交换,在函数被调用时,编译器会为该函数开辟内存空间,在该函数运行时,系统会把函数所需的参数和变量放到这段内存中,运行完后再释放掉。
6-18 选择法排序
本题要求编写程序,将给定的n个整数从大到小排序后输出。
输入格式:
输入第一行给出一个不超过100的正整数n。第二行给出n个整数,其间以空格分隔。
输出格式:
在一行中输出从大到小有序的数列,相邻数字间有一个空格,行末不得有多余空格。
输入样例:
4
5 1 7 6
输出样例:
7 6 5 1
选择排序也是讲过的,我们用同样的办法swap就可以了:
#include <stdio.h>#define SWAP(a, b) \{ \int temp = a; \a = b; \b = temp; \}int main()
{int a[100], n, i, j, k;scanf("%d", &n);for (i = 0; i < n; i++)scanf("%d", &a[i]);for (i = 0; i < n; i++){k = i;for (j = i; j < n; j++)if (a[j] > a[k])k = j;//找出最大的SWAP(a[i], a[k]);}for (i = 0; i < n; i++)printf("%d%c", a[i], i == n ? '\n' : ' ');return 0;
}
6-19 找出不是两个数组共有的元素
本题要求编写程序,给定两个整型数组,找出不是两者共有的元素。
输入格式:
输入分别在两行中给出两个整型数组,每行先给出正整数N(≤20),随后是N个整数,其间以空格分隔。
输出格式:
在一行中按照数字给出的顺序输出不是两数组共有的元素,数字间以空格分隔,但行末不得有多余的空格。题目保证至少存在一个这样的数字。同一数字不重复输出。
输入样例:
10 3 -5 2 8 0 3 5 -15 9 100
11 6 4 8 2 6 -5 9 0 100 8 1
输出样例:
3 5 -15 6 4 1
这一题很简单,嵌套一次循环即可。示例的代码如下:
#include <stdio.h>int main()
{int a[25], b[25], n, m, i, j, flag;scanf("%d", &n);for (i = 0; i < n; i++)scanf("%d", &a[i]);scanf("%d", &m);for (i = 0; i < m; i++)scanf("%d", &b[i]);for (i = 0; i < n; i++){flag = 1;for (j = 0; j < m; j++)if (a[i] == b[j]){flag = 0;break;}if (flag)printf("%d ", a[i]);}return 0;
}
6-20 打印杨辉三角
本题要求编写程序,按照规定格式打印前n行杨辉三角。
输入格式:
输入在一行中给出n(1≤n≤10)。
输出格式:
以正三角形的格式输出前n行杨辉三角。每个数字占固定4位。
输入样例:
6
输出样例:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
我们是不是写过这道题……?好像是写过的,不过不太想找了。我们现在用二维数组来写。代码如下:
#include <stdio.h>int main()
{int n, a[10][10];scanf("%d", &n);a[0][0] = 1;for (int i = 1; i < n; i++){a[i][0] = 1;for (int j = 1; j < i; j++){a[i][j] = a[i - 1][j] + a[i - 1][j - 1];}a[i][i] = 1;}for (int i = 0; i < n; i++){for (int k = 0; k < n - i - 1; k++){printf(" ");}for (int j = 0; j <= i; j++){printf("%4d", a[i][j]);}printf("\n");}return 0;
}
结语
不知道你有没有发现,这次的代码风格和以往的有很大不同。这是为什么呢?
因为基本全部代码均由ChatGPT生成,我只做了一点点修改,欸嘿。
不知道你怎么看待这种情况,那么,下周见
(不知道这种算不算原创,如有侵权请联系删除