山东大学计算机导论与程序设计基础实验5-9

A : 实验5 字符串的输入输出

题目描述

利用循环结构连续调用scanf(”%[^\n]”,str) 输入多个字符串,并使用printf(),将str输出。根据str的输出结果,观察是否在输入一个字符串后,后续的scanf(”%[^\n]”,str)中,会将缓冲区中残留的回车换行符读入到str中。

提示:利用格式scanf(”%[^\n]”,str)输入;
注意输入缓冲区的数据残留;如scanf(”%[^\n]”,str)语句会造成输入缓冲中残留回车换行符。 根据str的输出结果理解输入缓冲区残留的问题,并使用相应的解决方案,以消除数据残留所带来的副作用。

输入格式

第一行一个整数n,代表接下来有多少行字符串需要读取,接下来n行为待读取的字符串,字符串中包含空格。

输出格式

输出读入的n行字符串

注意

A 题不能使用 fflush 函数清空缓冲区,请换用其他函数(具体原因与 OJ 数据输入形式有关)。

完整答案代码

#include<stdio.h>
int main()
{
	int n;
	scanf("%d\n",&n);
	int i;
	char str[10001];
	for(i=0;i<n;i++){
		scanf("%[^\n]%*c",str);
	
		printf("%s\n",str);
	
	}
	return 0;
 } 

B : 实验5 复数转换

题目描述

键盘输入一个英文单词,输出其对应的复数形式

规则如下:

(a)以辅音字母+y结尾,则将y变成i,再加es;

(b)以s,x,ch,sh,o结尾,加es;

(c)其它情况,加s;

注:系统只会提供符合以上变换规律的英文单词

输入格式

一个字符串,为待变换的单词

输出格式

一个字符串,为变换后的单词

完整答案代码

#include<stdio.h>
int main()
{
	char str[1001];
	scanf("%s",str);
	int len;
	int i;
	i=0;
	while(str[i]!='\0'){
		i++;
		len++; 
	}
	if(str[len-1]=='y'){
		str[len-1]='i';		
		printf("%ses",str);
	}else if(str[len-1]=='s'||str[len-1]=='x'||str[len-1]=='o'){
		printf("%ses",str);
	}else if((str[len-2]=='c'||str[len-2]=='s')&&str[len-1]=='h'){
		printf("%ses",str);
	}else{
		printf("%ss",str);
	}
	return 0;
}

C : 实验6 整数的进制转换

题目描述

系统将给出三个数:A、B、C,其中C是A进制数,要求将C转换为B进制数。

  • A、B均为整数
  • A、B的值在2、8、10、16中选取
  • C的长度不大于10
  • 16进制中字母的输入输出均为小写
  • 注:将数制之间的转换方法利用程序实现,不能利用itoa()系列函数进行自动转换,不允许直接利用“%d”、”%o”及”%x”等格式由机器自动转换。

输入格式

两个整数:A、B;一个字符串C,其中C是A进制数,要求将C转换为B进制数。

输出格式

一个字符串

完整答案代码

#include<stdio.h>
#include<math.h>
int main()
{
	int a,b;
	char c[1001];
	scanf("%d%d %s",&a,&b,c);
	int i;
	int n[1001];
	int len=0;
	int d=0;
	int s=0;
	if(a==b) printf("%s",c);
	for(i=0;c[i]!='\0';i++){
		len++;
	}
	int l=len;
	
	for(i=0;i<l;i++){
		if(c[i]>='0'&&c[i]<='9'){
			n[l-1-i]=c[i]-'0';
		}
		if(c[i]=='a'){
			n[l-1-i]=10;
		}else if(c[i]=='b'){
			n[l-1-i]=11;
		}else if(c[i]=='c'){
			n[l-i-1]=12;
		}else if(c[i]=='d'){
			n[l-1-i]=13;
		}else if(c[i]=='e'){
			n[l-1-i]=14;
		}else if(c[i]=='f'){
			n[l-1-i]=15;
		}
	}
	for(i=0;i<len;i++){
		d=d+n[i]*pow(a,i);
	}	
	if(b==10){
		printf("%d",d);
	}else{
		int t=d;
		int m=d;
		i=0;
		while(t!=0){
			t=t/b;
			s++;
		}
		int x[s];
		for(i=0;i<s&&m!=0;i++){
			x[i]=m%b;
			m=m/b;
		}
		
			for(i=s-1;i>=0;i--){
				if(x[i]==10){
					printf("a");
				}else if(x[i]==11){
					printf("b");
				}else if(x[i]==12){
					printf("c");
				}else if(x[i]==13){
					printf("d");
				}else if(x[i]==14){
					printf("e");
				}else if(x[i]==15){
					printf("f");
				}else{
					printf("%d",x[i]);
				}
			}
		
	}

	return 0;
}

