A3_众数问题
图1 功能框架图 图2 数组存储算法图 图3 频率统计算法图 图4 求数组重数算法图 图5 调整重数算法图 图6 核心设计流程图- 众数问题_B19030825.cpp
#include <iostream>
#include <cstring>
#include <stdlib.h>
using namespace std;
int main(){
int n,i,j,temp; //临时输入存入 temp
int array[1000][2]={(0,0)}; //可存放1000个自然数及其频率
re: cout<<"\n>> 请输入自然数个数n:"; cin>>n; //自然数个数
if(n<=0){ //错误输入 n
cout<<"\nERROR:请输入正数!\n";
goto re;
}
cout<<"\n>> 请输入n个自然数:";
for(i=0;i<n;i++){
re2: cin>>array[i][0];
if(array[i][0]<0){ //错误输入自然数
cout<<"\nERROR:请输入自然数!\n";
goto re2;
}
}
for(i=0;i<n;i++){ //统计自然数出现次数
for(j=0;j<n;j++){
if(array[j][0]==array[i][0])
array[i][1]++;
}
}
int max=0;
for(i=0;i<n;i++){ //统计数组重数
if(array[i][1]>max)
max=array[i][1];
cout<<"\n自然数:"<<array[i][0]<<" 频率:"<<array[i][1]*1.0/n<<endl;
}
for(i=0;i<n;i++){ //将重复众数的重数置 0,避免重复输出
if(array[i][1]==max){
for(j=i+1;j<n;j++){ //只保留第一次出现的众数
if(array[j][0]==array[i][0])
array[i][1]=0;
}
}
}
for(i=0;i<n;i++){ //输出所有众数、重数
if(array[i][1]==max)
cout<<"\n集合S的众数:"<<array[i][0]<<" 重数:"<<array[i][1]<<endl;
}
return 0;
}
图7 测试结果截图一
图8 测试结果截图二
图9 测试结果截图三
图10 测试结果截图四
程序调试过程中的问题
问题1:最开始想的是用链表结点存储数组元素,但是遍历结点的值总是和预期效果不一致,而且调试的时候总是报错。
解决方法:采用自己更熟练的二维数组数据结构存储。
问题2:输出重数以及众数的时候,重复输出。
解决方法:意识到一个重要的规律:重数只能有一个,而众数可以有多个。所以可以将多个相同众数的重数调整为一个,此时不在需要用到重复的众数,将其置0,最后得到数组所有不重复众数的重数。
问题3:刚开始准备沿用临时链表结点的思想,创建另一个二维数组存储众数,却发现代码冗长。
解决方法:直接用同一个二维数组存储、计算、输出。
问题4:在调试的时候,输出频率竟然随机出错。
解决方法:局部变量n是终端输入,而计算频率时array[i][1]用到了n,当时array的初始化为array[][2]={(0,0)},没有明确指明n。所以改为array[1000][2]={(0,0)}解决了问题。
B3_大整数算术运算器
图1 功能框架图 图2 字符串转换/倒序存储算法图 图3 比较大整数大小算法图 图4 大整数加法算法图 图5 大整数减法算法图 图6 大整数乘法算法图 图7 大整数除法算法图 图8 核心设计流程图- 大整数算术运算器_B19030825.cpp
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
struct big_number{ //大整数结构体
int d[1000];
int len; //大整数位数
big_number(){ //构造函数,用来初始化
d[1000]={0};
len=0;
}
};
big_number change(char str[]){ //将大整数字符串存储在结构体
big_number x;
x.len=strlen(str);
for(int i=0;i<x.len;i++) //把大整数的低位切换为高位
x.d[i]=str[x.len-i-1]-'0'; //例:str='12345', a=[5,4,3,2,1]
return x;
}
int compare(big_number a,big_number b){ //比较两个大整数的大小
if(a.len>b.len)return 1; //a大于b,返回 1
else if(a.len<b.len)return 0; //a小于b,返回 0
else{
for(int i=a.len-1;i>=0;i++){ //从高位到低位逐一比较
if(a.d[i]>b.d[i])return 1;
else if(a.d[i]<b.d[i])return 0;
}
}
return 1;
}
big_number add(big_number a,big_number b){//1、加法运算
big_number c;
int carry=0,temp; //进位标志,本位和
int i;
for(i=0;i<b.len;i++){ //从低位到高位相加
temp=a.d[i]+b.d[i]+carry;
c.d[c.len++]=temp%10;
// cout<<"\ncarry:"<<carry<<" temp:"<<temp<<" result:"<<c.d[i]<<endl;
carry=temp/10;
}
if(carry!=0) //如果最高位进位
c.d[c.len++]=a.d[i++]+carry;
for(;i<a.len;i++)
c.d[c.len++]=a.d[i];
return c;
}
big_number sub(big_number a,big_number b){//2、减法运算
big_number c;
int i;
for(i=0;i<b.len;i++){
// int carry=0;
if(a.d[i]<b.d[i]) { //如果不够减,向高位借
if(a.d[i+1]>0){ //如果高位为正
a.d[i+1]--;
a.d[i]+=10;
}
else{ //如果高位为 0
a.d[i+1]=9;
a.d[i]+=10;
}
// carry=-1;
}
c.d[c.len++]=a.d[i]-b.d[i];
// cout<<"\ncarry:"<<carry<<" a[i]:"<<a.d[i]<<" b[i]:"<<b.d[i]<<" result:"<<c.d[c.len-1]<<endl;
}
//方案A:先 c.len=a.len,再遍历 i<a.len求得 c。例:a=10345,b=123,c=00000->10222
//方案B:先遍历 i<b.len,再将 a的高位赋值给 c。例:a=10345,b=123,c=222->10222
for(;i<a.len;i++) //这里采用的方案 B
c.d[c.len++]=a.d[i];
while(c.len-1>=1&&c.d[c.len-1]==0)
c.len--; //去除为 0的高位,同时保留一个最低位
return c;
}
big_number multi(big_number a,int b){ //3、乘法运算
big_number c;
int carry=0;
for(int i=0;i<a.len;i++){ //a从低位到高位依次乘 b
int temp=a.d[i]*b+carry;
c.d[c.len++]=temp%10;
// cout<<"a[i]:"<<a.d[i]<<" b:"<<b<<" carry:"<<carry<<" temp:"<<temp<<" c[i]:"<<c.d[c.len-1]<<endl;
carry=temp/10;
}
while(carry!=0){ //如果最高位进位
c.d[c.len++]=carry%10;
carry/=10;
}
return c;
}
big_number divide(big_number a,int b,int &r){//4、除法运算
big_number c;
c.len=a.len;
for(int i=a.len-1;i>=0;i--){ //a从高位到低位依次除 b
r=r*10+a.d[i];
if(r<b) c.d[i]=0;
else{
c.d[i]=r/b;
r=r%b;
}
// cout<<"a[i]:"<<a.d[i]<<" r:"<<r<<" b:"<<b<<" c[i]:"<<c.d[i]<<endl;
}
while(c.len-1>=1&&c.d[c.len-1]==0)
c.len--; //去除为0的高位,同时保留一个最低位
return c;
}
void print(big_number a){ //终端输出
for(int i=a.len-1;i>=0;i--)
printf("%d",a.d[i]);
}
void show(char line1[1000],char line2[1000],char ysf){//输出文本内容
cout<<"\na: "<<line1<<endl;
cout<<"\nb: "<<line2<<endl;
cout<<"\n运算符: "<<ysf<<endl;
}
void put_wb(big_number result,FILE *wb2){ //保存结果到文本
for(int i=result.len;i>=0;i--)
fprintf(wb2,"%d",result.d[i]);
}
void ZDCZ(){
char str1[1000],str2[1000]; //可以存储1000位大整数
big_number a,b; //加数,减数,被乘数,被除数
int r,c,d; //乘数,除数,余数
cout<<"\n【 1:大整数加法 2:大整数减法 3:大整数乘法 4:大整数除法 5:退出 】\n";
re: cout<<"\n>> 请输入操作选项:"; char choice2; cin>>choice2;
switch(choice2){
case '1':
cout<<"\n>> 请输入大整数a、b:"; cin>>str1>>str2;
a=change(str1); b=change(str2);
cout<<"\na+b= ";
if(compare(a,b)) print(add(a,b));
else print(add(b,a));
cout<<endl; goto re;
case '2':
cout<<"\n>> 请输入大整数a、b:"; cin>>str1>>str2;
a=change(str1); b=change(str2);
cout<<"\na-b= ";
if(compare(a,b)) print(sub(a,b));
else{
cout<<"-";
print(sub(b,a));
}
cout<<endl; goto re;
case '3': //能力有限,要求被乘数不超过 8位
cout<<"\n>> 请输入大整数a、b:"; cin>>str1>>c;
a=change(str1);
cout<<"\na*b= "; print(multi(a,c));
cout<<endl; goto re;
case '4': //能力有限,要求被除数不超过 8位
re2: cout<<"\n>> 请输入大整数a、b:"; cin>>str1>>d;
if(d==0){
cout<<"\nERROR:除数不能为0,请重新输入!\n";
goto re2;
}
a=change(str1); r=0;
cout<<"\na/b= "; print(divide(a,d,r));
cout<<"···"<<r<<endl; goto re;
case '5':
break;
default:
cout<<"\nERROR:输入错误,请重新输入!\n"; goto re;
}
}
void WBCZ(){
big_number a,b; //加数,减数,乘数,除数
int r=0,c,d,result; //被乘数,被除数,余数,运算结果
char line1[1000],line2[1000],line3[1000];
FILE *wb = fopen("ab.txt","r");
FILE *wb2 = fopen("result.txt","w");
if(!wb) cout<<"\nwarning:文本为空!\n";
fscanf(wb,"%s",line1);
fscanf(wb,"%s",line2);
fscanf(wb,"%s",line3);
switch(line3[0]){
case '+':
show(line1,line2,line3[0]);
a=change(line1); b=change(line2);
fprintf(wb2,"a+b= ");
put_wb(add(a,b),wb2);
cout<<"\nSuccessfully:运算结果已经写入文本!\n";
break;
case '-':
show(line1,line2,line3[0]);
a=change(line1); b=change(line2);
if(compare(a,b)){
fprintf(wb2,"a-b= ");
put_wb(sub(a,b),wb2);
}
else{
fprintf(wb2,"a-b= -");
put_wb(sub(b,a),wb2);
}
cout<<"\nSuccessfully:运算结果已经写入文本!\n";
break;
case '*':
show(line1,line2,line3[0]);
a=change(line1); c=atoi(line2);
fprintf(wb2,"a*b= ");
put_wb(multi(a,c),wb2);
cout<<"\nSuccessfully:运算结果已经写入文本!\n";
break;
case '/':
show(line1,line2,line3[0]);
a=change(line1); d=atoi(line2);
if(d==0){
cout<<"\nERROR:除数不能为0,请重新输入!\n";
goto close;
}
fprintf(wb2,"a/b= ");
put_wb(divide(a,d,r),wb2);
fprintf(wb2," ··· %d",r);
cout<<"\nSuccessfully:运算结果已经写入文本!\n";
break;
default:
cout<<"\nERROR:运算符错误,或文本为空!\n";
break;
}
close:fclose(wb);
}
int main(){
cout<<"\n【 方案A:终端输入、输出 】\n\n【 方案B:文本输入、输出 】\n";
cout<<"\n>> 请输入操作选项:"; char choice; cin>>choice;
if(choice=='A') {ZDCZ(); return 0;} //终端操作
if(choice=='B') {WBCZ(); return 0;} //文本操作
}
图9 测试结果截图一
图10 测试结果截图二
图11 测试结果截图三
图12 测试结果截图四
图13 测试结果截图五
图14 测试结果截图六
图15 测试结果截图七
图16 测试结果截图八
图17 测试结果截图九
图18 测试结果截图十
图19 测试结果截图十一
程序调试过程中的问题
问题1:在编写乘法和除法时,我意识到不再是一位一位的处理数据,而是将乘数(除数)看作一个整体,而被乘数(被除数)仍然当作结构体(大整数数组)处理。
解决方法:将乘法和除法的乘数(除数)改为int类型即可。
问题2:在编写文本操作之乘法和除法时,第二行不能用change函数转换。
解决方法:因为change函数是将字符串转数组,所以换做将字符串转整型即可(利用algothorm库的atoi函数)。
问题3:在编写调整减法高位位置时,发现不能采用像加法那样遍历较大数的位数。
解决方法:方案A:先 c.len=a.len,再遍历 i<a.len求得 c。例:a=10345,b=123,c=00000->10222。方案B:先遍历 i<b.len,再将 a的高位赋值给 c。例:a=10345,b=123,c=222->10222
问题4:在调试减法时,发现当a<b时输出错误。
解决方法:因为采用的数组存储的大整数,所以当a<b时,减出来高位可能会为负。创建一个compare函数,先比较两数大小,保证sub函数参数传入时:第一个数大于等于第二个数。然后输出时前面加上负号即可。
课程设计总结
通过这次实验设计,我懂得了当程序编写遇到问题时不要顽固自封,不要守着一个方法做,换一种思路从头再来可能更加顺利。在刚开始编写时,虽然做到了实验要求里基本的简单输入要求,但当输入数据值、数据量情况多变时,就会出现错误。而这样的结果并不完美,这样的程序没有普适性,更没有实用性。所以我们应该不断优化自己的代码,不断考虑各种终端的操作情况,因为写出来的程序不光是拿给自己用,也是给别人用。如果用户的输入不在你的意料之中而出现报错,那么这个程序就失败了。这次B3实验我写的代码虽然成功运行了,但是还有一些bug需要优化,比如:终端/文本操作不能一次输入多个表达式(终端只能多次输入一个表达式),加法运算不支持负数输入(而是偷懒转线用减法),而乘法和除法没有做到两个(>20位)大整数的计算。
A3_众数问题拓展:界面实现
#include <graphics.h> // 引用图形库头文件
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <iostream>
#include <cstring>
using namespace std;
int r[3][4] = { {30,20,100,80},{140,20,210,80},{250,20,320,80} }; //三个按钮的二维数组
char s[30]; //输入字符串变量
int button_judge(int x, int y){ //按钮判断函数
if (x > r[0][0] && x<r[0][2] && y>r[0][1] && y < r[0][3])return 1;
if (x > r[1][0] && x<r[1][2] && y>r[1][1] && y < r[1][3])return 2;
if (x > r[2][0] && x<r[2][2] && y>r[2][1] && y < r[2][3])return 3;
return 0;
}
void simulation(int n,int array[1000][2]){ //运行函数
int i,j;
for(i=0;i<n;i++){ //统计自然数出现次数
for(j=0;j<n;j++){
if(array[j][0]==array[i][0])
array[i][1]++;
}
}
int max=0;
for(i=0;i<n;i++){ //统计数组重数
if(array[i][1]>max)
max=array[i][1];
cout<<"当前自然数:"<<array[i][0]<<" 频率:"<<array[i][1]*1.0/n<<endl;
}
for(i=0;i<n;i++){ //将重复众数的重数置 0,避免重复输出
if(array[i][1]==max){
for(j=i+1;j<n;j++){ //只保留第一次出现的众数
if(array[j][0]==array[i][0])
array[i][1]=0;
}
}
}
for(i=0;i<n;i++){ //输出所有众数、重数
if(array[i][1]==max)
cout<<"集合S的众数:"<<array[i][0]<<" 重数:"<<array[i][1]<<endl;
}
}
int main(){
int array[1000][2] = { (0,0) };
int event = 0,n,i; //n是自然数个数
short win_width, win_height; //定义窗口的宽度和高度
win_width = 350;win_height = 100;
initgraph(win_width, win_height); //初始化窗口
for (i = 0;i < 256;i += 5){ //窗口颜色动态变化,由黑变白
setbkcolor(RGB(i, i, i));
cleardevice(); //清屏
Sleep(30); //延时30ms
}
RECT R1 = { r[0][0],r[0][1],r[0][2],r[0][3] };
RECT R2 = { r[1][0],r[1][1],r[1][2],r[1][3] };
RECT R3 = { r[2][0],r[2][1],r[2][2],r[2][3] };
LOGFONT f; //字体样式指针
gettextstyle(&f); //获取字体样式
_tcscpy(f.lfFaceName, _T("宋体")); //修改字体样式为宋体
f.lfQuality = ANTIALIASED_QUALITY; //修改字体样式为平滑
settextstyle(&f); //设置字体样式
settextcolor(BLACK); //设置字体黑色
drawtext("输入", &R1, DT_CENTER | DT_VCENTER | DT_SINGLELINE); //在矩形区域R1内输入文字,水平居中,垂直居中,单行显示
drawtext("运行", &R2, DT_CENTER | DT_VCENTER | DT_SINGLELINE); //在矩形区域R2内输入文字,水平居中,垂直居中,单行显示
drawtext("打印", &R3, DT_CENTER | DT_VCENTER | DT_SINGLELINE); //在矩形区域R3内输入文字,水平居中,垂直居中,单行显示
setlinecolor(BLACK); //保存边框黑色
rectangle(r[0][0], r[0][1], r[0][2], r[0][3]);
rectangle(r[1][0], r[1][1], r[1][2], r[1][3]);
rectangle(r[2][0], r[2][1], r[2][2], r[2][3]);
MOUSEMSG m; //鼠标指针
while (true){
m = GetMouseMsg(); //获取一条鼠标消息
switch (m.uMsg){
case WM_MOUSEMOVE:
setrop2(R2_XORPEN);
setlinecolor(LIGHTCYAN); //线条颜色为亮青
setlinestyle(PS_SOLID, 3); //设置画线为实线,10磅
setfillcolor(WHITE); //填充颜色为白色
if (button_judge(m.x, m.y) != 0){
if (event != button_judge(m.x, m.y)){
event = button_judge(m.x, m.y); //记录这一次触发的按钮
fillrectangle(r[event - 1][0], r[event - 1][1], r[event - 1][2], r[event - 1][3]);//有框填充矩形(X1,Y1,X2,Y2)
}
}
else{
if (event != 0){ //上次触发的按钮未被修正为原来的颜色
fillrectangle(r[event - 1][0], r[event - 1][1], r[event - 1][2], r[event - 1][3]);//两次同或为原来颜色
event = 0;
}
}
break;
case WM_LBUTTONDOWN:
switch (button_judge(m.x, m.y)){ //按照按钮判断左键单击后的操作
case 1:
InputBox(s, 30, "请输入n"); //1、输入参数
sscanf(s, "%d", &n);
for (int i = 0;i < n;i++) {
InputBox(s, 30, "请输入n个自然数");
sscanf(s, "%d", &array[i][0]);
}
FlushMouseMsgBuffer(); //单击事件后清空鼠标消息
break;
case 2:
simulation(n,array); //2、运行函数
FlushMouseMsgBuffer(); //单击事件后清空鼠标消息
break;
case 3:
closegraph(); //3、关闭绘图环境
exit(0);
default:
FlushMouseMsgBuffer(); //单击事件后清空鼠标消息
printf("\n打印鼠标坐标:(%d,%d)\n",m.x,m.y); //方便调试时确定区域
break;
}
break;
}
}
return 0;
}
B3_大整数运算拓展:python实现
import math
a = input("a: ")
b = input("b: ")
x = input("x: ")
y = input("y: ")
result = str(int(a) + int(b))
print("a+b= " + result)
result = str(int(a) - int(b))
print("a-b= " + result)
result = str(int(a) * int(b))
print("a*b= " + result)
result = str(int(a) // int(b))
r = str(int(a) % int(b))
print("a/b= " + result + "···" + r)
result = str(math.isqrt(int(x)))
r = str(int(x) - (math.isqrt(int(x))) ^ 2)
print("sqrt(x)= " + result + "···" + r)
result = str(math.pow(int(x), int(y)))
print("pow(x,y)= " + result)
网友评论