Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - amchacon

#181
Programación C/C++ / Re: Lanzar excepcion
23 Marzo 2014, 19:23 PM
La propia librería te dirá como se procesan los errores. No tiene nada que ver con el lenguaje.
#182
Por cierto es importante distinguir entre lectura en modo texto y lectura binaria.

Lo que estás haciendo ahí es lectura en modo texto, el programa lee las cifras y las interpreta.

Pero también cabe guardar la cifra a "palo seco":
Código (cpp) [Seleccionar]
int b;

ofstream escritura("texto.bin");
escritura.write((char*) &b,sizeof(int));


Si abrimos el archivo con un bloc de notas no veremos nada pero ahí está el número guardado.

Leyendolo sería parecido:
Código (cpp) [Seleccionar]
int b;

ifstream escritura("texto.bin");
escritura.read((char*) &b,sizeof(int));


Este modo de lectura es "más natural" para el programa, los datos suelen ocupar menos espacio y la lectura y escritura es más rápida (ya que no tienen que reinterpretarlo como texto).

¿Cual usar? Pues depende de tus necesidades por supuesto, si quieres que el archivo pueda ser leído por humanos entonces usa los operadores >> y << que has usado antes.

Para ser leído por programas es mejor esta opción.
#183
Serán similares supongo.

Eso si, tienes que tener en cuenta que no son tipos nativos sino emulados. De modo que cualquier operación que hagas sera mas lenta que una que hagas con un int o un long long.
#184
¿Seguro? A mi siempre me lo coge con iostream.
#185
1º ¿No te reconoce el string? Pues sintácticamente está correcto Oo

2º Para leer líneas enteras se usa getline:
Código (cpp) [Seleccionar]
getline(archivo,string);

También se puede leer directamente por read():
http://www.cplusplus.com/reference/istream/istream/read/

Esa es una lectura literal.

3º Escribe las líneas que vas leyendo. Puedes los saltos de línea que creas necesario.
#186
Ah!. Había oido bits xD.

No hay tipos nativos que te permitan eso, tienes que usar una librería de números grandes como BigInteger:
https://mattmccutchen.net/bigint/
#187
Cita de: yoel_alejandro en 23 Marzo 2014, 02:51 AM
Gracias por el token = c !!!

Ahora dos detallitos:

(1) Si podrías hacer el código más portable, que no requiera necesariamente C++11. Yo uso Ubuntu 10.04, de 2010, y g++ no está actualizado a 2011. Tengo problemas con el "auto it", en el otro código tive que cambiar todas las expresiones de ese tipo al tipo "class<T> :: it". Quiero que sea portable porque la idea de ésto es primero usarlo como objeto académico-pedagógico en la Universidad por ejemplo, y no se si todos los estudiantes están actualizado a la última versión del software.
No solo necesitas un compilador que soporte C++11 sino que también tienes que activar ese modo en la compilación (creo que era std=C++11 o algo así).

Lo más fácil esque quites los auto y listo. No hay nada más que use de C++11 en ese código.

Cita de: yoel_alejandro en 23 Marzo 2014, 02:51 AM(2) La invocación de la conversión a número empieza cuando se detecta un carácter entre '0' y '9', no con el signo '+' ó '-'. ¿Eso no hará que por ejemplo al recibir 2 * -3, lo interprete como 2 * 3?
Efective wonder.

Puedes empezar también con un '-', conviertes el número y a falta de operadores asumes una suma.

Por cierto:
Código (cpp) [Seleccionar]
const string operators[N_operators] = {"+", "-", "*", "/", "%", "^"};

Mucho mejor es lo siguiente:
Código (cpp) [Seleccionar]
const char operators[N_operators] = {'+','-','*','/','%','^'};

No me gusta usar strings para cadenas constantes, es un desperdicio de recursos (tanto en espacio como en tiempo).
#188
Programación C/C++ / Re: funciones en c
23 Marzo 2014, 02:34 AM
Ambas opciones son correctas.
#189
Yo no me confiaría tanto del POSIX. Para C son estupendas pero el futuro de C++ va a ser las nuevas clases thread del estandar C++11.

Digo futuro porque son nuevas y aún tienen que madurar un poco. Pero vamos a mí personalmente me parecen de lo mejor que se ha hecho:
Código (cpp) [Seleccionar]

void hilo(int a,int b)
{
    cout<<a<<b<<endl;
}
void otro_hilo(double a,float b,float c)
{
  a += b/c;
  cout<<a<<endl;
}

int main()
{
    thread t1(hilo,1,2); // llamo a la funcion hilo con los argumentos 1 y 2
    thread t2(otro_hilo,3.2,12.5,6.1); // llamo a la funcion otro_hilo con los argumentos 3.2, 12.5 y 6.1
    t1.join();
    t2.join();
}


A ver como haces eso en POSIX sin tirar de casts y de hacerte estructuras cada 2x3 ^^

