2016年机试真题及题解
1.输入学生信息,姓名 成绩(成绩的数目不一定)
输出每个学生的姓名和平均成绩,按不及格课程数从大到小排好序输出,以及不及格课程数超过2的学生。
#include<iostream>  
#include<string>  
#include<algorithm>  
using namespace std;  
struct stu{  
    string name;  
    int score[100];  
    int number;  
    double avg;  
    int unum;  
};  
// 定义学生按不及格科目数量的排序规则   
bool cmp(stu x,stu y){  
    return x.unum>y.unum;  
}   
int main()  
{  
    string str[100];    // 记录原始输入情况  
    int n=0;            // 用于记录学生的数量  
    // 读取原始数据  
    while(getline(cin,str[n++]));  
    n--;  
    // 整理数据  
    stu s[100];  
    for(int i=0;i<n;i++){  
        int j=0;  
        // 提取姓名  
        while(str[i][j]!=' '&&str[i][j]!='\0')  
            s[i].name+=str[i][j++];  
        // 提取成绩  
        int count=0;        // 记录成绩的数量  
        while(str[i][j]!='\0'){  
            int temp=0;     // 存储局部成绩  
            while(str[i][++j]!=' '&&str[i][j]!='\0'){  
                temp=temp*10+(str[i][j]-'0');  
            }  
            s[i].score[count++]=temp;  
        }  
        s[i].number=count;  // 记录每个学生的成绩数量  
    }  
    /*// 测试数据的输入及处理正确性  
    for(int i=0;i<n;i++){ 
        cout<<s[i].name<<": "; 
        int t=0; 
        while(t<s[i].number) 
            cout<<s[i].score[t++]<<" "; 
        cout<<s[i].number; 
        cout<<endl; 
    }*/  
    // 计算学生的平均成绩及不及格科目数量   
    for(int i=0;i<n;i++){  
        int t=0,    // 科目游标   
        sum=0,      // 局部总成绩   
        u=0;        // 不及格科目数量   
        while(t<s[i].number){  
            if(s[i].score[t]<60)  
                u++;   
            sum+=s[i].score[t++];  
        }  
        s[i].avg=sum/(s[i].number*1.0);  
        s[i].unum=u;   
    }  
    // 按照不及格成成数量从大到小排序  
    sort(s,s+n,cmp);   
    // 按照不及格成绩数量从大到小输出学生信息   
    for(int i=0;i<n;i++){  
        cout<<s[i].name<<": "<<s[i].avg<<endl;  
    }  
    // 输出不及格成绩超过两门的学生姓名   
    cout<<"不及格成绩超过两门的学生姓名为:"<<endl;  
    bool f=true;        // 用于记录无不及格成绩超过两门的学生的情况   
    for(int i=0;i<n;i++){  
        if(s[i].unum>2){  
            f=false;  
            cout<<s[i].name<<" ";  
        }         
    }  
    if(f)  
        cout<<"无不及格成绩超过两门的学生!";   
    cout<<endl;  
    return 0;  
}  
2.输入字符串,输出字符串中包含的数字,比如2.3ABC0-2.3  输出 2.3 0 -2.3。
注意一些特殊的情况如+004.500值为+4.5。
#include<iostream>  
#include<string>  
using namespace std;  
void f(int &op,string &temp,int &t){  
    if(temp==""){  
        if(t==1)  
            cout<<0<<" ";  
        op=0;  
        t=0;  
        return;  
    }  
    // 之前有有效数字  
    if(op==1){  
        cout<<"+"<<temp<<" ";  
    }  
    else if(op==-1){  
        cout<<"-"<<temp<<" ";  
    }  
    else  
        cout<<temp<<" ";  
    temp="";  
    op=0;  
    t=0;  
}  
int main(){  
    string str[100];  
    int n=0,k=0;  
    while(getline(cin,str[n++]));  
    n--;  
    while(k<n){  
        int i=0;            // 字符串游标  
        int op=0;           // 存储运算符  
        string temp="";     // 存储临时数值  
        string zero="";     // 存储连续的0  
        int flag=0;         // 记录是否是小数部分  
        int t=0;            // 记录是否有全0的特殊情况  
        while(str[k][i]!='\0'){  
            // 如果不是数字元素,直接忽略。  
            if((str[k][i]>='0'&&str[k][i]<='9')||str[k][i]=='+'||str[k][i]=='-'||str[k][i]=='.'){  
                /* 
                * 第一部分处理数字中的特殊符号。 
                */  
                if(str[k][i]=='+'){  
                    // 输出之前的数值  
                    f(op,temp,t);  
                    flag=0;  
                    zero="";  
                    op=1;  
                }  
                else if(str[k][i]=='-'){  
                    // 输出之前的数值  
                    f(op,temp,t);  
                    flag=0;  
                    zero="";  
                    op=-1;  
                }  
                else if(str[k][i]=='.'){  
                    // 处理+.123的特殊情况  
                    if(temp=="")  
                        op=0;  
                    // 有多余的小数点  
                    if(flag==1){  
                        f(op,temp,t);  
                        flag=0;  
                        zero="";  
                    }  
                    // 有效的小数点  
                    if(temp!=""){  
                        // 标记一下,之后到达了小数部分。小数点不知道是否有效,先暂存。  
                        flag=1;  
                    }  
                    if(temp==""&&t==1){  
                        temp+='0';  
                        flag=1;  
                    }  
                }  
                /* 
                * 第二部分处理纯数字。 
                */  
                else{  
                    // 首部的无效0  
                    if(temp==""&&str[k][i]=='0')  
                        t=1;  
                    // 小数点之后  
                    else if(flag){  
                        // 小数部分的0,不知道是否有效,先暂存  
                        if(str[k][i]=='0'){  
                            zero+='0';  
                        }  
                        // 小数点之后第一位非零数  
                        else if(flag==1){  
                            // 把之前暂存的小数点,0都加上  
                            temp+='.';  
                            temp+=zero;  
                            zero="";  
                            temp+=str[k][i];  
                            flag++;  
                        }  
                        // 小数点之后多位  
                        else{  
                            temp+=zero;  
                            zero="";  
                            temp+=str[k][i];  
                        }  
                    }  
                    // 整数部分  
                    else{  
                        temp+=str[k][i];  
                    }  
                }  
            }  
            // 非字符忽略,并输出其前面的数字  
            else{  
                f(op,temp,t);  
                flag=0;  
                zero="";  
            }  
            // 向后检索  
            i++;  
        }  
        // 输出最后一个数  
        f(op,temp,t);  
        // 处理下一个字符串  
        k++;  
        cout<<endl;  
    }  
    return 0;  
}  
2017年机试真题及题解
1.身份证号的校验
身份证号码共18位,最后一位是校验位
A[18] : aaaaaabbbbbbbbccc d
校验的规则是如下
前十七位的权值分别是:W[17]:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
x=(A[0]*W[0]+A[1]*W[1]+A[2]*W[2]+...+A[16]*W[16]) mod 11
x和校验位y的对应规则对应如下:
x:0 1 2 3 4 5 6 7 8 9 10
y:1 0 x 9 8 7 6 5 4 3 2
若y等于d则身份证号码正确
输出格式:aaaaaabbbbbbbbcccd 正确
若y不等于d则身份证号码不正确
输出格式:应为:aaaaaabbbbbbbbcccy
测试用例:拿自己身份证实验一下就知道了
#include<iostream>  
#include<string>  
using namespace std;  
int main()  
{  
    int x=0;  
    char y;  
    // 前十七位的权值数组   
    int weight[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};  
    // 转化表   
    char tran[17]={'1','0','x','9','8','7','6','5','4','3','2'};  
    string data;    // 接收输入数据  
    cin>>data;  
    for(int i=0;i<17;i++)  
         x=(x+((data[i]-'0')*weight[i]))%11;  
    y=tran[x];  
    // 校验位正确   
    if(y==data[17])  
        cout<<data<<"正确"<<endl;  
    // 校验位错误   
    else{  
        cout<<"应为:";  
        for(int i=0;i<17;i++)  
            cout<<data[i];  
        cout<<y<<endl;   
    }  
    return 0;  
}  
2.二分查找
-36 -25 0 12 14 29 35 47 76 100(具体数字不一样,但是就是这个类型)
对上述十个数进行二分查找
测试用例:
请输入要查找的数据:14
14是第5个数,查找次数为1
请输入要查找的数据:-25
-25是第2个数,查找次数为2
请输入要查找的数据:121
查找失败
#include<iostream>  
using namespace std;  
int main()  
{  
    int find;  
    int data[10]={-36,-25,0,12,14,29,35,47,76,100};  
    cout<<"请输入要查找的数据:";  
    while(cin>>find){  
        int low=0,high=9;  
        int number=-1,times=0;  
        while(low<=high){  
            times++;  
            int mid=(low+high)/2;  
            if(data[mid]==find){  
                number=mid+1;  
                break;  
            }  
            else if(data[mid]<find){  
                low=mid+1;  
            }  
            else{  
                high=mid-1;  
            }     
        }  
        if(number!=-1)  
            cout<<find<<"是第"<<number<<"个数,查找次数为"<<times<<endl;  
        else  
            cout<<"查找失败"<<endl;  
        cout<<endl;  
        cout<<"请输入要查找的数据:";  
    }   
    return 0;  
}  
3.建立一个学生信息系统,输入学生信息,输出有挂科同学的信息,再按照平均成绩从高到低排序输出
输入:
5
zhaoyi 70 80 90 240
qianer 65 32 77 174
sunsan 100 55 68 223
lisi 86 77 90 253
wangwu 100 59 66 225
输出:
*[qianer] 65 32 77
*[sunsan] 100 55 68
*[wangwu] 100 59 66
lisi 86 77 90
zhaoyi 70 80 90
wangwu 100 59 66
sunsan 100 55 68
qianer 65 32 77
#include<iostream>  
#include<string>  
#include<algorithm>  
using namespace std;  
struct stu{  
    string name;  
    int score[3];  
    int sum;            // 总成绩  
    double avg;         // 平均成绩  
    bool flag;          // 是否挂科  
};  
bool cmp(stu x,stu y){  
    return x.avg>y.avg;  
}  
int main()  
{  
    int n;      // 学生数量  
    stu s[100];  
    cin>>n;  
    for(int i=0;i<n;i++){  
        cin>>s[i].name;  
        cin>>s[i].score[0]>>s[i].score[1]>>s[i].score[2]>>s[i].sum;  
        if(s[i].score[0]<60||s[i].score[1]<60||s[i].score[2]<60)  
            s[i].flag=true;  
        else  
            s[i].flag=false;  
        s[i].avg=s[i].sum/3.0;  
    }  
    // 输出有挂科的同学  
    for(i=0;i<n;i++){  
        if(s[i].flag)  
            cout<<"*["<<s[i].name<<"]"<<" "<<s[i].score[0]<<" "<<s[i].score[1]<<" "<<s[i].score[2]<<endl;  
    }  
    cout<<endl;  
    // 按平均成绩从高到低输出  
    sort(s,s+n,cmp);  
    for(i=0;i<n;i++){  
        cout<<s[i].name<<" "<<s[i].score[0]<<" "<<s[i].score[1]<<" "<<s[i].score[2]<<endl;  
    } 
    return 0;  
}  

        





            
            
            










