目录
先上代码
#include<iostream>
#include<string>
#include<vector>
using namespace std;
char c[11]={'1','0','X','9','8','7','6','5','4','3','2'};
int b[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
int check_pass (string a);
int main(){
int N;
cin>>N;
vector<string> a(N);
for(int i=0;i<N;i++){
cin>>a[i];
}
int j=0;
int recored_=0;
for(int i=0;i<N;i++){
j=check_pass(a[i]);
if(j==-1){
cout<<a[i]<<endl;
recored_=-1;
}
}
if(recored_==0){
cout<<"All passed";
}
}
int check_pass (string a){
int sum=0;
int z=0;
for(int i=0;i<17;i++){
sum+=(a[i]-'0')*b[i];
}
z=sum%11;
if(c[z]==a[17]){
return 1;
}
else{
return -1;
}
}
我遇到的问题
首先,对题目的理解
首先是没有意识到身份证号码是18位的,其次对加权求和的理解不准确,认为是“加”权,实际上是乘,这直接导致我的代码错误,只过一个测试点。加权求和是指对一组数字,按照一定的权重分配,将每个数字乘以对应的权重,然后将所有乘积相加得到一个结果。
其次,是对代码的优化问题
动态数组用vector或者new要比直接定义string a[N]要好,
最后,返回值
用bool类型比int更好,为了避免将 0 或 1 作为返回值的误判,函数 check_pass 的返回值最好定义为 bool 类型。同时,将 recored_ 的数据类型修改为 bool 类型。因为bool类型只有true和false两个值,没有其他的可能性,所以不会出现误判。
最重要的是,直观!!!! 不管谁看,一眼就知道,直观!
可以降低错误的概率,你想,你代码量少还行,但一旦一多,就容易出问题,看花眼。
而且别人看你代码,也晕。害己害人。
多种解法
1.换种数据结构
用结构体进行封装,当然,也可以用类
#include <iostream>
#include <string>
using namespace std;
// 定义结构体,用于存储身份证号码
struct ID {
string id;
bool is_valid; // 是否合法
};
// 验证身份
2.back()函数
#include <iostream>
#include <string>
using namespace std;
bool check_pass(const string& a) {
static int b[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
static char c[] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
int sum = 0;
for (size_t i = 0; i < 17; ++i)
sum += (a[i] - '0') * b[i];
int z = sum % 11;
if(c[z]==a.back()){
return true;
}
else{
return false;
}
}
int main() {
int n;
cin >> n;
string s;
bool all_passed = true;
for (int i = 0; i < n; ++i) {
cin >> s;
if (!check_pass(s)) {
cout << s << endl;
all_passed = false;
}
}
if (all_passed) {
cout << "All passed" << endl;
}
return 0;
}
3.类
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class IDNumber {
public:
IDNumber(const string &s) : id_(s) {}
bool check() const {
static int b[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
static char c[] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
if (id_.size() != 18) return false;
int sum = 0;
for (size_t i = 0; i < 17; ++i)
if (!isdigit(id_[i])) return false;
else sum += (id_[i] - '0') * b[i];
return id_[17] == c[sum % 11];
}
const string &get() const {
return id_;
}
//这是一个C++类的成员函数,函数名为get,返回类型为const string&,并且是一个常量成员函数。常量成员//函数是指在函数内部不能修改对象的成员变量,以保证对象的状态不会被修改。
//这个函数的作用是返回对象的私有成员变量id_的值,并且由于是常量成员函数,所以可以在对象的const函数//中被调用,以保证不会修改对象的状态。
private:
string id_;
};
int main() {
int n;
cin >> n;
vector<IDNumber> ids;
for (int i = 0; i < n; ++i) {
string s;
cin >> s;
ids.emplace_back(s);
//ids.emplace_back(s) 是将字符串 s 添加到 vector<string> ids 的尾部,可以理解为在 ids //中增加一个元素,并将 s 赋值给这个元素。这里使用了 C++11 中的 emplace_back() 函数,它相比 //push_back() 函数的优势在于可以在不产生中间对象的情况下直接将元素添加到容器中,从而提高了效率。
}
bool all_passed = true;
for (const auto &id : ids) {
if (!id.check()) {
cout << id.get() << endl;
all_passed = false;
}
}
if (all_passed) cout << "All passed" << endl;
return 0;
}
在上面的代码中,我们定义了一个名为IDNumber
的类,用于表示身份证号码。在该类的构造函数中,我们接受一个身份证号码字符串并将其存储在私有变量id_
中。我们还为IDNumber
类定义了两个公有函数:check
和get
。
check
函数用于检查身份证号码的校验码是否正确。具体地,我们使用权重分配数组b
对前17位数字进行加权求和,并计算其对11取模的结果z
。然后根据z
的值与预设的校验码字符数组c
的对应关系,比较z
和最后一位校验码字符,判断校验码是否正确。如果校验码正确,check
函数返回true
,否则返回false
。
get
函数用于获取存储在IDNumber
对象中的身份证号码字符串。
在主函数中,我们使用vector<IDNumber>
存储所有输入的身份证号码,并使用for
循环依次检查每个身份证号码的校验码是否正确。如果某个身份证号码的校验码不正确,我们输出该号码并将all_passed
变量设为false
。最后,如果所有身份证号码的校验码都正确,我们输出All passed
。