Y en el tema de argumentos por referencia o llamadas de metodos de objetos ya ni hablamos xD.
#190
La solución es más fácilita de lo que parece:
Código (cpp) [Seleccionar]
/* es un carácter numérico: pasar al posfijo */
if ( c >= '0' && c <= '9' )
{
   cout << "\tes numero: pasado a posfijo" << endl << endl;
   postfix = postfix + " " + c;
   continue;
}


Has detectado un número, bien. Aquí debes leer EL NUMERO ENTERO, un ejemplo sería reutilizar mi función:

Código (cpp) [Seleccionar]
/* es un carácter numérico: pasar al posfijo */
if ( c >= '0' && c <= '9' )
{
   double aux = ConvertirNumero(infix,i);
   cout << "\tes numero: pasado a posfijo" << endl << endl;
   result.push(aux);
   continue;
}


La función ConvertirNumero() te actualiza la posición de tu indice i, asi que no deberías preocuparte por eso. También te lee los decimales.

El código completo sería:

Código (cpp) [Seleccionar]
#include <cstdlib>
#include <iostream>
#include <string>
#include <stack>
#include <cmath>
#include <list>
#include <sstream>
using namespace std;

/* Operadores matematicos */
#define N_operators 6
const string operators[N_operators] = {"+", "-", "*", "/", "%", "^"};
int precedences[N_operators] = {1, 1, 2, 2, 2, 3};

bool is_operator( const string );
int precedence( const string );

/* Mis sugerencias personales a este programa:
*
* - Considerar el cambio del nombre standby por aux_stack, u otro.
* - Incorporar el analizador lexico para expresiones numericas de punto
*   flotante, o que ocupen mas de un caracter.
* - Eliminar la cadena intermedia postfix, pasando directamente los
*   resultados de la pila de operadores extraidos de infix, a una pila
*   de evaluacion.
* - Incorporar operadores unarios, como sin(), cos(), exp(), log(), etc.
* - Detectar errores de sintaxis en la expresion infija.
* - Otros que sean recomendados.
*/

double ConvertirNumero(string &Entrada,int &Index)
{
   list<double> Enteros;
   list<double> Decimales;
   short aux;
   short signo = 1;

   // Nos saltamos los espacios en blanco

   while(Entrada[Index] == ' ')
   {
       Index++;
   }

   if (Entrada[Index] == '-')
   {
       signo = -1;
       Index++;
   }

   /** Ahora debería haber números, de lo contrario tenemos un error **/

   if (Entrada[Index] < '0' || Entrada[Index] > '9')
   {
       stringstream buffer;
       buffer<<"Error de sintaxis, desconocido elemento: '"<<Entrada[Index]<<"' en la posicion: "<<Index+1;
       throw buffer.str().c_str();
   }

   /** Añadimos los enteros **/

   while (Entrada[Index] >= '0' && Entrada[Index] <= '9' && Index < Entrada.size())
   {
       Enteros.push_back(Entrada[Index]-48);
       //cout<<Cosa[i]<<endl;
       Index++;
   }

   /** Si a continuación encontramos un punto o una coma, esque hay numeros a continuacion **/

   if (Entrada[Index] == '.' || Entrada[Index] == ',')
   {
       bool Activado = false;
       Index++;
       while (Entrada[Index] >= '0' && Entrada[Index] <= '9' && Index < Entrada.size())
       {
           Decimales.push_back(Entrada[Index]-48);
           Index++;
           Activado = true;
       }
       if (!Activado)
       {
           throw "Error de sintaxis, se insertó un punto pero no se añadió ningun decimal";
       }
   }
   double Numero = 0; // El valor que devolveremos
   aux = 0;

   /** Recorremos los enteros y lo pasamos a número. Como tenemos las cifras simplemente es sumarlas **/

   for (auto it = Enteros.begin(); it != Enteros.end(); it++)
   {
       Numero += *it*pow(10,Enteros.size()-aux-1);
       aux++;
   }
   aux = 0;

   /** Idem, pero para los decimales **/

   if (!Decimales.empty())
       for (auto it = Decimales.begin(); it != Decimales.end(); it++)
       {
           Numero += *it/(pow(10,(aux))*10);
           aux++;
       }

   Numero *= signo;
   Index--;
   return Numero;
}

