十六進製制轉八進位制的快捷方法 巧用格式化輸入輸出

2021-09-19 21:04:03 字數 2896 閱讀 3102

最近刷題的時候遇到乙個基礎題,就是將16進製制數轉為8進製數。咋一看極其簡單,用二進位製做中介即可,簡單規劃了一下就開始動手了。

問題描述

給定n個十六進製制正整數,輸出它們對應的八進位制數。

輸入格式

輸入的第一行為乙個正整數n (1<=n<=10)。

接下來n行,每行乙個由0~9、大寫字母a~f組成的字串,表示要轉換的十六進製制正整數,每個十六進製制數長度不超過100000。

輸出格式

輸出n行,每行為輸入對應的八進位制正整數。

因為乙個十六進製制數為4個二進位制數組成,而乙個八進位制數則由三個二進位制數組成,所以二進位制就成了鏈結八進位制與十六進製制的橋梁。又因為輸入資料的規模較為龐大,所以我們得申請大量的記憶體空間。

我們需要申請的記憶體空間主要分為三部分:儲存輸入的n個陣列,存放中間值的二進位制陣列,以及存放轉換好的八進位制的陣列。由於題目要求輸出必須在全部輸入後,所以我們有這樣一條流程:

我們知道,在格式化輸入輸出函式中,請求列印變數的指令取決於變數的型別,即轉換說明符指定了如何把資料轉換成可顯示的形式。除了我們常用的%d %f %c之外,還有一些特定的進製數計數法,如:

%i:有符號十進位制數; %u:無符號十進位制整數; %o:無符號八進位制整數; %x:使用0f的無符號十六進製制整數; %x: 使用0f的無符號十六進製制整數。

所以,在輸入的時候以十六進製制輸入,輸出時以八進位制輸出,就完成了這個程式的基本框架。

/*

用printf

的格式化進行

16進製制與

8進製的轉換 */

#include 

intmain (void)  

輸入十六進製制 'abc'

十進位制為a*16^2+b*16^1+c*16^0 = 2748,二進位制為1010 1011 1100,轉換為八進位制為5274,正確。

有了借助於轉換說明符的方法也不行,因為在<=100000的輸出條件下,哪怕是long long long ….也得溢位。所以不能直接就把輸出scanf()到變數裡。我們在這兒借助乙個陣列(字串),把所有的輸入都存起來,再把輸入流stdin匯入到scanf()裡。這裡我們借助了sscanf()函式。

int sscanf( string str, string fmt, mixed var1, mixed var2 ... );

從乙個字串中讀進與指定格式相符的資料

對於一組長度恐怖的資料進行操作,分解是必須要做的。所以,一次讀取多少個資料,又該怎麼讀,就成了下乙個要思考的問題。

在傳統的解法,也即將二進位製作為中介的解法中,對十六進製制的操作是從最後一位開始的,因此對於十六進製制'abcd',把它分成兩部分放入scanf()中,與一次讀入的結果是不同的。所以對於陣列,從低位到高位是可行的方法。

又因為三位十六進製制,即12個bit,恰好可以轉化為4個八進位制,所以一次讀取的數量應該為3的倍數。具體的數目也得依據讀入該資料的記憶體大小來定,也即示例**中'x'的型別。太大會溢位,太小又不高效。

由此可以看出,當一次讀入9個f時,對應的十進位制數超過了687億,遠遠超過了long long 可以表示的範圍,所以,一次讀取六個字元就成了最好的方案。

如果是從後往前讀取十六進製制字元的話,那麼讀取到的字元就是反過來的。而輸出是要求正序,所以這樣的話就要求把處理後的結果儲存起來,再輸出。但是再次申請記憶體空間是沒必要的,所以我們得做一些處理,讓程式正序處理字串。

整個待處理的十六進製制字串可分為兩部分,一部分是一次六個字元被統一讀入的部分,另一部分是沒有湊夠六個的部分。如果字元長度對六取模的值為零,那麼正序後者倒敘的結果都一樣。所以先對開頭的一部分單獨處理,再用乙個迴圈來處理後面的字串,就成了最直接的方法。

intx = 0;  

j = arr_len[i] % 6;  

if(j != 0)  

}for(j ;j

//接下來迴圈處理的部分

變數j是規則部分開始的下標,所以乙個迴圈可以搞定剩下的部分。

for(j ;j

printf("\n");  

上面的模組以及把整個程式交代的差不多了,不過還是有一處細節要交代一下。我們來看一組測試用例:

理論上,六位十六進製制數可以轉化成八個八進位制數。但在實際操作中,有時讀取到的十六進製制數太小,以至於不到八位。如果讀取的數是單獨的十六進製制數那當然沒問題,但是如果讀取的是乙個長十六進製制的一部分,那就出錯了。所以在輸出時得把前導零帶上。但是十六進製制最開始的幾個字元的前導零得去掉,所以要進行一次判斷。

for(j ;j

我在csdn上找了乙份該題的另乙份原始碼,這是借助二進位制的乙個版本。提交後,各情況如下:

新提交的為二進位制的版本。可以看到二進位制的版本用空間換取了時間,時間消耗極少。而sscanf()版本由於呼叫了標準庫,所以消耗時間較多。

十六進製制轉八進位制

時間限制 1.0s 記憶體限制 512.0mb 問題描述 給定n個十六進製制正整數,輸出它們對應的八進位制數。輸入格式 輸入的第一行為乙個正整數n 1 n 10 接下來n行,每行乙個由0 9 大寫字母a f組成的字串,表示要轉換的十六進製制正整數,每個十六進製制數長度不超過100000。輸出格式 輸...

十六進製制轉八進位制

問題描述 給定n 個十六進製制正整數,輸出它們對應的八進位制數。輸入格式 輸入的第一行為乙個正整數n 1 n 10 接下來 n行,每行乙個由 0 9 大寫字母 a f組成的字串,表示要轉換的十六進製制正整數,每個十六進製制數長度不超過 100000 輸出格式 輸出n 行,每行為輸入對應的八進位制正整...

十六進製制轉八進位制

資料很大 因此直接考慮用字串陣列來儲存十六進製制和八進位制 先根據 四位一體 的方法將十六進製制轉化為二進位制,而後根據 三位一體 將二進位制轉化為八進位制。include includeint main else if a i 1 else if a i 2 else if a i 3 else ...