ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

字符串的陷阱-记对字符串大小比较的错误理解

2021-10-31 22:05:34  阅读:163  来源: 互联网

标签:return 号码 int 记对 length second 陷阱 字符串 first



本文记录了笔者在做题过程中被字符串坑的(其实就是自己菜,顺便水一篇博客)的一次小经历,希望能够帮助像我一样的小白加深对字符串某个方面的理解。

万恶之源

小明决定申请一个新的QQ号码,系统随机生成了若干个号码供他选择。小明的选号原则是:

  1. 选择所有号码中各位数字之和最大的号码。
  2. 如果有多个号码各位数字之和相同则选择数值最大的号码。
    请你写一个程序帮助小明选择一个QQ号码。

输入说明    
输入数据由两行构成,第一行为一个整数n表示有n个待选号码(0<n<100),第二行有n个正整数,表示各个待选的号码,每个号码长度不超过9位数。每个号码之间用空格分隔,且每个号码都不相同。

输出说明    
输出根据小明的选号原则选出的号码。

输入样例    
5
10000 11111 22222 333 1234

输出样例    
2222

问题描述:

首先这是我的思路是用pair来存储一个号码的各位数字之和以及这个号码它本身,然后用sort对它进行一个排序,取最后一个元素即可。各位可以想想这样做会有什么问题。(提示,题目的第二个要求是数值最大的号码)

这是我写的比较函数(sort本身也是这样比较的)

bool cmp(pair<int, string>a, pair<int, string>b) {
if (a.first != b.first)
return a.first < b.first;
else
return a.second < b.second;
}

原因分析:

看出问题了吗?

如果能一眼看出来,说明你对字典序的概念和string的比较已经了如指掌啦。

在else里,我们比较string使用了小于号,这类似于c语言中的strcmp函数,它的比较方法是从第一个字母开始,依次向后比较每个字符(ascii),一旦出现不一样的就返回一个值(具体可以参考baidu)。

比如98455987和676692496,98455987的字典序更大,但其实数值上它更小。

于是,在string里大于号小于号不一定能反映真实的数值的比较(其实这我之前就知道,但就是没留意到=-=)

解决方案:

留意到了“不一定”吗,其实字典序在某些条件下也可以反映数值大小。

那就是两个字符串长度相同的时候。

因此长度是一个关键的量,这里的号码有长有短,因而不能比较字符串的大小,于是我们就可以想到对于不同长度的字符串,首先比较的应该是他们的长度。长度长,位数多,数值自然更大。

于是我们可以这样改写比较函数

bool cmp(pair<int, string>a, pair<int, string>b) {
if (a.first != b.first)
return a.first < b.first;
else if (a.second.length() != b.second.length())
return a.second.length() < b.second.length();
else
return a.second < b.second;
}

总结

string中的大于小于比较的是字典序,只有在两个字符串(纯数字)长度相同时才能反映真实的数值大小,否则一定要考虑长度。

另附代码

#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
#include <set>
using namespace std;

bool cmp(pair<int, string>a, pair<int, string>b) {
	if (a.first != b.first)
		return a.first < b.first;
	else if (a.second.length() != b.second.length())
		return a.second.length() < b.second.length();
	else
		return a.second < b.second;
}

int main() {
	pair<int, string> s[1000];
	int n;
	cin >> n;

	for (int i = 0; i < n; i++) {
		cin >> s[i].second;
		int sum = 0, ans = 0;
		for (int j = 0; j < s[i].second.length(); j++) {
			sum += (s[i].second[j] - '0');
		}
		s[i].first = sum;
	}
	sort(s, s + n, cmp);
//	for (int i = 0; i < n; i++)
//		cout << s[i].second << endl;
	cout << s[n - 1].second;
	return 0;
}
//对拍用
#include <iostream>
#include <ctime>
using namespace std;

//返回L 到 R之间的整数
int gr(int L, int R) {
	return rand() * rand() % (R - L + 1) + L;
}

int main() {
	//初始化随机种子
	srand(time(0));
	int a, b;
	//生成一组随机数据
	a = gr(1, 100);
	cout << a << endl;
	for (int i = 0; i < a; i++)
		cout << gr(1, 1000000000) << " ";
	return 0;
}

​

标签:return,号码,int,记对,length,second,陷阱,字符串,first
来源: https://www.cnblogs.com/tsrigo/p/15491016.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有