int main()
{
       string infix, postfix, token;
       stack <string> standby;
       stack <double> result;
       int i;
       char c;
       double A, B;

       /* Cadena de entrada */
       cout << "Intro expresion infija: ">
            getline( cin, infix );
       cout << endl;

       /*************************************************************
        PRIMERA PARTE: Procesar la cadena infijo, y crear posfijo
       *************************************************************/
       for ( i = 0; i < infix.size(); i++ )
       {
           /* esto debe cambiar luego a un token o palabra devuelta por
           * el analizador léxico */
           c = infix[i];
           token.clear();
           token += c; /* parece burdo, pero no conozco mejor manera de
   * crear un string a partir de un unico caracter */

           /* es un espacio: despreciar */
           if ( c == ' ' ) continue;

           cout << "Analizando token: '" << c << "'" << endl;

           if ( c >= '0' && c <= '9' )
           {
               cout<<"Init: "<<i<<endl;
               double aux = ConvertirNumero(infix,i);
               cout<<"finit: "<<i<<endl;
               cout << "\tes numero: pasado a posfijo:" << aux<<endl << endl;
               result.push(aux);

               // esto es solo para la depuracion

               stringstream cosa;
               cosa<<aux;

               postfix = postfix + " " + cosa.str();

               continue;
           }

           /* si se lee un operador: sacar de la pila y pasar al postfijo
           * todos los operadores con una precedencia mayor o igual a la
           * suya, y depositar el mismo en la pila */
           if ( is_operator( token ) )
           {
               cout << "\tes operador:" << endl;
               while ( !standby.empty() && precedence( standby.top() )
                       >= precedence( token ) )
               {
                   cout << "\tpasado operador '" + standby.top() +
                        "' de la pila a posfijo" << endl;
                   postfix = postfix + " " + standby.top();
                   standby.pop();
               }
               standby.push( token );
               cout << "\tcolocar '" << token << "' en la pila" << endl << endl;
               continue;
           }

           /* si se lee "(": colocar en la pila */
           if ( token == "(" )
           {
               cout << "pasado a posfijo" << endl << endl;
               standby.push( token );
               continue;
           }

           /* si se lee ")": retirar de la pila hasta encontrar '(', y pasar
           * los elementos retirados a posfijo, luego descartar el "(" */
           if ( token == ")" )
           {
               while ( !standby.empty() && standby.top() != "(" )
               {
                   cout << "\tpasado operador '" + standby.top() +
                        "' de la pila a posfijo" << endl << endl;
                   postfix = postfix + " " + standby.top();
                   standby.pop();
               }
               if ( !standby.empty() )
                   standby.pop(); /* descartar el "(" */
           }
       }

       /* extraer de la pila cualquier operador restante y pasarlo a la cadena posfijo */
       while ( !standby.empty() )
   {
       cout << "Pasado operador '" + standby.top() +
            "' de la pila a posfijo" << endl << endl;
       postfix = postfix + " " + standby.top();
       standby.pop();
   }

   /* Imprimir el posfijo */
   cout << "Posfijo es: \n\t" << postfix << endl << endl;

   /****************************************************************
    SEGUNDA PARTE: Procesar la cadena posfijo, y devolver resultado
   ****************************************************************/

   A = 0;
   cout << "Evaluando la expresion ..." << endl;
   for ( i = 0; i < postfix.size(); i++ )
   {

       c = postfix[i];
       token.clear();
       token += c;

       /* si se lee un operando (caracter numerico), depositar en la pila */
       if ( c >= '0' && c <= '9' )
       {


           continue;
       }

       /* si se lee un operador binario, poner en A y B los últimos dos argumentos
       * de la pila y operarlos, guardando el resultado en la pila */
       if ( is_operator( token ) )
       {
           if ( !result.empty() )
           {
               B = result.top();
               result.pop();
           }
           else
           {
               cout << "Argumentos insuficientes para '" << c << "'" << endl;
               return -1;
           }

           if ( !result.empty() )
           {
               A = result.top();
               result.pop();
           }
           else
           {
               cout << "Argumentos insuficientes para '" << c << "'" << endl;
               return -1;
           }

           cout << "\toperar " << A << token << B << " = ";
           if ( token == "+" )
           {
               A += B;
               result.push( A );
           }
           else if ( token == "-" )
           {
               A -= B;
               result.push( A );
           }
           else if ( token == "*" )
           {
               A *= B;
               result.push( A );
           }
           else if ( token == "/" )
           {
               A /= B;
               result.push( A );
           }
           else if ( token == "%" )
           {
               A = (int )A % (int )B;
               result.push( A );
           }
           else if ( token == "^" )
           {
               A = pow(A, B);
               result.push( A );
           }
           cout << A << endl;
       }
   }


   if ( !result.empty() )
       cout << endl << "El resultado es: " << result.top() << endl;

   return 0;
}

/* Verdadero si el token corresponde a un operador. */
bool is_operator( const string token )
{

   for ( int i = 0; i < N_operators; i++ )
       if ( operators[i] == token )
           return true;

   return false;
}

/* Devuelve la precedencia del operador descrito por el
* string token (-1 si no es un operador) */
int precedence( const string token )
{

   for ( int i = 0; i < N_operators; i++ )
       if ( operators[i] == token )
           return precedences[i];

   return -1;
}


Esto debería funcionarte con número de x cifras y con números decimales/enteros. El separador decimal puede ser ',' o '.' resulta totalmente indiferente.

Por supuesto, hay cosas que se pueden optimizar de ahí. Yo solo te he copypasteado la función y he tocado 1-2 cosas para que funcione (por ejemplo, que el deposito de números en la pila sea en la primera lectura y no en la segunda).

Por cierto:
Código (cpp) [Seleccionar]
token.clear();
token += c;


Esto es equivalente a:
Código (cpp) [Seleccionar]
token = c;

De todas formas, si solo vas a tener un caracter podrías usar un char a secas :huh: