
C语言第八章作业
也可以参考 博客园 的解答
1. 输入3个整数,要求按由小到大的顺序输出。
解题思路: 先获取到三个变量的地址,然后获取三个数据,通过指针进行比较转换即可
#include <stdio.h>
#include<stdlib.h>
void swap(int *p_a, int *p_b){
int temp = *p_a;
*p_a = *p_b;
*p_b = temp;
}
int main(){
int a, b, c, *p_a = &a, *p_b = &b, *p_c = &c; // 获取每个变量空间的地址
printf("Please enter three numbers:");
scanf_s("%d%d%d", p_a, p_b, p_c);
if (*p_a > *p_b) {
swap(p_a, p_b); //通过指针进行指向空间内的数据交换
}
if (*p_a > *p_c) {
swap(p_a, p_c);
}
if (*p_b > *p_c) {
swap(p_b, p_c);
}
printf("%d %d %d\n", *p_a, *p_b, *p_c);
system("pause");
return 0;
}
2. 输入3个字符串,要求按由小到大的顺序输出。
解题思路: 字符串的比较可以使用strcmp函数,返回值>0表示大于,返回值小于0表示小于,返回追等于0表示相同。其他的比较排序思路与数字的排序交换没有区别,逐个进行比较先找出最大的,然后找出第二大的。
#include <stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){
char str[3][32];
char *p[3];
printf("Please enter three strings:");
for (int i = 0; i < 3; i++) {
p[i] = str[i];
scanf_s("%s", p[i], 32); //后边的数字限制缓冲区边界,防止缓冲区溢出访问越界
}
//让p[0]和p[1]/p[2]分别进行比较,找出最大的字符串,i+1之后,则让p[1]和p[2]进行比较,找出第二大
//i循环总个数-1次,最后一个是不需要比较的
for (int i = 0; i < 2; i++) {
for (int j = i + 1; j < 3; j++) {
if (strcmp(p[i], p[j]) > 0) {
char *tmp = p[i]; p[i] = p[j]; p[j] = tmp;
}
}
}
printf("%s %s %s\n", p[0], p[1], p[2]);
system("pause");
return 0;
}
3. 输入10个整数,将其中最小的数与第一个数对换, 把最大的数与最后一个数对换。
解题思路: 在进行数值逐个比较的同时找到最小值的空间地址以及最大值的空间地址,使用这两个空间中的数据最终与第一和最后数据进行对换即可。
#include <stdio.h>
#include <stdlib.h>
void input(int *arry, int len){
for (int i = 0; i < len; i++) {
scanf_s("%d", &arry[i]);
}
}
void print(int *arry, int len){
for (int i = 0; i < len; i++) {
printf("%d ", arry[i]);
}
printf("\n");
}
void handle(int *arry, int len){
int max_num = arry[0], min_num = arry[0];
int *p_max = NULL, *p_min = NULL;
for (int i = 1; i < len; i++) {
if (min_num > arry[i]) { //逐个比对后找出最小值
min_num = arry[i];
p_min = &arry[i]; //逐个比对后找到最小值的空间地址
}
if (max_num < arry[i]) { //逐个比对后找出最大值
max_num = arry[i];
p_max = &arry[i]; //逐个比对后找到最大值的空间地址
}
}
int tmp;
tmp = *p_min; *p_min = arry[0]; arry[0] = tmp; //最小值与第一个数据交换
tmp = *p_max; *p_max = arry[len - 1]; arry[len - 1] = tmp; //最大值与最后一个数据交换
}
int main(){
int arry[10];
printf("Please enter ten nums:");
input(arry, 10);
handle(arry, 10);
print(arry, 10);
system("pause");
return 0;
}
4. 有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数。
写一函数实现以上功能,在主函数中输人n个整数和输出调整后的n个数。
解题思路:找出倒数第m个数据,从这里开始保存倒数第m位置的数据,因为倒数第m位置的数据要放到数组最前方,将m之前的数据向后偏移一位,然后将数组第一个位置的数据替换为保存的m位的数据,逐个往后递增即可。
#include <stdio.h>
#include<stdlib.h>
// [1, 2, 3, 4, 5] 移2 --> [4, 5, 1, 2, 3]
void move(int *arry, int n, int m){
int end_idx = n - m; //找到倒数第m个数据的位置,也就是要移动到数组首部的数据的起始位置
for (int i = 0; i < m; i++) {
int *p = arry + end_idx + i; //从倒数第m个数据的位置开始逐渐向后偏移直到数组尾部
int tmp = *p; //获取到这个位置的值,用于数组前边数据向后偏移1位之后,向数组第i位赋值
for (int j = end_idx + i; j > i; j--) { //从第i位开始逐个向后偏移一位
*p = *(p - 1);
p--;
}
*(arry + i) = tmp; //数组的前第i个数字逐个替换为后边被覆盖的值
}
}
int main(){
int number[32], n, m, i;
printf("Please enter the number of numbers: ");
scanf_s("%d", &n); //先确定要输入多少个数字
printf("Please enter %d numbers: ", n);
for (i = 0; i < n; i++) {
scanf_s("%d", &number[i]); //输入指定个数的数字
}
printf("Number of positions to move: ");
scanf_s("%d", &m); //确定要向后移动多少个位置
move(number, n, m);
for (i = 0; i < n; i++) {
printf("%d ", number[i]);
}
printf("\n");
system("pause");
return 0;
}
5. 有n个人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位
解题思路: 从第一个人开始,逐个报数,谁报3就退出,并且重置报数,直到最后一个人后,又重新从第一个人继续报数,直到最终只剩一个人的时候退出即可。
#include <stdio.h>
#include<stdlib.h>
int main(){
int people[128], n;
printf("Please input how many people: ");
scanf_s("%d", &n);
for (int i = 0; i < n; i++) {
people[i] = i + 1; //对每个人顺序排号
}
int remain = n;
int num_off = 0;
int *p = NULL;
while (remain > 1) {
p = people;
while (p != people + n) { // 每次从第一个位置开始,直到最后一个位置,报数是一直递增的
if ((*p) != 0) { //若这个位置人还在
num_off++; //则报数
if (num_off == 3) { //否则当前的人即将要报的数字是3
*p = 0; //则剔除这个人
num_off = 0; //并且重新开始计数,下边会++,所以是从1开始报数
remain--; //剩余人数-1
}
}
p++;
}
}
for (int i = 0; i < n; i++) {
if (people[i] != 0) {
printf("Serial number of the remaining person:%d\n", people[i]);
}
}
printf("\n");
system("pause");
return 0;
}
6. 写一函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度
解题思路: 字符串以\0作为结尾,则从第一个字符开始向后移动遇到\0认为字符串结束。
#include <stdio.h>
#include<stdlib.h>
int mystrlen(char *str){
int len = 0;
char *ptr = str;
while (*ptr != '\0') {
ptr++;
len++;
}
return len;
}
int main(){
char buf[1024];
printf("Please enter a string: ");
scanf_s("%s", buf, 1024);
printf("string len:%d\n", mystrlen(buf));
system("pause");
return 0;
}
7. 有一字符串,包含n个字符。写一函数,将此字符串中从第m个字符开始的全部字符复制成为另一个字符串
解题思路: 当字符串指针移动到源字符串的第m位时,则开始向另一个缓冲区中写入剩下的数据
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
int main(){
char buf1[1024], buf2[1024];
printf("Please enter a string: ");
scanf_s("%s", buf1, 1024);
int m;
printf("Please enter a location to start copying: ");
scanf_s("%d", &m);
if (m < 0 || m > strlen(buf1)) { //检测输入的位置是否合法
printf("Illegal location entered\n");
return -1;
}
char *ptr1 = buf1 + m; // 从第m个位置开始复制新数据
char *ptr2 = buf2;
while (*ptr1 != '\0') {
*ptr2++ = *ptr1++;
}
*ptr2 = '\0'; //不要忘了字符串结尾标志
printf("%s\n", buf2);
system("pause");
return 0;
}
8. 输入一行文字,找出其中大写字母、小写字母、空格、数字以及其他字符各有多少。
解题思路: 字符可以直接进行比较,但是要注意字符串中的数字是字符数字,必须以字符的形式比较,也就是加上单引号
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
int main()
{
char buf[1024];
printf("Please enter a string: ");
gets_s(buf, 1024);
int upper_count = 0, lower_count = 0, digit_count = 0, space_count = 0, other_count = 0;
char *ptr = buf;
while (*ptr != '\0') {
if (*ptr >= 'A' && *ptr <= 'Z') { //大写字母
upper_count++;
}else if (*ptr >= 'a' && *ptr <= 'z'){//小写字母
lower_count++;
}else if (*ptr >= '0' && *ptr <= '9') {//数字字符
digit_count++;
}else if (*ptr== ' ') {//空格字符
space_count++;
}else { //其他字符
other_count++;
}
ptr++;
}
printf("upper:%d; lower:%d; digit:%d; space:%d; other:%d\n", \
upper_count, lower_count, digit_count, space_count, other_count);
system("pause");
return 0;
}
9. 写一函数,将一个3x3的整型矩阵转置。
解题思路: 矩阵转置就是行变列,列变行,说白了就是 arry[i][j] 转换为 arry[j][i] ; 但是需要注意的是,
一. 因为行列个数可能并非相同,转换后行数或者列数变多了或者变少,因此不能直接转换。需要重新申请空间存储转换后的数据。
二. 二维数组是线性扁平化存储的,无法确定列数的情况下传参后,在函数中使用时需要头指针向后偏移 列数*第n行 才能访问到第n行的数据。例如在函数中访问 arry[i][j] ,需要通过arry + col_num*i + j 方式进行访问。
#include <stdio.h>
#include <stdlib.h>
int **transform(int (*arry)[4], int row_count, int col_count) {
// 列变行,行变列,则行的个数是以前列的个数,列的个数是以前行的个数
int **p = NULL;
// 矩阵中有多少行,取决于以前有多少列,然后申请地址空间
p = (int **)malloc(sizeof(int *) * col_count);
for (int i = 0; i < col_count; i++) {
// 一行中有多少列,取决于以前有多少行,然后申请空间
p[i] = (int *)malloc(sizeof(int) * row_count);
}
for (int i = 0; i < col_count; i++) {
for (int j = 0; j < row_count; j++) {
// 二维数组的存储是扁平化的,访问第j行第i列的数据,应该是 arry + j*列数 + i
// j是新数组的列,但是是源数组的行
p[i][j] = arry[j][i];
}
}
return p;
}
int main() {
int arry[3][4];
printf("Please enter a 3 x 4 matrix: \n");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
scanf("%d", &arry[i][j]);
}
}
int **p = transform(arry, 3, 4);
printf("\n");
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", p[i][j]);
}
free(p[i]); // 释放二级指针中每个一级指针申请的空间
printf("\n");
}
free(p); // 释放总体二级指针的空间
system("pause");
return 0;
}
/* test
11 12 13 14
15 16 17 18
19 20 21 22
*/
10. 将一个5x5的矩阵中最大的元素放在中心,4个角分别放4个最小的元素
(顺序为从左到右,从上到下依次从小到大存放),写一函数实现之。用main函数调用。
解题思路: 将二维数组当做一维数组进行处理比较方便,而二维数组本身就是扁平化存储,所以直接使用首地址即可。
先遍历找到最大值,将其与中间数字交换,而中间数字的下标就是数字总数除以2;
其次寻找四次最小值,每次寻找的时候将最小值的下标记录起来,前提是这个数字如果已经是选中的最小数字之一,则需要跳过,也就是只跟剩余的数字作比较。(第二次开始遍历找最小数字的时候,千万不能与第一个最小数进行比较,否则永远都只有一个最小数)。
#include <stdio.h>
#include <stdlib.h>
void mymin(int(*p)[5],int *min){
int a[25];
int temp = 0;
for (int i = 0; i < 5; i++){
for (int j = 0; j < 5; j++){
a[temp] = p[i][j];
temp++;
}
}
for (int i = 0; i < 25; i++){
for (int j = 0; j < 25 - i - 1; j++){
if (a[j] > a[j + 1]){
int tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}
for (int i = 0; i < 4; i++){
min[i] = a[i];
}
}
void cal(int (*p)[5]){
int min[4] = {0};
int max = p[0][0];
mymin(p, min);
for (int i = 0; i < 5; i++){
for (int j = 0; j < 5; j++){
if(max < p[i][j]){
max = p[i][j];
}
}
}
p[2][2]=max;
p[0][0]=min[0];
p[0][4]=min[1];
p[4][0]=min[2];
p[4][4]=min[3];
}
int main(){
int a[5][5];
printf("please input 5 x 5: \n");
for (int i = 0; i < 5; i++){
for (int j = 0; j < 5; j++){
scanf("%d", &a[i][j]);
}
}
cal(a);
printf("result: \n");
for (int i = 0; i < 5; i++){
for (int j = 0; j < 5; j++){
printf("%d ", a[i][j]);
}
printf("\n");
}
system("pause");
return 0;
}
/* test
66 12 13 14 15
16 17 18 19 88
20 21 22 23 99
33 34 35 36 37
55 56 57 58 59
*/
11. 在主函数中输入10个等长的字符串。用另一函数对它们排序。然后在主函数输出这10个已排好序的字符串。
解题思路: 排序方式与数字比较没什么不同,先遍历比较找出最大的字符串,与第一个字符串进行交换,然后剩下的进行比较找出最大的字符串与第二个交换....
需要主机的就是字符串的比较采用strcmp接口,返回值大于0表示第一个字符串大于第二个字符串
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
// 类似于冒泡排序
void sort(char s[10][32]){
int i, j;
for (i = 0; i < 10; i++){
for (j = i; j < 10; j++){
if (strcmp(s[i], s[j])> 0){
char tmp[32];
strcpy(tmp, s[i]);
strcpy(s[i], s[j]);
strcpy(s[j], tmp);
}
}
}
}
int main(){
char str[10][32];
printf("Please enter ten strings:\n");
for (int i = 0; i < 10; i++){
scanf("%s", str[i]);
}
sort(str);
printf("\nresult: \n\n");
for (int i = 0; i < 10; i++){
printf("%s\n", str[i]);
}
system("pause");
return 0;
}
/*test
abcdefghijk
lmnopqrstuv
wxyzabcd
efghijklmnop
qrstuvwxyz
abcdefghi
jklmnopqr
stuvwxyz
abcdefghijkl
mnopqrstuvw
*/
12. 用指针数组处理上一题目,字符串不等长
解题思路: 与数字的比较没什么区别,只不过需要采用strcmp进行字符串的大小比较,使用指针实现需要在最早接收数据的时候就采用字符串指针数组,这样的好处在于指针的指向可以直接通过赋值进行改变,而指针数组中的字符串的顺序只需要交换不同字符串的地址就可以实现
#include<stdio.h>
#include<string.h>
void sort(char *s[10]){
int i, j;
for (i = 0; i < 10; i++){
for (j = i; j < 10; j++){
if (strcmp(s[i], s[j])> 0){
char *tmp = s[i]; //指针的好处在于直接通过赋值可以改变指向
s[i] = s[j]; //只要交换了字符串的地址就实现了字符串的交换
s[j] = tmp;//因此通过指针指向的交换就能够实现数组中字符串的排序
}
}
}
}
int main(){
char *str[10];
printf("Please enter ten strings:\n");
for (int i = 0; i < 10; i++) {
str[i] = malloc(32); //为每一个指针分配空间
scanf("%s", str[i]);
}
sort(str);
printf("\nretult: \n\n");
for (int i = 0; i < 10; i++){
printf("%s\n", str[i]);
free(str[i]);
}
system("pause");
return 0;
}
/*test
abcdefghijk
lmnopqrstuv
wxyzabcd
efghijklmnop
qrstuvwxyz
abcdefghi
jklmnopqr
stuvwxyz
abcdefghijkl
mnopqrstuvw
*/
15. 有一个班4个学生,5门课程
①求第1门课程的平均分;
②找出有两门以上课程不及格的学生,输出他们的学号和全部课程成绩及平均成绩;
③找出平均成绩在90分以上或全部课程成绩在85分以上的学生。
分别编3个函数实现以上3个要求。
解题思路: 4个学生,5门课程就是一个4x5的二维数组,
求第一门课的平均分,就是将第0列数据相加除以学生人数
遍历每个学生的成绩,判断不及格次数,若大于2则输出信息即可
统计每个学生总成绩,以及对每门课程成绩进行判断即可
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
float avg(int arry[4][5], int n)
{
float sum = 0;
for (int i = 0; i < n; i++) {
sum += arry[i][0];
}
printf("Average of course 1: %f\n", (sum / n));
return (sum / n);
}
float avg2(int (*poiner)[5], int n){ // pointer
float sum = 0;
for(int i = 0; i < 4; i++){
sum += *(*(poiner + i));
}
printf("Average of course 1: %f\n", (sum / n));
return (sum / n);
}
void fail(int arry[4][5], int n)
{
printf("Information on students who fail in more than two courses: \n");
for (int i = 0; i < n; i++) {
float sum = 0, fail_count = 0;
for (int j = 0; j < 5; j++) {
if (arry[i][j] < 60) {
fail_count++;
}
}
if (fail_count <= 2) {
continue;
}
printf("stuId: %d ", i + 1);
printf("score: ");
for (int j = 0; j < 5; j++) {
sum += arry[i][j];
printf("%d ", arry[i][j]);
}
printf("avg: %f ", sum / 5);
printf("\n");
}
}
void fali2(int (*pointer)[5], int n){
for(int i = 0; i < 4; i++){
int fali_cout = 0; float sum;
for(int j = 0; i < 5; j++){
if(*(*(pointer + i)+j) < 60){
fali_cout++;
}
}
if(fali_cout <= 2){
continue;
}else{
printf("stuId: %d", i + 1);
printf("score: ");
for(int j = 0; j < 5; j++){
printf("%d ", *(*(pointer + i)+j));
}
}
printf("avg: %f", sum / 5);
printf("\n");
}
}
void excellent(int arry[4][5], int n)
{
int i, j;
for (i = 0; i < n; i++) {
int sum = 0, count = 0;
for (j = 0; j < 5; j++) {
sum += arry[i][j];
if (arry[i][j] > 85) {
count++;
}
}
if ((sum / 5) > 90 || count == j) {
printf("Excellent students: %d\n", i + 1);
}
}
}
int main()
{
int arry[4][5] = {
99,99,99,99,99,
99,99,50,33,44,
99,99,99,99,99,
99,99,99,99,99,
};
// avg(arry, 4); //1
avg2(arry, 4); // 1-2
// fail(arry, 4); //2
fail(arry, 4); //2-2
excellent(arry, 4); //3
printf("\n");
system("pause");
return 0;
}
16. 输入一个字符串,内有数字和非数字字符, 统计共有多少个整数,并输出这些数。
例如:A123x456 17960? ,302tab5876,将其中连续的数字作为一个整数,依次存放到一数组a中。例如,123放在a[0],456放在a1[1].....
解题思路: 遇到数字字符,则开始统计连续数字字符的个数,统计完毕后,则从右往左每次乘以10(除了个位数)作为数字的单位,最终相加得到数字;然后越过这个数字,从后边继续查找。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void count_digit(char *str){
int digit[32], count = 0;
char *ptr = str;
int i = 0, str_len = strlen(str);
while (i < str_len) {
if (*(ptr+i) >= '0' && *(ptr+i) <= '9') {
int len = 1;//用于统计连续数字的个数
while (*(ptr + i + len) >= '0' && *(ptr + i+ len) <= '9' && (i+len) < str_len) {//找出从当前位置连续数字的个数
len++;
}
int sum = *(ptr + i + len - 1) - '0';//先获取个位数的数据
int unit = 1;//每一位的单位,从十位开始每次乘以10作为单位
for (int j = len - 2; j >= 0; j--) {//从右往左逐个处理
unit *= 10;
sum += (*(ptr + i + j) - '0') * unit;
}
digit[count++] = sum;
i += len; // i需要加上len的长度,越过这个数字,防止一个连续数字中的字符重复处理
continue;
}
i++;
}
for (int i = 0; i < count; i++) {
printf("%d ", digit[i]);
}
}
int main(){
char buf[1024] = { 0 };
printf("Please enter a string with numbers:\n");
gets(buf);
printf("\nretult: \n");
count_digit(buf);
printf("\n");
system("pause");
return 0;
}
/*test
A123x456 17960? ,302tab5876
*/
- 感谢你赐予我前进的力量