D : 实验6 浮点数的进制转换

题目描述

系统将给出三个数:A、B、C,其中C是A进制数,要求将C转换为B进制数。

  • A、B均为整数
  • A、B的值在2、8、10、16中选取
  • C的长度不大于10
  • 16进制中字母的输入输出均为小写
  • 注:将数制之间的转换方法利用程序实现,不能利用itoa()系列函数进行自动转换,不允许直接利用printf()的“%d”、”%o”及”%x”等格式由机器自动转换。

输入格式

两个整数A、B和一个小数C,其中C是A进制数,要求将C转换为B进制数。

输出格式

一个数,如果为浮点数且小数点后超过八位输出八位即可,无需在后面补零。如果为整数则输出整数。

数据描述

测试点编号12345678910111213141516
A10101022216161616222161616
B281681016102816101010288

注意

D 题整体难度较大,推荐放到后面去做(其实转换为任意进制都是同样的算法,一法通万法通)。

完整答案代码

#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
	int a,b;
	scanf("%d%d",&a,&b);
	char c[1001];
	scanf("%s",c);
	int len=strlen(c);
	char o[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
	char z[1001],f[1001];
	int lenz=0;
	int lenf=0;
	int i;
	for(i=0;i<len;i++){
		if(c[i]=='.'){
			z[i]='\0';
			break;
		}
		if(c[i]=='\0'){
			z[i]='\0';
			break;
		}
		z[i]=c[i];
		lenz++;
	}
	for(i=0;lenz+i+1<len;i++){
		f[i]=c[lenz+i+1]; 
		lenf++;
	}
	int z1=0;
	int a1=1;
	for(i=lenz-1;i>=0;i--){
		if(z[i]>='a'&&z[i]<='f'){
			z1=z1+(z[i]-'a'+10)*a1;
		}else{
			z1=z1+(z[i]-'0')*a1;
		}
		a1=a1*a;
	}
	double f1=0;
	double a2;
	a2=1.0/a;
	for(i=0;i<lenf;i++){
		if(f[i]>='a'&&f[i]<='f'){
			f1=f1+(f[i]-'a'+10)*a2;
		}else{
			f1=f1+(f[i]-'0')*a2;
		}
		a2=a2/a;
	}
	char zp[1001],fp[1001];
	int lenz2=0;
	int lenf2=0;
	for(i=0;z1>0;i++){
		int y=z1%b;
		zp[i]=o[y];
		z1/=b;
		lenz2++;
	}
	for(i=0;f1>0;i++){
		int y=f1*b;
		fp[i]=o[y];
		f1=f1*b-y;
		lenf2++;
		if(f1<=0){
			break;
		}
	}
	for(i=lenz2-1;i>=0;i--){
		printf("%c",zp[i]);
	}
	if(lenz2==0){
		printf("0");
	}
	if(lenf2!=0){
		printf(".");
		for(i=0;i<lenf2;i++){
			printf("%c",fp[i]);
			if(i==7){
				break;
			}
		}
	}
	return 0; 
}

E : 实验7 递推

题目描述

编程求解青蛙跳台阶的问题:青蛙跳台阶问题:有n个台阶,每次青蛙可以选择跳1个台阶、2个台阶或者3个台阶,青蛙爬到第n个台阶,共有多少种走法?
提示:
设f(n)表示青蛙爬到第n个台阶的走法。
原问题分解为3个子问题:
如果青蛙目前站在第n-1台阶上,一步迈1个台阶即可到达第n个台阶;
如果青蛙目前站在第n-2台阶上,一步迈2个台阶即可到达第n个台阶;
如果青蛙目前站在第n-3台阶上,一步迈3个台阶即可到达第n个台阶;
因此,当n>3时,f(n)=f(n-1)+ f(n-2)+ f(n-3) ;
其中,f(1)=1 (1种走法:迈1个台阶,表示为1)
f(2)=2 (2种走法:两个一步,或一个2步,表示为11或2)
f(3)=f(1)+f(2)+1=1+2+1=4;(4种走法:表示为111,12,21,3)
因此有递推公式,f(n)=f(n-1)+ f(n-2)+ f(n-3),n>3;

