2011-07-08 85 views
2

我最近一直在閱讀一本書的練習。其任務是創建一個程序,以二進制,八進制和十六進制等值的形式打印1-256之間的所有數字。我們只應該使用我們在本書中學到的方法,這意味着只使用for,while和do..while循環,if和else if語句,將整數轉換爲ASCII等價物和一些更基本的東西(例如cmath和了iomanip)。優化轉換算法

因此,經過一番工作,這是我的結果。然而,這是混亂和不雅,並混淆。有沒有人有任何建議來提高代碼效率(或優雅...:P)和性能?

#include <iostream> 
#include <iomanip> 
#include <cmath> 
using namespace std; 

int main() 
{ 
int decimalValue, binaryValue, octalValue, hexadecimalValue, numberOfDigits; 
cout << "Decimal\t\tBinary\t\tOctal\t\tHexadecimal\n\n"; 
for (int i = 1; i <= 256; i++) 
{ 
    binaryValue = 0; 
    octalValue = 0; 
    hexadecimalValue = 0; 
    if (i != 0) 
    { 
    int x, j, e, c, r = i, tempBinary, powOfTwo, tempOctal, tempDecimal; 
    for (j = 0; j <=8; j++) //Starts to convert to binary equivalent 
    { 
     x = pow(2.0, j); 
     if (x == i) 
     { 
       powOfTwo = 1; 
       binaryValue = pow(10.0, j); 
       break; 
     } 
     else if (x > i) 
     { 
       powOfTwo = 0; 
       x /= 2; 
       break; 
     } 
    } 
    if (powOfTwo == 0) 
    { 
    for (int k = j-1; k >= 0; k--) 
    { 
     if ((r-x)>=0) 
     { 
      r -= x; 
      tempBinary = pow(10.0, k); 
      x /= 2; 
     } 
     else if ((r-x)<0) 
     { 
      tempBinary = 0; 
      x /= 2; 
     } 
     binaryValue += tempBinary; 
    } 
    } //Finished converting 
    int counter = ceil(log10(binaryValue+1)); //Starts on octal equivalent 
    int iter; 
    if (counter%3 == 0) 
    { 
     iter = counter/3; 
    } 
    else if (counter%3 != 0) 
    { 
     iter = (counter/3)+1; 
    } 
    c = binaryValue; 
    for (int h = 0; h < iter; h++) 
    { 
     tempOctal = c%1000; 
     int count = ceil(log10(tempOctal+1)); 
     tempDecimal = 0; 
     for (int counterr = 0; counterr < count; counterr++) 
     { 
      if (tempOctal%10 != 0) 
      { 
       e = pow(2.0, counterr); 
       tempDecimal += e; 
      } 
      tempOctal /= 10; 
     } 
     octalValue += (tempDecimal * pow(10.0, h)); 
     c /= 1000; 
    }//Finished Octal conversion 
    cout << i << "\t\t" << binaryValue << setw(21-counter) << octalValue << "\t\t"; 
    int c1, tempHex, tempDecimal1, e1, powOf; 
    char letter; 
    if (counter%4 == 0)//Hexadecimal equivalent 
    { 
     iter = counter/4; 
    } 
    else if (counter%4 != 0) 
    { 
     iter = (counter/4)+1; 
    } 
    c1 = binaryValue; 
    for (int h = 0, g = iter-1; h < iter; h++, g--) 
    { 
     powOf = g*4; 
     if (h == 0) 
     { 
       tempHex = c1/pow(10.0, powOf); 
     } 
     else if (h > 0) 
     { 
      tempHex = c1/pow(10.0, powOf); 
      tempHex %= 10000; 
     } 
     int count = ceil(log10(tempHex+1)); 
     tempDecimal1 = 0; 
     for (int counterr = 0; counterr < count; counterr++) 
     { 
      if (tempHex%10 != 0) 
      { 
       e1 = pow(2.0, counterr); 
       tempDecimal1 += e1; 
      } 
      tempHex /= 10; 
     } 
     if (tempDecimal1 <= 9) 
     { 
     cout << tempDecimal1; 
     } 
     else if (tempDecimal1 > 9) 
     { 
     cout << char(tempDecimal1+55); //ASCII's numerical value for A is 65. Since 10-15 are supposed to be letters you just add 55 
     } 
    } 
    cout << endl; 
    } 
} 
system("pause"); 
return 0; 
} 

任何改進建議將不勝感激。

+1

我假設你不能使用printf? – Coeffect

+0

@fvu在這個特殊情況下,變量j被用於循環以外的其他地方,因此聲明在for頭之外。 –

回答

5

分解每個輸出類型的函數,然後遍歷整數列表並依次調用每個不同格式的函數來輸出每個輸出類型的函數。

for (int i = 1; i <= 256; ++i) 
{ 
    printBin(i); 
    printHex(i); 
    printOct(i); 
} 

根本的問題是,這個功能需要很長重構更加模塊化。想象一下,你正在編寫別人使用的代碼。他們怎麼能打電話給main?他們如何理解代碼的每一部分在做什麼?他們不能。如果您將每個具有特定作業的代碼段作爲函數進行調用,那麼更容易理解其意圖,並在稍後重用。

+0

至少有一位瞭解Emile的人要求提供代碼建議,而不是微不足道的「使用內置函數」。 – vrince

+2

+ 1-1 = 0:好的建議模塊化,但是這個C++,而不是Java:沒有理由讓所有的靜態方法都成爲一個更好的解決方案... – 6502

+0

@ 6502 - 這是更多的C#或Java成語 - 謝謝 –

1

我的回答可能是面頰有點舌頭,但

printf ("%u %o %x \n", value, value, value); 

會做的八進制和十六進制版本的伎倆;)

對於二進制版本,我會使用初始化的標誌到256,並用AND運算符與您的數字進行比較。如果爲true,則打印1,否則打印0.然後將旗子除以2。重複,直到標誌爲1

僞從整數到二進制

int flag = 256 
do 
{ 
if (flag && value) 
print "1" 
else 
print "0" 
flag = flag >> 1 // aka divide by two, if my memory serves well 
} while flag > 1 

轉換爲八進制和十六進制值,我有點生疏,但環顧四周應引導你,你可以適應樣本

6

你已經覆蓋了'iomanip',它推斷你已經覆蓋'iostream'。

如果是這樣的話,看看下面:

#include <iostream> 
#include <iomanip> 
using namespace std; 

int x = 250; 
cout << dec << x << " " 
    << oct << x << " " 
    << hex << x << "\n" 
    << x << "\n";  // This will still be in HEX 
+1

我的C++絕對是生鏽的,我忘記了關於cout和它的各種格式化選項 – samy

+1

請注意,操縱器通常具有持久效果('setw'是一種特殊情況)。所以當循環重複執行時,上面的內容可能不會按照您的想法執行。 ;-)當然,在你修正了這個例子之後,這個評論對其他人來說似乎有點奇怪,所以,如果讀者看起來很奇怪,那麼代碼可能已經修復了。乾杯, –

+0

這將是最簡單的方法。但是,任務要求我們不要使用內置的函數,並且要讓我們自己的算法將每個值轉換爲1-256。不管怎麼說,還是要謝謝你! –

0

爲什麼讓任何困難比它確實是。

for (int i = 1; i <= 256; ++i) 
{ 
    std::cout << std::dec << i << "\t" << std::oct << i << "\t" << std::hex << i << std::endl; 
} 
+0

正如我之前對乍得所說的:任務不是使用內置函數,而是創建和設計自己的算法,將1-256之間的所有數字轉換爲二進制,八進制和十六進制。另一方面,如果情況並非如此,我肯定會使用你的方法! :d –

0

試試這個

using namespace std; 

template <typename T> 
inline void ShiftMask(T& mask) { 
    mask = (mask >> 1) & ~mask; 
} 

template < typename T > 
std::ostream& bin(T& value, std::ostream &o) 
{ 
    T mask = 1 << (sizeof(T) * 8 - 1); 

    while (!(value & mask) && (mask != 0)) ShiftMask(mask); 

    while (mask) { 
     o << (value & mask ? '1' : '0'); 
     ShiftMask(mask); 
    } 

    return o; 
} 

int main(void) { 
    for (int i=0; i<256;i++) { 
    bin(a, std::cout); 
    cout << " " << oct << i; 
    cout << " " << dec << i; 
    cout << " " << hex << i; 
    cout << "" 
    } 
} 
0

也許這樣的事情?

#include "stdio.h" 
int main(){ 
    char Chars[16]= {48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70}; 
    for(int n = 1;n != 256; n++) 
    { 
     {//decimal 
      printf("%i\t", n); 
     } 
     {//Hexadecimal 
      char L, R; 
      R = (n & 0x0F) >> 0; 
      L = (n & 0xF0) >> 4; 
      printf("%c%c\t", Chars[L], Chars[R]); 
     } 
     {//Octal 
      char L, M, R; 
      R = (n & 0x07) >> 0; 
      M = (n & 0x38) >> 3; 
      L = (n & 0xC0) >> 6; 
      printf("%c%c%c\t", Chars[L], Chars[M], Chars[R]); 
     } 
     {//Binary 
      char B0, B1, B2, B3, B4, B5, B6, B7; 
      B0 = (n & 0x01) >> 0; 
      B1 = (n & 0x02) >> 1; 
      B2 = (n & 0x04) >> 2; 
      B3 = (n & 0x08) >> 3; 
      B4 = (n & 0x10) >> 4; 
      B5 = (n & 0x20) >> 5; 
      B6 = (n & 0x40) >> 6; 
      B7 = (n & 0x80) >> 7; 
      printf("%c%c%c%c%c%c%c%c\n", Chars[B0], Chars[B1], Chars[B2], Chars[B3], Chars[B4], Chars[B5], Chars[B6], Chars[B7]); 
     } 
     printf("256\t100\t400\t100000000\n"); 
    } 
} 
2

你有沒有考慮過編寫一個可以與任何基地協同工作的通用函數?

將非負數轉換爲通用基數很簡單...你只需要計算number % base,你會得到最顯著的數字,然後通過base劃分number和重複獲得其他數字...

std::string converted_number; 
do { 
    int digit = number % base; 
    converted_number = digits[digit] + converted_number; 
    number = number/base; 
} while (number != 0); 

一旦你有一個通用的轉換功能,然後幫你解決問題容易.. 。只需用base = 2,8和16調用它就可以得到你需要的字符串結果。