苏州大学c语言作业


知识点

  1. 实参和其对应的形参各占用独立的存储单元
  2. c语言允许函数值类型缺省定义,此时函数值隐含的类型是int
  3. C语言文件存取方式:顺序存取,随机存取均可
  4. C语言能识别处理的文件为文本文件和二进制文件
  5. 系统的标准输入文件为键盘
  6. typedef不能增加新类型。其用于为已存在的数据类型创建一个新的名称(别名)。它本身并不创建新的数据类型,而是为现有的类型提供一个更容易理解或更简洁的名称。
  7. 单引号只能引用一个字符常量,双引号可以引用多个,算字符串。整数可以被类型转化为字符型。
  8. 宏定义的时候要考虑后面有没有分号,带入的时候是整体带入。
  9. 在C/C++语言中,变量做实参时,它和对应形参之间的数据传递方式是单向值传送

一、选择填空

1.结构体引用

在这里插入图片描述
引用有两种方式,要么用点,要么用箭头。
D

2.函数返回值

在这里插入图片描述
没有return语句,它的返回值是未定义的。这意味着函数可能会返回任意的值,包括垃圾值。
B

3.函数调用

在这里插入图片描述
整型数据和字符型数据可以通用,整型变量和浮点型变量的赋值相互兼容。
D

4.逗号操作符

在这里插入图片描述
返回值是逗号表达式,虽然这里写的像坐标点
最终只会返回最后一个表达式的值
B

5.函数体内外的参数

在这里插入图片描述
输出结果为21
在函数体内部操作a不影响外面的a

6.函数调用(传入参数)

在这里插入图片描述

7.引用

以下代码输出结果:

#include<iostream>
using namespace std;
int main(){
	int x=50,&y=x;
	x=100;
	cout<<y<<endl;
}

在这段代码中,y 是一个指向 x 的引用。因此,无论你改变 x 的值,y 的值都会随之改变,因为它们指向同一个内存位置。所以,当你将 x 的值改变为 100 后,y 的值也会变为 100。
故输出结果为100.

8.

二、编程

1.进制转化

编写程序,输入整数m,n,将m转成n(2<=n<16)进制整数并输出。若有英文字母,则一律输出大写字母形式。
【注意】输入和输出各占一行;运行效果应如下所示(第1行为输入,数据间用半角空格分隔,第2行为输出),格式错误算结果错误。
30 16
1E

#include"stdio.h"
int main(){
	int i,m,n,t=1,res,flag=0;
	int  a[10];
	scanf("%d%d",&m,&n);   
	
	while(t>0){
		res=m%n;
		t=m/n;
		m=t;
		a[flag]=res;
		flag++;		
		
	}
	for(i=flag-1;i>=0;i--){                      //用字母表示时用字符型输出,可以通过ASCIL码值来输出
		if(a[i]>=10){
			printf("%c",'A'+a[i]-10);
		}else{
				printf("%d",a[i]);
		}
	
	}
}

2.去除重复数据

编写一个程序,输入10个含重复数据整数,去掉重复的数据并按原顺序输出。
【注意】输入和输出各占一行;运行效果应如下所示(第1行为输入,数据间用半角空格分隔,第2行为输出),格式错误算结果错误。
1 6 5 6 7 6 7 7 4 3
1 6 5 7 4 3

my code:

#include"stdio.h" 
int main(){
	int n=10,flag=0;
	int size=10;
	int a[size];
	int i,j,t;
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	for(i=0;i<n-1;i++){
		//flag=0;
		j=i+1;
		while(j<n){              //在这里出了问题,因为在进行操作时,不是每一次j都要递增。如果对数组长度进行缩小处理,就没有必要递增,因为n减小了。
			if(a[i]==a[j]){
				for(t=j;t<n-1;t++){
						a[t]=a[t+1];						
				}
				n--;
				j=j;
			}else{
				j++;
			}
		}
	
	}
	//数组元素的删除逻辑:把其中要删除的元素之后的部分全部向前移动,然后缩短数组长度。
	
	for(i=0;i<n;i++){
		printf("%d ",a[i]);
	}
}
#include <stdio.h>

int main() {
    int input[10];
    int unique[10];
    int size = 0;

    // 输入10个整数
    printf("请输入10个整数(可能包含重复数据):\n");
    for (int i = 0; i < 10; i++) {
        scanf("%d", &input[i]);

        // 检查是否为重复数据
        int isDuplicate = 0;
        for (int j = 0; j < size; j++) {                   //此处是与unique数组里面的数字逐一进行比较,如果是一样的,结束比较,该数字不能被放入unique数组里,不一样就放进去
            if (input[i] == unique[j]) {
                isDuplicate = 1;
                break;
            }
        }

        // 如果不是重复数据,添加到unique数组中
        if (!isDuplicate) {                       //注意这里是非isDuplicate不等于0,即isDuplicate==0
            unique[size] = input[i];             //开始的时候unique里面没有给值,所以第一个输入的数一定会放入unique里面
            size++;
        }
    }

    // 输出去重后的结果
    printf("去重后的结果为:\n");
    for (int i = 0; i < size; i++) {
        printf("%d ", unique[i]);
    }
    printf("\n");

    return 0;
}

3. 字符串转化

编写程序,输入一个长度小于1000的字符串s1,再输入一个待查找的字符串s2和一个替换的字符串s3,将原始字符串中所有出现的待查找字符串s2替换成s3,输出查找到的次数及替换后的字符串s1。要求必须要用字符数组处理字符串。
运行效果应如下所示,格式错误算结果错误。
测试1:(第1、2、3行为输入,第4、5行为输出)
hello,Jack!. hello Mary!
hello

#include <stdio.h>
#include <string.h>