输入格式

一个整数N,代表第N个台阶,N<40

输出格式

一个整数M,代表爬到第N个台阶可能的走法数量

注意

E 题尽量使用递推形式求解,递归易导致超时。可以使用尾递归进行优化,有兴趣的同学可以尝试。

#include<stdio.h>
int main()
{
	int n;
	scanf("%d",&n);
	int i;
	int f[n+1];
	f[0]=1;
	f[1]=1;
	f[2]=2;
	for(i=3;i<=n;i++){
		f[i]=f[i-1]+f[i-2]+f[i-3];
	}
	printf("%d",f[n]);
	return 0;
}

F : 实验7 线性同余法

题目描述

编程利用线性同余法产生n个随机数,理解随机数产生方法,以及随机数种子的作用与含义;

线性同余法是一个经典的伪随机数发生器,算法如下:
a)将X(0)作为随机数的种子;
b)根据递推公式X(n+1) = (a*X(n)+b) mod M,依次产生一个随机数序列X(1),X(2),…
本题为函数题,请你根据函数所给的参数,完成本题。

其中,M的作用是产生0到M-1之间的伪随机数,因此M的大小直接影响伪随机数序列的周期长短,故M尽可能取比较大的值;
a和b的值越大,产生的伪随机数也越均匀
如果a和M如果互质,产生随机数效果更好。
例如:a.b可定义为int型;
数组X可定义为int型,但要防止a,b取值太大,造成X[i]溢出;
M可取随机数的最大值RAND_MAX(0x7FF);
种子X(0)可依次取1,2,3,…,或取当前时间作为种子,测试你生成的随机数;

输入格式

第一行为5个整数,分别为需产生随机数个数N,随机数种子seed,递推公式中a,b,M;

输出格式

输出共N个,为产生的n个随机数,以空格分隔。

完整答案代码

#include<stdio.h>
int main()
{
	int n,seed,a,b,m;
	scanf("%d%d%d%d%d",&n,&seed,&a,&b,&m);
	long long x[n+1];
	x[0]=seed;
	int i;
	for(i=1;i<=n;i++){
		x[i]=(a*x[i-1]+b)%m;
	}
	for(i=1;i<=n;i++){
		printf("%d ",x[i]);
	}
	return 0;
}

G : 实验9 排序

题目描述

给定一组整数(包括正数与负数),利用冒泡法将数据按升序排列。

输入格式

第一行一个参数N,为这一组数的个数; 0 < N < 1000 0 \lt N \lt 1000 0<N<1000,第二行为N个整数,为待排序的数

输出格式

输出排序后的整数,中间使用空格分隔

注意

G题倘若出现本地测试正常但是提交出现 RE,最大可能是数组越界导致。可以尝试动态开辟内存(🔍 搜索 C 语言动态内存分配)或者直接申请一块较大的数据区域,推荐使用前者。

完整答案代码

#include<stdio.h>
int main()
{
	int n;
	scanf("%d",&n);
	int i,t,j;
	int a[n];
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	} 
	for(i=0;i<n;i++){
		for(j=i+1;j<n;j++){
			if(a[i]>=a[j]){
				t=a[i];
				a[i]=a[j];
				a[j]=t;
			}
		}
	}
	for(i=0;i<n;i++){
		printf("%d ",a[i]);
	}
	return 0;
}

H : 实验9 查找

题目描述

给定一组排序后递增的整数,再给定一个整数,使用折半查找法判断该整数是否在整数组内,并输出其下标

输入格式

第一行参数N,M;N为这一组数的个数,M为待查找的数;第二行为N个整数,为排序后的数。

输出格式

一个整数J,若能找到,则输出该整数在数组内的下标,若无法找到,则输出-1;

注意

H 题倘若出现本地测试正常但是提交出现 RE,最大可能是数组越界导致。可以尝试动态开辟内存(🔍 搜索 C 语言动态内存分配)或者直接申请一块较大的数据区域,推荐使用前者。

完整答案代码

