1. 程式人生 > >7-5 字串轉換成十進位制整數 (15 分) 測試點 2 測試

7-5 字串轉換成十進位制整數 (15 分) 測試點 2 測試

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就說不足以證明字串特徵