// 函数:replaceString
// 功能:在字符串str中查找并替换所有的find字符串为replace字符串,同时统计替换次数
void replaceString(char *str, const char *find, const char *replace, int *count) {
    int findLen = strlen(find); // 获取待查找字符串的长度
    int replaceLen = strlen(replace); // 获取替换字符串的长度
    int strLen = strlen(str); // 获取原始字符串的长度
    
    char result[1000] = ""; // 存储替换后的结果字符串
    int index = 0; // 结果字符串的索引
    *count = 0; // 初始化替换次数为0

    for (int i = 0; i < strLen; i++) {
        if (strncmp(&str[i], find, findLen) == 0) { // 检测是否匹配待查找字符串,&str[i]表示从i开始返回的子字符串
            strcat(result, replace); // 执行替换操作
            index += replaceLen;
            i += findLen - 1; // 更新索引位置
            (*count)++; // 替换次数加一
        } else {
            result[index] = str[i]; // 将当前字符复制到结果字符串中
            index++;
        }
    }

    strcpy(str, result); // 将替换后的结果复制回原始字符串
}

int main() {
    char s1[1000];
    char s2[100];
    char s3[100];
    int count = 0;

    printf("请输入一个长度小于1000的字符串s1:");
    scanf("%s", s1);

    printf("请输入待查找的字符串s2:");
    scanf("%s", s2);

    printf("请输入替换的字符串s3:");
    scanf("%s", s3);

    replaceString(s1, s2, s3, &count); // 调用替换函数

    printf("查找到的次数:%d\n", count);
    printf("替换后的字符串s1:%s\n", s1);

    return 0;
}

另:全部在主函数里完成

#include"stdio.h"
#include"string.h"
int main(){
	char str[1000];
	char find[1000];//wait to searc
	char replace[1000];//replace
	char result[1000]="";
	
	gets(str);
	gets(find);
	gets(replace);
	int findLen = strlen(find); 
    int replaceLen = strlen(replace); 
    int strLen = strlen(str); 
    int i,index=0,count=0;
    for(i=0;i<strLen;i++){
    	if(strncmp(&str[i],find,findLen)==0){
    		strcat(result,replace);
    		index=index+replaceLen;      
    		i=i+findLen-1;
    		count++;
		}else{
			result[index]=str[i];
			index++;
		}  	
	}
	strcpy(str, result); 
	printf("%d\n",count);
	printf("%s",result);
	

} 

4.数据排列

有一个非负整数数组。现要把数组中的元素重新排列组合成一个最大的数。每个数不可拆分。
例如, 数组元素有3,30,34,5,9, 重新组合后的最大值为9534330。
编写程序,输入一个正整数n(2<=n<=10),再输入n个非负整数,计算并输出拼接后的最大数。
运行效果应如下所示,格式错误算结果错误。
测试1:(第1、2行为输入,第3行为输出)
5
3 30 34 5 9
9534330

错误代码:
以下只完成了每输入一个数就和前面一个链接,然后比较最大值,但实际上把数据变成字符串,顺序不一定是输入的顺序。

#include"stdio.h"
#include"string.h"
#include <stdlib.h>
int main(){
	int x,n;
	scanf("%d",&n);
	int i,cnt=0;
	int x0,num1,num2;
	char str1[100];
	char str2[100];
	scanf("%d",&x0);
	for(i=0;i<n-1;i++){
		scanf("%d",&x);
		sprintf(str1,"%d%d",x0,x);
		sprintf(str2,"%d%d",x,x0);
	    num1 = atoi(str1);                  
	    num2 = atoi(str2); 
		if(num1>=num2){
			x0=num1;
		}else{
			x0=num2;
		}
	}
	if(num1>=num2){
			printf("%d",num1);
		}else{
			printf("%d",num2);
		}

}

5. 回文字符串(中文输出)

输入一个长度小于100的全中文字符串,判断它是否是回文,若是则输出“Yes”,否则输出“No”。
所谓回文即正序和逆序内容相同的字符串。
运行效果应如下所示,格式错误算结果错误。
测试1:(第一行为输入,第2行为输出)
上海自来水来自海上
Yes
测试2:(第一行为输入,第2行为输出)
上海自来水
No

//不知道为什么过不了测试
#include"stdio.h"
#include"string.h"
#include <wchar.h>
#include <locale.h>
int main(){
	//setlocale(LC_ALL, "zh_CN.UTF-8");
	setlocale(LC_ALL, ""); // 设置本地化环境为用户的默认环境 
	wchar_t str[100];
	wchar_t opp[100] = L"";
	
	fgetws(str,100,stdin);
	str[wcslen(str) - 1] = L'\0';
	int i,j=0,flag=1;
	i=wcslen(str)-1;
	while(i>=0){
		opp[j]=str[i];
		i--;
		j++;
	}
	opp[j] = L'\0';
	int k=0;
	while(k<wcslen(str)){
		if(opp[k]!=str[k]){
			flag=0;
			break;
		}
		k++;		
	}
	if(flag==1){
		printf("Yes");
	}else{
		printf("No");
	}	
}

6.矩阵按行和排序

输入一个矩阵,以它每一行的和的大小升序排列

#include <stdio.h>
int main(){
   int row,col,sum;
   scanf("%d%d",&row,&col);
   int i,j,k,temp;
   int a[row][col];
   int S[row];
    for (int i = 0; i < row; i++) {
       for (int j = 0; j < col; j++) {
           scanf("%d", &a[i][j]);
       }
   }
   //计算每一行的和 
   for(i=0;i<row;i++){
   	sum=0;
   	for(j=0;j<col;j++){
   		sum=sum+a[i][j];
   	}
   	S[i]=sum;
   }
   //冒泡排序,并交换行数
   for(i=0;i<row;i++){
   	for(j=i+1;j<row;j++){
   		if(S[i]>S[j]){
   			temp=S[i];
   			S[i]=S[j];
   			S[j]=temp;
   			for(k=0;k<col;k++){         //在行一定的情况下,依次遍历列,然后交换
   				temp=a[i][k];
   				a[i][k]=a[j][k];
   				a[j][k]=temp;				
   			}				
   		}
   	}
   } 	
    for (int i = 0; i < row; i++) {
       for (int j = 0; j < col; j++) {
           printf("%d ", a[i][j]);
       }
       printf("\n");
   }
}

7.数据拼接

有一个非负整数数组。现要把数组中的元素重新排列组合成一个最大的数。每个数不可拆分。
例如, 数组元素有3,30,34,5,9, 重新组合后的最大值为9534330。
编写程序,输入一个正整数n(2<=n<=10),再输入n个非负整数,计算并输出拼接后的最大数。