#include<stdio.h>
int main()
{
	int n,key;
	scanf("%d%d",&n,&key);
	int a[n];
	int i,p;
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	int star,end,mid;
	star=0;
	end=n-1;
	mid=(star+end)/2;
	while(star<end){
		mid=(star+end)/2;
		if(mid==star||mid==end){
			p=-1;
			break;
		}
		if(a[mid]==key){
			p=mid;
			break;
		}else if(a[mid]>key){
			end=mid;
		}else if(a[mid]<key){
			star=mid;
		}
	}
	if(star>end){
		p=-1;
	}
	printf("%d",p);
	return 0;
}

I : 实验9 蒙特卡罗算法

题目描述

利用蒙特卡罗法计算定积分与π的近似值。
计算定积分的近似值
函数f(x)从a到b的定积分,就是求f(x)曲线下方的面积,如下图所示。
在这里插入图片描述

可以用一个比较容易计算面积的矩型包含函数的积分区间,然后随机地向这个矩形框里面投点,假设落入矩形区域内的点数为M,落在函数f(x)下方的点数为N,则面积之比即为点数之比。
设矩形面积为A, f ( x ) f(x) f(x)下方的面积为B,则有 A B = M N \frac{A}{B}=\frac{M}{N} BA=NM,即 B = N M A B=\frac{N}{M} A B=MNA,由此可计算定积分 ∫ a b f ( x ) d x \int_{a}^{b} f(x) dx abf(x)dx的近似值。投点的数量越来越多,其近似值也越接近真实值。

利用上述思想编程计算 ∫ 1 2 1 x d x \int_{1}^{2} \frac{1}{x} dx 12x1dx的近似值。
由于 ∫ 1 2 1 x = ln ⁡ 2 − ln ⁡ 1 = ln ⁡ 2 \int_{1}^{2} \frac{1}{x} = \ln2 - \ln1 = \ln2 12x1=ln2ln1=ln2,因此求得的值为 ln ⁡ ⁡ 2 \ln⁡2 ln⁡2的近似值。
定积分 ∫ 1 2 1 x d x \int_{1}^{2} \frac{1}{x} dx 12x1dx图像如下图所示。

提示: 取 n 个随机点 ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x n , y n ) 取n个随机点(x_1,y_1 ),(x_2,y_2 ),…,(x_n,y_n ) n个随机点(x1,y1),(x2,y2),,(xn,yn),限定 1 ≤ x i ≤ 2 , 0 ≤ y i ≤ 1 1 \leq x_i \leq 2,0 \leq y_i\leq 1 1xi2,0yi1则这n个点都在所标矩形的范围内;
矩形的面积为A=(2-1)*(1-0),阴影部分的面积设为S;
若这n个点中有m个落入阴影内,则 m n = S A \frac{m}{n} = \frac{S}{A} nm=AS,则 S = m n × A = m n × ( 2 − 1 ) × ( 1 − 0 ) = m n S=\frac{m}{n}×A=\frac{m}{n}×(2-1)×(1-0)=\frac{m}{n} S=nm×A=nm×(21)×(10)=nm,即为所给定积分的近似值。
随机数的产生于使用方法参见教材第12章:蒙特卡洛法。

注:为了便于自动化测评,我们对你的输入有一定的限制。我们会提供随机数种子以及循环的次数以保证结果的可重复性。

输入格式

两个整数seed,N;
seed为传入的随机数种子,N为循环的次数

输出格式

一个浮点数N,为求得的结果
注:windows和linux产生随机数的方式不一样,样例中的结果为在linux系统下的结果,windows下的结果为0.694445
注:由于这道题目目前没有spj,建议将+1的数放在上面,即先进行赋值

注意

I 题可能出现本地求解与题目示例不同的情况(也即精度有差异),大家可以在保证算法思路正确的情况下尝试提交。

完整答案代码

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int seed;
	int n;
	int m=0;
	scanf("%d%d",&seed,&n);
	srand(seed);
	float x,y;
	float ln;
	int i;
	for(i=0;i<n;i++){
		x=1.0+(float)rand()/(RAND_MAX+1.0);
		y=(float)rand()/(RAND_MAX+1.0);
		
		if(y<=(1/x)){
			m++;
		}
	}
	ln=(float)m/n;
	printf("%f",ln);
	
	return 0;
}

如能打赏,不胜感激[叩谢]。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值