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