【注意】运行效果应如下所示,格式错误算结果错误。
测试1:(第1、2行为输入,第3行为输出)
5
3 30 34 5 9
9534330
测试2:(第1、2行为输入,第3行为输出)
6
210 38 308 98 22 70
98703830822210

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
  
// 自定义比较函数,用于比较两个数字的拼接结果  
int compare(const void *a, const void *b) {  
    char num1[20], num2[20]; // 假设数组中的数字不会超过19位  
    sprintf(num1, "%d%d", *(int*)b, *(int*)a); // 先拼接b再拼接a  
    sprintf(num2, "%d%d", *(int*)a, *(int*)b); // 先拼接a再拼接b  
    return strcmp(num2, num1); // 返回降序排列的结果  
}  
  
int main() {  
    int n,i;  
    scanf("%d", &n);  
      
    if (n < 2 || n > 10) {  
        printf("n must be between 2 and 10.\n");  
        return 1;  
    }  
      
    int *nums = (int*)malloc(n * sizeof(int));  
    if (!nums) {  
        perror("Failed to allocate memory");  
        return 1;  
    }  
      
    for ( i = 0; i < n; i++) {  
        scanf("%d", &nums[i]);  
    }  
      
    // 使用自定义比较函数对数组进行排序  
    qsort(nums, n, sizeof(int), compare);  
      
    // 输出拼接后的最大数  
    for ( i = n-1; i >=0; i--) {  
        printf("%d", nums[i]);  
    }  
    printf("\n");  
      
    free(nums);  
    return 0;  
}

8.字符串的查找与替换

.编写程序,输入一个长度小于1000的字符串s1,再输入一个待查找的字符串s2和一个替换的字符串s3,将原始字符串中所有出现的待查找字符串s2替换成s3,输出查找到的次数及替换后的字符串s1。要求必须要用字符数组处理字符串。
运行效果应如下所示,格式错误算结果错误。
测试1:(第1、2、3行为输入,第4、5行为输出)
hello,Jack!. hello Mary!
hello
Hi
2
Hi,Jack!. Hi Mary!

#include"stdio.h"
#include"string.h"
int main(){
	char str[1000];
	char find[1000];//wait to searc
	char replace[1000];//replace
	char result[1000]="";
	
	gets(str);
	gets(find);
	gets(replace);
	int findLen = strlen(find); 
    int replaceLen = strlen(replace); 
    int strLen = strlen(str); 
    int i,index=0,count=0;
    for(i=0;i<strLen;i++){
    	if(strncmp(&str[i],find,findLen)==0){
    		strcat(result,replace);
    		index=index+replaceLen;      
    		i=i+findLen-1;
    		count++;
		}else{
			result[index]=str[i];
			index++;
		}  	
	}
	strcpy(str, result); 
	printf("%d\n",count);
	printf("%s",result);
} 

9.函数(最大公约数,最小公倍数)

编写一个自定义函数,函数原型如下所示。
void divmod(int m,int n,int *pmax,int *pmin);
参数为两个正整数m和n及两个整型的指针pmax和pmin,通过两个指针带回两个返回值,其中第一个为m和n的最大公约数,第二个为m和n的最小公倍数。
编写程序,输入两个正整数,调用自定义函数,输出最大公约数和最小公倍数的元组。
【注意】运行效果应如下所示,格式错误算结果错误。
测试1:(第1行为输入,第2行为输出)
12,30
6 60

