Domanda

Sto cercando di scrivere un programma che riceve l'input di - esadecimali, ottali e decimali -, li memorizza in variabili intere, e li emette insieme con la loro conversione in formato decimale. Ad esempio:

Ingressi utente: 0x43, 0123, 65

uscite del programma:

0x43 hexadecimal converts to 67 decimal
0123 octal converts to 83 decimal
65 decimal converts to 65 decimal

Quindi, ovviamente, ho bisogno di un modo di interpretare i numeri, ma non sono sicuro di come fare per farlo. Ho provato vari metodi, come la loro lettura in funzione e la loro conversione in una stringa, e viceversa (vedi qui per esempi di codice), ma interpretando i numeri richiede sempre conversione in un formato che trashes l'ingresso originale.

L'unica cosa che mi viene in mente sta sovraccaricando un operatore >> che legge un carattere alla volta e se si vede 0x o 0 all'inizio dell'ingresso allora memorizza l'intero di ingresso in una stringa prima che viene letto in un int. Poi il programma avrebbe in qualche modo necessario determinare il manipolatore destra durante l'uscita.

Non è sicuro se c'è un modo più semplice per fare questo, ogni aiuto è apprezzato.

Modifica:. Questo è stato risolto, ma ho deciso di pubblicare il codice in se qualcuno è interessato

#include "std_lib_facilities.h"

void number_sys(string num, string& s)
{
  if(num[0] == '0' && (num[1] != 'x' && num[1] != 'X')) s = "octal";
  else if(num[0] == '0' && (num[1] == 'x' || num[1] == 'X')) s = "hexadecimal";
  else s = "decimal";
}

int main()
{
    cout << "Input numbers in hex, dec, or oct. Use 0xx to cancel.\n";
    string a;

    while(cin >> a){
    if(a == "0xx")break;
    string atype;
    number_sys(a, atype);

    int anum = strtol(a.c_str(), NULL, 0);

    cout << a << setw(20-a.length()) << atype << setw(20) << "converts to" << setw(10)
         << anum << setw(10) << "decimal\n";
                 }

    keep_window_open();
}
È stato utile?

Soluzione

Date un'occhiata alla funzione strtol.

char * args[3] = {"0x43", "0123", "65"};
for (int i = 0; i < 3; ++i) {
  long int value = strtol(args[i], NULL, 0);
  printf("%s converts to %d decimal\n", args[i], value);
}

Uscite:

0x43 converts to 67 decimal
0123 converts to 83 decimal
65 converts to 65 decimal

Altri suggerimenti

Si può sempre conservarlo come una stringa per iniziare, e guardare i primi due caratteri per vedere se sono 0x:

std::string num;
std::cin >> num;

if (num[0] == '0' && num[1] == 'x')
{ 
  //handle
}

Non sono sicuro se c'è un modo C ++ di fare questo, ma se non ti dispiace un po 'di C-ishness, è possibile leggere la cosa in un array char e usare qualcosa come sscanf(buffer, "%i", &output). Il %i interpreta l'input come esadecimale, ottale o decimale a seconda del suo formato, proprio come si descrive.

Edit: Ah, non sapevo che strtol potrebbe anche farlo. ignorarmi.

Se si desidera conservare le informazioni di base (hex / ott / dicembre), è necessario memorizzare le informazioni separatamente dal valore intero in sé, e vi richiederà di analizzare almeno il primo paio di caratteri dell'ingresso stringa (sscanf (), strtol (), ecc, non sarà conservare tali informazioni per voi).

Si potrebbe rotolare il proprio mini-parser che salva la base di ingresso e fa la conversione (codice fuori dalla parte superiore della mia testa, non testata):

char inputStr[MAX_INPUT_LENGTH+1];
char *p;
int result = 0;
char values[128];

/**
 * This enumeration serves double duty; it keeps track of what
 * base the input was entered in, and it controls the state machine 
 * used to parse the input; from a didactic POV, this is probably bad form
 */
enum {
  eStart, 
  eHexOrOctal, 
  eOctal, 
  eDecimal, 
  eHexadecimal, 
  eError
} eBase = eStart;


/**
 * Use the values array as a table to map character constants to their corresponding 
 * integer values.  This is safer than using an expression like *p - '0', in 
 * that it can work with character encodings where digits are not consecutive.
 * Yes, this wastes a little space, but the convenience makes
 * up for it IMO.  There are probably better ways to do this.
 */
values['0'] = 0; values['1'] = 1; values['2'] = 2; values['3'] = 3; 
values['4'] = 4; values['5'] = 5; values['6'] = 6; values['7'] = 7; 
values['8'] = 8; values['9'] = 9; values['a'] = 10; values['b'] = 11; 
values['c'] = 12; values['d'] = 13; values['e'] = 14; values['f'] = 15;

/**  
 * Insert code to get input string here 
 */

for (p = inputStr; *p != 0; p++)
{
  /**
   * Cycle through each character in the input string, adjusting the state
   * of the parser as necessary.  Parser starts in the eStart state.
   */
  switch(eBase)
  {
    /**
     * Start state -- we haven't parsed any characters yet
     */
    case eStart:
      if (*p == '0') eBase = eHexOrOctal; // leading 0 means either hex or octal
      else if (isdigit(*p))
      {
        eBase = eDecimal;    // leading non-0 digit means decimal
        result = values[*p];  
      }                    
      else eBase = eError;    // no other character may start an integer constant
      break;
    /**
     * HexOrOctal -- we've read a leading 0, which could start either a hex or
     * octal constant; we need to read the second character to make a determination
     */
    case eHexOrOctal:      
      if (tolower(*p) == 'x')  base = eHexadecimal;
      else if (isdigit(*p) && *p != '8' && *p != '9')
      {
        base = eOctal;   
        result = values[*p];
      }
      else eBase = eError;
      break;
    /**
     * Octal -- we are parsing an octal constant
     */
    case eOctal:
      if (isdigit(*p) && *p != '8' && *p != '9')
      {
        result *= 8;
        result += values[*p];
      }
      else eBase = eError;
      break;
    /**
     * Decimal -- we are parsing a decimal constant
     */
    case eDecimal:
      if (isdigit(*p))
      {
        result *= 10;
        result += values[*p];
      }
      else eBase = eError;
      break;
    /**
     * Hexadecimal -- we are parsing a hex constant
     */
    case eHexadecimal:
      if (isxdigit(*p))
      {
        result *= 16;
        result += values[tolower(*p)];
      }
      else eBase = eError;
      break;
    /**
     * String is not a properly formatted integer constant in 
     * any base; once we fall into the error state, we stay there.
     */
    case eError:
    default:
      break;
  }
}
if (eBase != eError)
{
  printf("input: %s ", inputStr); fflush(stdout);
  switch(eBase)
  {
    case eOctal: printf("octal "); break;
    case eHexadecimal: printf("hexadecimal "); break
    default: break;
  }
  fflush(stdout);
  printf("converts to %d decimal\n", result);
}
else
{
  /** Print a suitable error message here */
}

Se letteralmente sono di utilizzare una variabile singolo intero per la conservazione di tutte le informazioni di cui avete bisogno per poter visualizzare l'output finale, quindi è necessario utilizzare parte della variabile intera per la memorizzazione della base originale che l'ingresso era in. Altrimenti non è recuperabile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top