7-5 字符串转换成十进制整数 (15 分)
输入一个以#结束的字符串,本题要求滤去所有的非十六进制字符(不分大小写),组成一个新的表示十六进制数字的字符串,然后将其转换为十进制数后输出。如果在第一个十六进制字符之前存在字符“-”,则代表该数是负数。
输入格式:
输入在一行中给出一个以#结束的非空字符串。
输出格式:
在一行中输出转换后的十进制数。题目保证输出在长整型范围内。
输入样例:
+-P-xf4+-1!#
输出样例:
-3905
前提:测试点有三个 编号分别是 0 1 2
测试点 2 的特征是 长度为 16可见字符 其中第八位是 负号 其余位置均为非法字符的字符串。就是说 整个字符串中只有负号是十六进制判断中的合法字符 ,其余的都不合法!!!!!
模拟输入样例:!!!!!!!!-!!!!!!!#
模拟输出样例:0
我一共写了三种代码 第一种 不经意绕开了 正确我们来看一下第一种绕开法: (C++)
#include <bits/stdc++.h>
using namespace std;
string tmp;
void Input() {
getline(cin, tmp);
char* s = strstr(&(tmp[0]), "#");
*s = 0;
}
bool ISSIX(char x) {
if (x >= 'A' && x <= 'Z') x += 32;
if (x >= '0' && x <= '9') return true;
if (x >= 'a' && x <= 'f')
return true;
return false;
}
int main() {
Input();
bool lock = true; // 锁
int first=-0x3f3f3f3f;
char* t = &(tmp[0]);
string JG = "";
for (int i = 0, j = strlen(t); i < j; i++) {
bool f = ISSIX(t[i]);
if (f != false) {
JG += t[i];
if (lock) {
lock = false;
first = i;
}
}
}
if (strstr(t, "-") - t < first) { // 编号 1
printf("-");
}
long long int ft = strtoll(JG.c_str(), NULL, 16);
printf("%lld", ft);
system("pause");
return 0;
}
我们知道 strstr 找到返回待查找字符串首字母在源字符串的一个地址。找不着返回NULL 。NULL是什么东西 NULL 就是 0
所以 以上 编号 1 处 不会发生意外情况崩溃。最多减出负数。 而在第三个测试点中,first 从头到尾除开头手动赋值以外,均无赋值,我给了 first 一个很小值 。这个判断是正确的!!而转换字符串 JG 我初始化为空串 这也让转换函数strtoll不出错.
但我说一下 这个正确的代码目考虑到 -0 这个情况。所以是不完美的代码。
同时 批评 样例提出人 不严谨 考虑不周的问题!!这个网上一直有人认为第三个是有输入 负号和零的 结果只测出了 负号。
测试方法 文章末尾。
第二个方法: (C 语言) strstr查找标记法 + 及时转换提取法
#include<stdio.h>
#include<string.h>
#include<math.h>
int main() {
char a[1000];
char b[1000] = { 0 };
gets(a);
a[strstr(a, "#") - a] = 0;
for (int i = 0,k=0, j = strlen(a); i < j; ++i) {
if (a[i] >= 'A' && a[i] <= 'Z')
a[i] += 32;
if ((a[i] >= 'a' &&a[i] <= 'f') || (a[i] >= '0' && a[i] <= '9') || (k == 0 && a[i] == '-')) {
b[k++] = a[i];
}
}
long long int f = strtol(b, NULL, 16);
printf("%lld", f);
system("pause");
return 0;
}
第三个方法 太不堪入目了,这是一个学弟问我的,我就不贴了。
现在 我把我是怎么测试出样例的说一下 也就是符号穷举法+范围二分法
符号穷举法:把重要特殊符号出现的位置在一个字符串中找出来。方法有两种
1. 使用for() + 特殊符号 :for 控制一段很大的范围 去找 找到就 while(1); 死循环 这样超时的时候就能命中特殊符号的范围。再逐步缩小。
2.字符串较短时 可以手动 判断 一个一个枚举。
范围二分法:测试样例输入的时候 采用范围二分法
1.输入的时候使用 一个if 把范围逐渐缩小 然后定位准确范围 模板是
if(...) while(0); 超时为 该数字范围 最后越缩越小 直接 就可以确定了
注意 随机大数据是无法测出的 注意
这是我测这道题我测试的时候的界面 分享一下 op 是手动枚举常量 不要看下面只有一个10就说不足以证明字符串特征