#include <stdio.h>
int gcd(int a, int b) {
    int temp;
    while (b != 0) {
        temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}
int f(int a,int b){
	int i;
	for(i=a;i<a*b;i++){
		if(i%a==0&&i%b==0){
			return i;
			break;
		}
	}
}
void divmod(int m,int n,int *pmax,int *pmin){
	*pmax=gcd(m,n);
	*pmin=f(m,n);
}
int main(){
	int num1,num2;
	int max,min;
	scanf("%d%d",&num1,&num2);
	divmod(num1,num2,&max,&min);
	printf("%d %d",max,min);
	}

10.黑洞数

黑洞数,是一类具有奇特转换特性的数。任何一个各位数字不全相同的三位数,经有限次“重排求差”操作,总会得到495。最后所得的495即为三位黑洞数。所谓“重排求差”操作即组成该数的数字重排后的最大数减去重排后的最小数。
例如,对三位数207:
第1次重排求差得:720-27=693;
第2次重排求差得:963-369=594;
第3次重排求差得:954-459=495;
以后会停留在495这一黑洞数。如果三位数的3个数字全相同,一次转换后即为0。
编写程序,任意输入一个整数n(1<=n<=999),编程给出三位黑洞数重排求差的过程。
(1)若数字不满三位数,例如1,可将其看做001,则重排后最大数为100,最小数为1。
(2)该题目要求使用自定义函数完成,程序中至少要定义两个函数如下:
int chongzu_max(int n);//求解n重排后的最大值
int chongzu_min(int n);//求解n重排后的最小值
【注意】运行效果应如下所示,格式错误算结果错误。
测试1:(第1行为输入,其余行为输出)
123
321-123=198
981-189=792
972-279=693
963-369=594
954-459=495
测试2:(第1行为输入,其余行为输出)
111
111-111=0
测试3:(第1行为输入,其余行为输出)
1
100-1=99
990-99=891
981-189=792
972-279=693
963-369=594
954-459=495

以下代码没有考虑99这样的数字的情况,关键在于如何找中间的数,不能只是单单排除法去掉最大和最小

#include"stdio.h"
int chongzu_max(int n);
int chongzu_min(int n);
int chongzu(int n){
	int max=chongzu_max(n);
	int min=chongzu_min(n);
	printf("%d-%d=%d\n",max,min,max-min);
	if(max-min!=495){
			return chongzu(max-min);
	}

}
//求解n重排后的最大值
int chongzu_max(int n){
	int max,min,mid;
	if(n>100){
		min=n%10;
	}else if(n<10){
		min=0;
		mid=0;
	}else{
		min=0;
	}
	 max=n%10;
	int x=n;
	while(n){
		if(n%10>max){
			max=n%10;
		}
		if(n%10<min){
			min=n%10;
		}
		n/=10;
	}
	while(x){
		if(x%10!=max&&x%10!=min){
			mid=x%10;
		}
		x/=10;
	}
	return max*100+mid*10+min;
}
//求解n重排后的最小值
int chongzu_min(int n){
	int max,min,mid;
	if(n>100){
		min=n%10;
	}else if(n<10){
		min=0;
		mid=0;
	}else{
		min=0;
	}
	 max=n%10;
	
	int x=n;
	while(n){
		if(n%10>max){
			max=n%10;
		}
		if(n%10<min){
			min=n%10;
		}
		n/=10;
	}
	while(x){
		if(x%10!=max&&x%10!=min){         //如果最大值最小值和中间值一样,这个就没有办法判断
			mid=x%10;
		}
		x/=10;
	}
		
	return min*100+mid*10+max;
}

int main(){
	int n;
	scanf("%d",&n);
	chongzu(n);
	
}
#include"stdio.h"
int chongzu_max(int n);
int chongzu_min(int n);
int Mid(int n){
	int a=n%10;                       //专门写了一个函数来获得中间值,这里注意分类讨论的全面性
	int b=n/10%10;
	int c=n/100;
	if((a>=b&&b>=c)||(c>=b&&b>=a)){
		return b;
	}else if((a>=c&&c>=b)||(b>=c&&c>=a)){
		return c;
	}else {
		return a;
	}
}
int Max(int n){
	int x=n;
	int max=n%10;
	while(n){
		if(n%10>max){
			max=n%10;
		}
		n/=10;
	}
	return max;
}
int Min(int n){
	int min=n%10;
	while(n){
		if(n%10<min){
			min=n%10;
		}
		n/=10;
	}
	return min;
}
int chongzu(int n){
	int max=chongzu_max(n);          //使用递归注意边界值,当max-min=0的情况最后没有考虑到,这个可能会死循环
	int min=chongzu_min(n);
	printf("%d-%d=%d\n",max,min,max-min);
	if(max-min!=495&&max-min!=0){
			return chongzu(max-min);
	}

}
//求解n重排后的最大值
int chongzu_max(int n){
	int max,min,mid;
	if(n<10){
		min=0;
		mid=0;
	}
	if(n>100){
	min=Min(n);
	mid=Mid(n);
	}
	if(n>9&&n<100){
		mid=Min(n);
		min=0;
	}
		max=Max(n);
	return max*100+mid*10+min;
}
//求解n重排后的最小值
int chongzu_min(int n){
	int max,min,mid;
	if(n<10){
		min=0;
		mid=0;
	}
	if(n>100){
	min=Min(n);
	mid=Mid(n);
	}
	if(n>9&&n<100){
		mid=Min(n);
		min=0;
	}
		max=Max(n);		
	return min*100+mid*10+max;
}

int main(){
	int n;
	scanf("%d",&n);
	//printf("%d  %d  %d\n",Max(n),Min(n),Mid(n));
	chongzu(n);
	
}

11. 日历

已知1800年1月1日为星期三,请编写程序,输入年(>=1800)、月,将该月的日历打印出来。要求使用自定义函数完成。
输入说明:一行,年和月之间用空格分割。
输出说明:第一行为月历的头部信息,用3个英文字母分别表示星期日~星期六,3个英文字母后加一个空格。第二行开始,显示月历主体部分,每个数字占4位宽,左对齐。
注意该月的1号的位置。例如,某月的1号是周四,在输出1之前,要输出一些空格,留好位置。空格数为4*(1号是周几),比如1号是周四,则前面需空4*4=16个空格。
【注意】运行效果应如下所示,格式错误算结果错误。
测试1:(第1行为输入,其余行为输出)
2023 5
Sun Mon Tue Wed Thr Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31

#include <stdio.h>

// 判断某年是否为闰年
int isLeapYear(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

// 获取某年某月的天数
int getDaysOfMonth(int year, int month) {
    if (month == 2) {
        return isLeapYear(year) ? 29 : 28;
    } else if (month == 4 || month == 6 || month == 9 || month == 11) {
        return 30;
    } else {
        return 31;
    }
}

// 获取某年某月1号是星期几
int getFirstDayOfWeek(int year, int month) {
    int days = 0;
    for (int i = 1800; i < year; i++) {
        days += isLeapYear(i) ? 366 : 365;
    }
    for (int i = 1; i < month; i++) {
        days += getDaysOfMonth(year, i);
    }
    return (days + 2) % 7; // 1800年1月1日是星期三,加2是为了将星期三作为0
}

// 打印月历
void printCalendar(int year, int month) {
    char *weekdays[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    int firstDayOfWeek = getFirstDayOfWeek(year, month);
    int daysOfMonth = getDaysOfMonth(year, month);

    // 打印月历头部
    printf("%s %s %s %s %s %s %s\n", weekdays[0], weekdays[1], weekdays[2], weekdays[3], weekdays[4], weekdays[5], weekdays[6]);

    // 输出月历主
    for (int i = 0; i < firstDayOfWeek; i++) {
        printf("    "); // 打印空格,留出位置
    }
    for (int day = 1; day <= daysOfMonth; day++) {
        printf("%-4d", day); // 打印日期,左对齐
        if ((firstDayOfWeek + day) % 7 == 0) {
            printf("\n"); // 每输出7个日期换行
        }
    }
}

int main() {
    int year, month;
    printf("请输入年份和月份(大于等于1800),以空格分隔:");
    scanf("%d %d", &year, &month);
    printf("%d年%d月的月历如下:\n", year, month);
    printCalendar(year, month);
    return 0;
}

12.学生成绩

1.通过完成函数完成以下程序代码,输入n(n<10),再输入n个学生的某课程的平时、期中和期末成绩,然后按平时占10%,期中占20%,期末占70%的比例计算出这些学生的学期成绩,按分数从高低排序输出学生的名次、学号、姓名、性别和期末成绩。若分数相同则名次相同,其输出顺序按学号升序输出。输入输出示意如下:
5
2107403004 张林 男 95 90 90
2107403005 郑洋 男 90 95 92
2107403003 杭丹丹 女 88 80 85
2107403002 陈可可 女 95 90 90
2107403010 赵文清 女 75 83 80
1,2107403005,郑洋,男,92.40
2,2107403002,陈可可,女,90.50
2,2107403004,张林,男,90.50
4,2107403003,杭丹丹,女,84.30
5,2107403010,赵文清,女,80.10

#include"stdio.h"
#include <string.h>
enum SEX {
    GIRL, BOY
};
struct SStudent
{
    int num;          //学号 
    char name[20];    //姓名
    enum SEX sex;          //性别
    float usual;      //平时成绩
    float mid;        //期中成绩
    float final;      //期末成绩
    float total;      //期末成绩
    int placing;      //名次
};

int Read(struct SStudent stu[]) {       //考试系统的编译器不允许直接用结构体的名字声明,前面要加struct。枚举类型同理,使用前要加eunm。
    int i, n;
    scanf("%d", &n);
    for (i = 0; i < n; i++) {
        scanf("%d %s", &stu[i].num, &stu[i].name);
        char sex_str[4];
        scanf("%s", &sex_str);
        if (strcmp(sex_str, "男") == 0) {     //read函数里关于性别的输入要参考write函数,和枚举类型,转化为BOY和GIRL
            stu[i].sex = BOY;
        }
        else {
            stu[i].sex = GIRL;
        }
        scanf("%f %f %f", &stu[i].usual, &stu[i].mid, &stu[i].final);
        stu[i].total = stu[i].usual * 0.1 + stu[i].mid * 0.2 + stu[i].final * 0.7;
    }
    return n;
}
int Write(struct SStudent stu[], int n) {
    int i;
    for (i = 0; i < n; i++)
        printf("%d,%d,%s,%s,%.2f\n", stu[i].placing, stu[i].num, stu[i].name, stu[i].sex ? "男" : "女", stu[i].total);
    return n;
}
void Sort(struct SStudent stu[], int n) {
    int i, j;
    struct SStudent temp;       //这里写冒泡排序,注意我们比较的是总成绩,但交换要交换整个结构体变量,所以声明的中间值变量也应该为结构体类型
for ( i = 0; i < n-1; i++){
    for (j = 0; j <n-1-i ; j++){
        if (stu[j].total< stu[j+1].total||((stu[j].total== stu[j + 1].total)&&(stu[j].num >stu[j + 1].num)))
        {
            temp = stu[j];
            stu[j]= stu[j + 1];
            stu[j + 1]= temp;
            
        }
    }
}
//这里用来产生名次
    for (i = 0; i < n; i++) {
	    stu[i].placing = i + 1;
	    if (i > 0) {
	        if (stu[i].total == stu[i - 1].total) {
	            stu[i].placing = stu[i - 1].placing;
	        }
	    }
 	}
}
int main()
{
    struct SStudent a[10] = { 0 };
    int n = Read(a);
    Sort(a, n);
    Write(a, n);
    return 0;
}

##13.统计文章单词

2.通过完成函数完成以下程序代码,输入一篇文章(文章以半角句号结束),统计其中出现的单词(连续的字母)及出现频率,若有单词出现的频率相同,按字母顺序排序输出。输入输出示意如下:
aaa bbb ccc bbb ccc f.
bbb,2
ccc,2
aaa,1
f,1

#include <stdio.h>
#include <string.h>

struct SCount{
    char word[20];      // 单词
    int n;              // 出现次数
};

// 读取文章,返回读入字符个数
int Read(char s[]) {
    scanf("%[^\n]", s);
    getchar(); // 消耗掉输入缓冲区中的换行符
    return strlen(s);
}

// 统计单词出现频率,返回单词出现个数
int Count(char s[], struct SCount count[]) {
    int len = strlen(s);
    int word_count = 0;
    
    char word[20] = "";
    int word_len = 0;
    for (int i = 0; i <= len; i++) {
        if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
            word[word_len++] = s[i];
        } else {
            if (word_len > 0) {
                int found = 0;
                for (int j = 0; j < word_count; j++) {
                    if (strcmp(count[j].word, word) == 0) {
                        count[j].n++;
                        found = 1;
                        break;
                    }
                }
                if (!found) {
                    strcpy(count[word_count].word, word);
                    count[word_count].n = 1;
                    word_count++;
                }
                word_len = 0;
                memset(word, 0, sizeof(word));
            }
        }
    }
    
    return word_count;
}

// 比较函数,用于排序
int compare(const void *a, const void *b) {
    struct SCount *count1 = (struct SCount *)a;
    struct SCount *count2 = (struct SCount *)b;
    
    if (count1->n != count2->n) {
        return count2->n - count1->n; // 按出现次数从大到小排序
    } else {
        return strcmp(count1->word, count2->word); // 若出现次数相同,则按字母顺序排序
    }
}

// 排序函数
void Sort(struct SCount count[], int n) {
    qsort(count, n, sizeof(struct SCount), compare);
}

// 输出函数
void Write(struct SCount count[], int n) {
    for (int i = 0; i < n; i++) {
        printf("%s,%d\n", count[i].word, count[i].n);
    }
}

int main(){
    struct SCount count[100] = {0};
    char s[1000];
    int n;
    Read(s); // 读入文章,返回读入字符个数
    n = Count(s, count); // 统计单词出现频率
    Sort(count, n); // 排序
    Write(count, n); // 输出计数
    return 0;
}

13.插入字符串

3.通过完成函数完成以下程序代码,输一个字符串和一个字符,在字符串中的所有数字字符子串前插入该字符并输出。
输入输出示意如下:
AB1CD12EF123GH $
AB$1CD$12EF$123GH

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 函数功能在p指向的字符串中所有连续的数字字符子串前插入一个$符号。函数返回p指向字符串的起始地址
char* insert(char* p, char c) {
    int len = strlen(p);
    char *new_str = (char*)malloc(sizeof(char) * (2 * len + 1)); // 分配足够的空间存放可能的插入字符
    int new_index = 0;

    for (int i = 0; i < len; i++) {
        if (p[i] >= '0' && p[i] <= '9') {
            new_str[new_index++] = c; // 插入指定字符
        }
        new_str[new_index++] = p[i]; // 将原字符复制到新字符串中
    }
    new_str[new_index] = '\0'; // 字符串结尾

    return new_str;
}

int main()
{
    char s[100], c;
    scanf("%s %c", s, &c);
    char* result = insert(s, c); // 调用insert函数得到处理后的字符串
    printf("%s", result);
    free(result); // 释放动态分配的内存
    return 1;
}

14.汉诺塔

编写程序,输入金片的数量,输出金片移动的过程。
输出说明:一行为一次的移动过程,每行的数据包含3个:第几片金片、从哪根针上移走、移到哪根针上,数据之间用英文空格分割。
【注意】
(1)运行效果应如下所示,格式错误算结果错误。
(2)该题目要求使用递归函数完成,所要定义的函数头部如下所示。
void hanoi(int n,char a,char b,char c);
测试1:(第1行为输入,其余行为输出)
3
1 A C
2 A B
1 C B
3 A C
1 B A
2 B C
1 A C

#include "stdio.h"
void hanoi(int n,char a,char b,char c){

	if(n==1){
	   	printf("%d %c %c\n",n,a,c);
	   	return ;
	}
 	hanoi(n-1,a,c,b);
	printf("%d %c %c\n",n,a,c);
 	hanoi(n-1,b,a,c);
 	
}

int main(){
	int n;
    scanf("%d", &n);
    hanoi(n, 'A', 'B', 'C');
    return 0;
}

15.整数划分

整数划分问题:
例如,对于正整数n=6,可以分划为:
6
5+1
4+2, 4+1+1
3+3, 3+2+1, 3+1+1+1
2+2+2, 2+2+1+1, 2+1+1+1+1
1+1+1+1+1+1+1
请编写程序,输入正整数n,计算并输出共有多少种划分方法。
【注意】
(1)运行效果应如下所示,格式错误算结果错误。
(2)该题目要求使用递归函数完成。
测试1:(第1行为输入,第2行为输出)
6
11
测试1:(第1行为输入,第2行为输出)
10
42

#include"stdio.h"
f(int n,int m){
	if (n == 0){
		return 1;
	}
    if (n < 0 || m == 0) {
    	return 0;
	}
	return f(n-m,m)+f(n,m-1);	
} 
int main(){
	int n;
	scanf("%d",&n);
	printf("%d",f(n,n));
}

16.学生信息(链表实现)

通过完成函数实现以下程序功能:输入若干个学生信息到链表,输入-1代表结束,依输入次序输出所有学生,输入输出示意如下:
2107403005 郑洋 男 90
2107403003 杭丹丹 女 88
2107403002 陈可可 女 95
2107403001 赵文清 男 90
-1
2107403005,郑洋,男,90.00
2107403003,杭丹丹,女,88.00
2107403002,陈可可,女,95.00
2107403001,赵文清,男,90.00

#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
enum SEX{GIRL, BOY};
struct SStudent 
{
    int num;          //学号 
    char name[20];    //姓名
    enum SEX sex;     //性别
    float score;      //成绩
    struct SStudent* next;  //下一个节点地址
};
struct SStudent* addtail(struct SStudent* head, struct SStudent* st)
{
	if(head==NULL){
		 head = st;
        st->next = NULL;
		return head;
	}
	struct SStudent*p=head ;
	while(p->next){
		p=p->next;
	}
	p->next=st;
	st->next=NULL;
	return head;
}
void write(struct SStudent* head)
{
	struct SStudent *p=head;	
	while(p){
		printf("%d,%s,",p->num,p->name);
		if(p->sex==BOY){
			printf("男");
		}else{
			printf("女"); 
		} 
		printf(",%.2f\n",p->score);
		p=p->next;
	}
	
}
void freelink(struct SStudent* head)
{
	struct SStudent* p;
	while(head){
		p=head;
		head=head->next;
		free(p);
	}
}
int main()
{
    struct SStudent* head = NULL,t;
    char s[4];
    do 
    {
        scanf("%d", &t.num);
        if (t.num != -1)
        {
            scanf("%s%s%f", t.name, s, &t.score);
            t.sex = (strcmp(s, "男") == 0) ? BOY : GIRL;
            struct SStudent* newNode = (struct SStudent*)malloc(sizeof(struct SStudent));
             *newNode = t;
                newNode->next = NULL;
                head = addtail(head, newNode);
           // head = addtail(head, &t);            //这里原题的代码是直接传入一个地址,但不知道是不是我addtail写的有问题,直接传入地址没有办法正常输入好像。所以重新开辟了一个指针,把结构体类型的变量放到指针里,然后来操控指针。
        }
    }while(t.num!=-1);
    write(head);
    freelink(head);
    return 0;
}

17.逆序(文件读取)

编写一个C语言程序,将一个文本文件in.txt的内容逐行读取,并将这些行以相反的顺序写入到另一个文件out.txt中。(in.txt中少于1000行,每行字符少于1000个)
测试数据1:
输入:in.txt
Line 1
Line 2
Line 3
输出:out.txt
Line 3
Line 2
Line 1

#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#include <string.h>
int main(){
	FILE *input;
	FILE *output;
	int i=0,j=0;
	char line[1000][1000];    //把字符串存在数组里,用二维数组存
	if((input=fopen("in.txt","rt"))==NULL){
		printf("error");
		getch();
		exit(1);
	}
	while(fgets(line[i],1000,input)){    //fgets读取字符串,一行一行读
		i++;
	}
	fclose(input);
	if((output=fopen("out.txt","wt"))==NULL){
		printf("error");
		getch();
		exit(1);
	}
	for(j=i;j>=0;j--){
		fprintf(output,"%s",line[j]);
	}
	fclose(output);
	
} 

18.文件中查找整数

编写一个C语言程序,用于搜索一个指定的整数是否存在于二进制文件data.bin中。程序应输出该整数出现的次数以及每次出现的位置(相对于文件开头的偏移量)。生成测试文件的代码已给出,请直接复制后在框架内编码。运行示例:
测试数据1:
输入:键盘
1
输出1:显示器
Found at offset: 0
Found at offset: 20
Integer found 2 times.
测试数据2:
输入:键盘
7
输出:显示器
Integer not found in the file.
#include<stdlib.h>
#include<stdio.h>
#define NUM 10
int main()
{
//写测试文件
FILE* fp;
int i;
int a[NUM];
for (i = 0; i < NUM / 2; i++)
{
a[i] = i + 1;
a[i + 5] = i + 1;
}
if ((fp = fopen(“data.bin”, “wb”)) == NULL)
{
printf(“Error opening file!”);
exit(1);
}
fwrite(a, NUM, sizeof(int), fp);
fclose(fp);
}

#include<stdlib.h>
#include<stdio.h>
#define NUM 10
void search(int n){
	int cnt=0;
	int num;
	int offset=0;
	char ch;
	FILE* fp;
	if ((fp = fopen("data.bin", "rb")) == NULL) 
    {
        printf("Error opening file!");
        exit(1);
    }
    while(fread(&num,sizeof(int),1,fp)==1){
    	//p=fscanf(fp,"%d",&p);
    	if(num==n){
    		cnt++;
    		printf("Found at offset: %d\n",offset);   		
		}
		offset+=4;
	}
	    fclose(fp);
	if(cnt==0){
		printf("Integer not found in the file.");
	}else{
		printf("Integer found %d times.",cnt);   
	}
  		
}
int main() 
{
    //写测试文件
    FILE* fp;
    int i;
    int a[NUM];
    for (i = 0; i < NUM / 2; i++) 
    {
        a[i] = i + 1;
        a[i + 5] = i + 1;
    }
    if ((fp = fopen("data.bin", "wb")) == NULL) 
    {
        printf("Error opening file!");
        exit(1);
    }
    fwrite(a, NUM, sizeof(int), fp);
    fclose(fp);
    int n;
    scanf("%d",&n);
    search(n);
        fclose(fp);
}

19.排序

输入正整数m(m<10),接着输入m个字符串,再输入一个正整数n(n<=m)。以下程序中函数void csort(char str[][N], int n)对str指向的二维数组前n行中存储的n个字符串分别作如下处理:从中间将字符串一分为二,左半部分字符子串按字符的ASCII码值从大到小排序(若字符串的长度为奇数,则中间字符不参加排序)。输出前n行字符串排序后的结果。

#include<stdio.h>
#include<string.h>
#include<conio.h>
#define N 80
void csort(char str[][N], int n);
int main()
{
    char s[10][N];
    int i, n, m;
    scanf("%d", &m);
    for (i = 0; i < m; i++){
    	scanf("%s", s[i]);
	} 
    scanf("%d", &n);
    csort(s, n);
    for (i = 0; i < n; i++)
        puts(s[i]);
}
void csort(char str[][N], int n)
{
    int i, j, k, len, half;
    char temp;
    for (i = 0; i < n; i++)
    {
        len = strlen(str[i]);
        half = len / 2;
        for (j = 0; j < half ; j++){
        	for (k = j + 1; k < half ; k++){ //这里写冒泡排序的时候注意循环结束的范围,half代表前一半的长度,没有必要再减一了;
                if (str[i][j]< str[i][k])
                {
                    temp = str[i][j];
                    str[i][j] = str[i][k];
                    str[i][k] = temp;
                }
            } 
		} 
            
    }
}

20.链表学生信息操作(约瑟夫问题)

#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
enum SEX{GIRL, BOY};
struct SStudent
{
//    int num;          //学号
    char num[25];//TODO
    char name[20];    //姓名
    enum SEX sex;     //性别
    float score;      //成绩
    struct SStudent* next;  //下一个节点地址
};
//添加节点到末尾,尾节点的next指向head,形成首尾相连的环状链表
struct SStudent* addtail(struct SStudent* head, struct SStudent* st)
{
    if(head==NULL){
        head=st;
        st->next=head;
    }
    struct SStudent*p=head;
    while(p->next != head){//TODO
        p=p->next;
    }
    p->next=st;
    st->next=head;
    return head;
}
void del(struct SStudent* head, int n)
{
    struct SStudent* current = head;
    struct SStudent* prev = NULL;

    // 找到最后一个节点
    while (current->next != head)
    {
        current = current->next;
    }

    // 找到第一个节点
    current = head;

    // 循环直到只剩下一个人
    while (head->next != head)
    {
        int i;
        // 循环n-1次,找到要删除的人的前一个节点
        for ( i = 0; i < n - 1; i++)
        {
            prev = current;
            current = current->next;
        }

        // 输出要删除的人的名字
        printf("%s\n", current->name);

        // 删除current节点
        prev->next = current->next;

        // 释放当前节点的内存
        free(current);

        // current指向下一个节点
        current = prev->next;

        // 如果删除的是第一个节点,需要更新head指针
        if (current == head)
        {
            head = current->next;
        }
    }

    // 输出最后剩下的人的名字
    printf("%s\n", current->name);

    // 释放最后一个节点的内存
    free(current);
}
struct SStudent* read()
{
    struct SStudent *st;
    char s[4];
    struct SStudent* p,*head=NULL;
    //TODO
    do{
        st=(struct SStudent*)malloc(sizeof(struct SStudent));
        scanf("%s",st->num);
        if(strcmp(st->num,"-1") != 0){
            scanf("%s %s %f",&st->name,s,&st->score);
            st->sex=(strcmp(s,"男")==0)?BOY:GIRL;
            head=addtail(head,st);
        }else{
            break;
        }
    }while(strcmp(st->num,"-1") != 0);
    return head;
}
int main()
{
    struct SStudent* head = NULL;
    int n;
    head=read();  //创建一首尾相接的链表
    scanf("%d",&n); //读入n
    del(head,n);//循环删除报数为n的人并输出其名字
    return 0;
}

21.学生信息反转链表

#include "stdio.h"
#include<stdio.h>
#include<malloc.h> 
struct student
{
 int num;
 char name[20];
 int sex;
 int age;
 student* next;
};
void write(struct student *head){
	struct student *p=head;
	while(p){
		printf("%d %s %d %d\n",p->num,p->name,p->sex,p->age);
		p=p->next;
	}
}
struct student *addtail(struct student *head,struct student *p){
	struct student *tail=head;
	if(head==NULL){
		head=p;
		head->next=NULL;
		return head;
	}
	while(tail->next){
		tail=tail->next;
	}
	tail->next=p;
	p->next=NULL;
	return head;
	
}
struct student *reverse(struct student *head){
	struct student *curr=head;
	struct student *prev=NULL;
	struct student *next;
	while(curr){
		next=curr->next;
		curr->next=prev;
		prev=curr;
		curr=next;
		
	}
 head = prev;
    return head;
}
int main(){
	struct student stu;
	struct student *head=NULL;
	struct student *p;
	//read
	do{
		p=(struct student*)malloc(sizeof(struct student));
		scanf("%d",&p->num);
		if(p->num!=-1){
			scanf("%s %d %d",p->name,&p->sex,&p->age);
			head=addtail(head,p);
		}
	}while(p->num!=-1);
	//wirte
	head=reverse(head);
	write(head);
}

22.学生信息排序(链表)

按学号输出女生的学生信息
这里不一定先找女生再排序,完全可以先排序再找女生,在输出的时候操作就好了

#include<stdio.h>
#include<malloc.h> 
struct student
{
 int num;
 char name[20];
 int sex;
 int age;
 student* next;
};
struct student *insert(struct student *head,struct student *p);
struct student *addtail(struct student *head,struct student *p){
	if(head==NULL){
		head=p;
		p->next=NULL;
		return head;
	}
	struct student * tail=head;
	while(tail->next){
		tail=tail->next;
	}
	tail->next=p;
	p->next=NULL;
	return head;
	
}
struct student *sort(struct student *head){
	struct student *curr=head;
	struct student *prev;
	struct student *sorted=NULL;
	while(curr){                             //先把第一个节点断开,然后再调用插入函数 
		prev=curr;
		curr=curr->next;
		prev->next=NULL;
		sorted=insert(sorted,prev);
	}
	return sorted; 
} 
struct student *insert(struct student *head,struct student *p){
	struct student *curr=head;
	struct student *prev=NULL;
	if(head==NULL){
		head=p;
		p->next=NULL;
		return head;
	}
	while(curr){
		prev=curr;
		curr=curr->next;
		if(curr!=NULL&&curr->num>p->num){
			prev->next=p;
			p->next=curr;
			return head; 
		}
	}
	prev->next=p;
	p->next=NULL;
	return head;
}
void write(struct student *head){
	struct student *p=head;
	while(p){
		if(p->sex==0){
			printf("%d %s %d %d\n",p->num,p->name,p->sex,p->age);
		}		
		p=p->next;
	}
}
int main(){
	struct student *head=NULL;
	struct student *p;
	do{
		p=(struct student*)malloc(sizeof(struct student));
		scanf("%d",&p->num);
		if(p->num!=0){
			scanf("%s %d %d",p->name,&p->sex,&p->age);
			head=addtail(head,p);
		}
	}while(p->num!=0);
	sort(head);
	write(head);
}

23.C++数组排序

#include <iostream>
using namespace std;

class CArray{
 int *arr;    //数组
 int n;     //数组元素个数
public:
 CArray();    //构造函数
 CArray(int a[],int n) //构造函数
 {
 	arr=a;
 	this->n=n;
 }
 CArray(CArray &t) //拷贝构造函数
 {
 	arr=t.arr;
 	this->n=t.n;
 }
 ~CArray(){
 	if (arr) {
            delete[] arr;
        }
 }    
 int Insert(int x)  //在数组中插入整数x,保持数组从小到大排序
 {
 	//在已经是升序数组里插入,可以弄一个新数组,把原数组的数据搬进去
	  int *newArr =new int [n+1];
	  int i,j=0;
	  while(i<n&&arr[i]<x){
	  	newArr[j]=arr[i];
	  	i++;
	  	j++;
	  } 
	  newArr[j]=x;
	  j++;
	  while(i<n){
	  	newArr[j]=arr[i];
	  	i++;
	  	j++;
	  }
	  arr =newArr;
	  n++;
	  return j;
 }
 void Print()   //输出数组
{
 	int i;
 	for(i=0;i<n;i++){
 		cout<<arr[i]<<" ";
	}
}
};
int main() {
 int a[] = { 3,6,9 },x;
 CArray a1(a, 3),a2(a1);
 for (int i = 0; i < 5; i++) {
  cin >> x;
  a2.Insert(x);
 }
 a2.Print();
 return 0;
}

24.字符串类

#include <iostream>
#include<cstring>
using namespace std;

class CString
{
	public :char *str;    //字符串
	public:
	 CString();    //构造函数
	 CString(const char s[])  //构造函数
	 {
	 	int len=strlen(s);
	 	str=new char(len+1);
	 	strcpy(str,s);
	 }
	 CString(CString&t)  //拷贝构造函数
	 {
	 	int len=strlen(t.str);
	 	str=new char(len+1);
	 	strcpy(str,t.str);
	 }
	 ~CString(){
	 	if(str){
	 		delete []str;
		 }
	 }
	 int Set(const char s[]){           //设置 
	 	int len=strlen(s);
	 	str=new char(len+1);
	 	strcpy(str,s);
	 }
	 void Print()  //输出
	 {
		cout<<str;
	 }
};
class CString2 :public CString
{
	public:
		 CString2():CString(){}  //构造函数
		 CString2(const char s[]):CString(s){} //构造函数
		 CString2(CString2& t):CString(t){}  //拷贝构造函数
		 CString2 &Cat(CString2&t)   //字符串连接
		 {
		 	char *temp=new char[strlen(str)+strlen(t.str)+1];
		 	strcpy(temp,str);
		 	strcat(temp,t.str);
		 	str=temp;
		 	return *this;
		 }
		 int Cmp(CString2& t)      //字符串比较
		 {
		 	return strcmp(str,t.str);
		 }
};
int main(){
	 char s0[100], s1[100];
	 cin >> s0 >> s1;
	 CString2 cs0(s0),cs1(cs0);
	 cs0.Set(s1);
	 cout << cs0.Cmp(cs1) << endl;
	 CString2 &t=cs0.Cat(cs1);
	 t.Print();
	 return 0;
}
  • 13
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值