Don't like ads? PRO users don't see any ads ;-)
Guest

Qt/C++ Converter um dado número para valor por extenso.

By: dthrvr on May 8th, 2012  |  syntax: C++ (with QT extensions)  |  size: 5.43 KB  |  hits: 72  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. // Moldado para C++ com uso da Qt Framework.
  2. //
  3. // Rotina simples que a partir de uma QVariant, converte números com ou sem casas decimais
  4. // para valores por extenso, com ou sem referências à moeda corrente do nosso país (Real)
  5. //
  6. // É uma perfeita gambiarra. Suporta valores até quintilhões de reais.
  7. //
  8. // Exemplo de uso:
  9. //   QString str = valorPorExtenso(pow(2,32));
  10. //        // str = "Quatro Bilhões, Duzentos e Noventa e Quatro Milhões, Novecentos e Sessenta e Sete Mil e Duzentos e Noventa e Seis Reais"
  11. //
  12.  
  13.  
  14.  
  15. // Includes necessários
  16. #include <QObject>
  17. #include <QStringList>
  18. #include <QVariant>
  19. #include <cmath>
  20.  
  21. /**
  22.  * @brief blocoExtenso - Funcao auxiliar para a valorPorExtenso(..)
  23.  * @param valor valor por extenso, limite de 3 numeros, maior que isso, ele trunca
  24.  * @return Retorna string contendo o bloco de 3 numeros por exenso
  25.  */
  26. static QString blocoExtenso(QVariant valor)
  27. {
  28.     QString aux, num;
  29.     QString extenso;
  30.     bool ok = false, round = false;
  31.  
  32.     static QStringList cent = QStringList()
  33.             << "Cento" << "Duzentos" << "Trezentos" << "Quatrocentos"
  34.             << "Quinhentos" << "Seiscentos" << "Setecentos" << "Oitocentos" << "Novecentos";
  35.     static QStringList deze = QStringList()
  36.             << "Dez" << "Vinte" << "Trinta" << "Quarenta" << "Cinquenta"
  37.             << "Sessenta" << "Setenta" << "Oitenta" << "Noventa";
  38.     static QStringList unid = QStringList()
  39.             << "Um" << "Dois" << QObject::tr("Três") << "Quatro" << "Cinco" << "Seis" << "Sete"
  40.             << "Oito" << "Nove" << "Dez" << "Onze" << "Doze" << "Treze" << "Quatorze"
  41.             << "Quinze" << "Dezesseis" << "Dezessete" << "Dezoito" << "Dezenove";
  42.  
  43.     int digito, tam = 2, val = valor.toInt(&ok);
  44.     if(!ok || !val) return QString();
  45.     num = valor.toString().rightJustified(3, '0');
  46.     num.truncate(3);
  47.  
  48.     if(val < 20) {
  49.         aux = unid.at(val-1);
  50.         extenso.prepend(aux);
  51.     }
  52.     else if(val == 100)
  53.         extenso.prepend("Cem");
  54.     else {
  55.         for(int i = 0; i <= tam; i++) {
  56.             digito = num.at(tam-i).digitValue();
  57.             if(!digito) continue;
  58.             round = false;
  59.             switch (i) {
  60.             case 2:
  61.                 aux = cent.at(digito-1); if(num.at(1) == QChar('0') && num.at(2) == QChar('0')) round = true;
  62.                 break;
  63.             case 1:
  64.                 if(num.at(1).digitValue() == 1 && num.at(0).digitValue() > 0) {
  65.                     aux = blocoExtenso(num.mid(1,2)); round = true;
  66.                 }
  67.                 else
  68.                     aux = deze.at(digito-1); if(num.at(0) == QChar('0') && num.at(2) == QChar('0')) round = true;
  69.                 break;
  70.             case 0:
  71.                 if(num.at(1).digitValue() == 1 && num.at(0).digitValue() > 0)
  72.                     aux = "";
  73.                 else
  74.                     aux = unid.at(digito-1); round = true;
  75.                 break;
  76.             }
  77.             (round) ? extenso.prepend(aux) : extenso.prepend(aux+" e ");
  78.         }
  79.     }
  80.     return extenso;
  81. }
  82.  
  83.  
  84. /**
  85.  * @brief valorPorExtenso - Imprime valor financeiro (ou nao) por extenso
  86.  * @param valor Valor a ser convertido
  87.  * @param decimais Decimais do numero na saida, maximo 3 casas
  88.  * @param semMoeda Omitir as palavras 'Reais' e 'Centavos' no valor por extenso
  89.  * @return Valor convertido para extenso.
  90.  */
  91. static QString valorPorExtenso(QVariant valor, int decimais = 2, bool semMoeda = false)
  92. {
  93.     bool ok;
  94.     QString aux, num, frac;
  95.     QString extenso;
  96.  
  97.     double val = valor.toDouble(&ok);
  98.     if(!ok) return "<NUMERO INVALIDO>";
  99.     if(decimais > 3) decimais = 3;
  100.  
  101.     double inteiro, fracao = modf(val, &inteiro);
  102.     fracao *= pow(10, decimais);
  103.     num = QString::number(inteiro, 'f');
  104.     num = num.mid(0, num.indexOf('.'));
  105.     int tam = num.size();
  106.     if(tam % 3) {
  107.         num = num.rightJustified((int)(ceil(tam/3.0) * 3),'0');
  108.         tam = num.size();
  109.     }
  110.  
  111.     frac = QString::number(fracao, 'f');
  112.     frac = frac.mid(0, frac.indexOf('.'));
  113.  
  114.     bool match = false;
  115.     if(val < 100)
  116.         extenso.prepend(blocoExtenso(num)+" ");
  117.     else {
  118.         for(int i = 3; i <= tam; i+=3) {
  119.             aux = blocoExtenso(num.mid(tam-i, 3));
  120.             if(aux.size() == 0)
  121.                 continue;
  122.             switch(i) {
  123.             case 21: aux += " Quinti"; match = true; break;
  124.             case 18: aux += " Quadri"; match = true; break;
  125.             case 15: aux += " Tri"; match = true; break;
  126.             case 12: aux += " Bi"; match = true; break;
  127.             case 9: aux += " Mi"; match = true; break;
  128.             case 6: aux += " Mi"; match = true; break;
  129.             default: aux += " "; break;
  130.             }
  131.             if(match) {
  132.                 if(num.mid(i, tam).indexOf("[1-9]") && i != 6 && num.mid(tam-i, 3).toInt() != 1)
  133.                     extenso.prepend(aux+QObject::tr("lhões, "));
  134.                 else
  135.                     (i == 6) ? extenso.prepend(aux+"l e ") : extenso.prepend(aux+QObject::tr("lhão, "));
  136.                 match = false;
  137.             }
  138.             else
  139.                 extenso.prepend(aux);
  140.         }
  141.     }
  142.     if(!semMoeda)
  143.         (val < 2) ? extenso.append("Real") : extenso.append("Reais");
  144.     if(fracao > 0) {
  145.         extenso += " e "+blocoExtenso(frac);
  146.         if(!semMoeda)
  147.             extenso += " centavos";
  148.     }
  149.     return extenso.replace("  ", " ").replace(" e Reais", " Reais").replace(", Reais"," de Reais");
  150. }