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ú

Temas - class_OpenGL

#46
Hola, muy buenas. Tengo una duda que se podría catalogar como matemática más que duda de programación.

El caso es que la manera que he visto más eficiente para saber si un número es primo en C es la siguiente:
(Código corregido)
unsigned int is_prime = 1, numero_a_comprobar = 2453564567U;

for(j = 2; is_prime == 1 && j*j <= numero_a_comprobar; j++)
   is_prime = numero_a_comprobar%j != 0;

// Ahora 'is_prime' almacena si 'numero_a_comprobar' es primo


Mi duda es: ¿Por qué solo comprobamos los posibles divisores del número a comprobar con la condición 'j*j <= numero_a_comprobar'? Seguro que tiene una respuesta matemática, pero no la se...

Muchas gracias
#47
Hola, hoy presento una duda corta. Si en una clase tienes diversas definiciones de tipos, si estás tratando con un objeto, ¿puedes declarar una variable fuera de la clase del tipo que está definido en el objeto?

Código de ejemplo:
Código (cpp) [Seleccionar]
class Foo {
    public:
        typedef int tipo_entero;
   
    private:
        /* Aquí las variables de la clase */
};

...

int main() {
    Foo objeto;
   
    objeto.tipo_entero variable = 54;
   
    return 0;
}


Evidentemente no estaría preguntando esto pudiendo proponer el ejemplo. Al intentar compilar el código de arriba me salta el siguiente error:
main.cpp: In function 'int main()':
main.cpp:12:12: error: invalid use of 'Foo::tipo_entero'
objeto.tipo_entero variable = 54;


Pues eso, me gustaría saber si se puede hacer lo que he preguntado. Muchas gracias anticipadamente!
#48
Introducción (se puede saltar): Hola, muy buenas. En mi afán por hacer una consola (no es por reinventar la rueda, es cosa de practicar :D) decidí hacerla usando OpenGL (suena raro, pero lo estoy consiguiendo XD).

____
El problema con el que me he topado es a la hora de sobrecargar el operador <<. Para sobrecargarlo, he hecho lo siguiente:

screen.h
Código (cpp) [Seleccionar]
class ConsoleScreen {
   public:
       // Algunos métodos...
       
       template <class T>
       ConsoleScreen& operator<<(T value); // Prototipo del operador
   
   private:
       // Varias variables...

       std::ostringstream m_cOutput;
       
       // Y más variables...
}


screen.cpp
Código (cpp) [Seleccionar]
// Definición de los métodos...

template <class T>
ConsoleScreen& ConsoleScreen::operator<<(T value) { // Aquí defino el operador
   m_cOutput << value;
   return *this;
}


main.cpp
Código (cpp) [Seleccionar]
int main() {
   // Inicialización de la consola, prueba de métodos...
   
   cConsole << "Checking operator\n"; // Aquí marca el error
   
   // Destrucción de la consola...
   return 0;
}


El error que aparece en la linea que he marcado es el siguiente:
||=== Build: Release in Texto (compiler: GNU GCC Compiler (x64)) ===|
obj\Release\main.o:main.cpp:(.text.startup+0x13c)||undefined reference to `ConsoleScreen& ConsoleScreen::operator<< <char const*>(char const*)'|
||error: ld returned 1 exit status|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|


Como ven, me aparece que no he definido la sobrecarga del operador (cuando se ve claramente que si). El error solo me aparece con el operador, no con los métodos. He probado a cambiar (dentro de template) 'class' por typename, pero me dice lo mismo.

Para probar también, he definido el operador simplemente con un const char*, y en ese caso si que ha funcionado:
Código (cpp) [Seleccionar]
ConsoleScreen& ConsoleScreen::operator<<(const char* value) { // Aquí defino el operador
   m_cOutput << value;
   return *this;
}


Mi duda es: ¿Por qué me salta el error cuando uso plantillas?



Siento si la pregunta se hace larga de leer, pero no sé como podría resumirla más sin dar los datos que creo que son necesarios...
#49
Hola, muy buenas. Haciendo un código me ha surgido una duda bastante importante a mi parecer. Según tengo entendido, una buena función es aquella que apenas tiene 'return'. Bien, pues yo quiero hacer una función con un diagrama de flujo como el siguiente:

Realizar Operación
Comprobar si ha salido bien
>> Ha salido mal
     Salir del programa
>> Ha salido bien
Realizar Operación 2º
>> Ha salido mal
     Salir del programa
>> Ha salido bien
Realizar Operación 3º
...
Y así sucesivamente hasta que todas las operaciones hayan terminado con éxito. Eso, en C++, sería algo así:

Código (cpp) [Seleccionar]
bool funcion() {
    Realizar_Operacion_1();
    if(Operacion_1_ha_tenido_exito() == false) {
        return false;
    }

    Realizar_Operacion_2();
    if(Operacion_2_ha_tenido_exito() == false) {
        return false;
    }
    Realizar_Operacion_3();
    ...

    return true;
}


Ahora bien, si tenemos en cuenta lo que dije al principio, este programa no sería el mejor porque tiene muchos saltos de línea 'return'. Entonces, otra forma de solucionarlo es así:

Código (cpp) [Seleccionar]
bool funcion() {
    Realizar_Operacion_1();
    if(Operacion_1_ha_tenido_exito() == false) {
        return false;
    } else {
        Realizar_Operacion_2();
        if(Operacion_2_ha_tenido_exito() == false) {
            return false;
        } else {
            Realizar_Operacion_3();
            ...
        }
    }

    return true;
}


Pero este código se hace muy "ancho" cuando hay muchas operaciones a comprobar.

Entonces, lo último que se me ha ocurrido es lo siguiente:
Código (cpp) [Seleccionar]
bool funcion() {
    bool error = false;
   
    Realizar_Operacion_1();
    if(Operacion_1_ha_tenido_exito() == false) {
        error = true;
    }

    if(error == false) {
        Realizar_Operacion_2();
        if(Operacion_2_ha_tenido_exito() == false) {
            error = true;
        }
    }

    if(error == false) {
        Realizar_Operacion_3();
        if(Operacion_3_ha_tenido_exito() == false) {
            error = true;
        }
    }
   
    ...

    return error;
}


Pero no lo veo muy bien, son muchos 'if' que no sé si son necesarios...

Me gustaría saber si saber de algún método mejor para realizar este tipo de diagramas de flujo... Gracias
#50
Yo sé que para acceder a la memoria, se que se usan dos registros de 16 bits (uno se aprovecha entero, y el otro se aprovecha parte, para así sumar 20 bits, de donde viene la limitación). La duda es, ¿por qué no usaron esos dos registros al completo para así poder tener segmentos de 4GB? Gracias
#51
Hola, muy buenas. La duda es ¿dónde está el buffer de stdout? Por ejemplo, cuando llamamos a la función printf, lo que hacemos es copiar el buffer del parámetro de dicha función a otro buffer manejado por Windows. Entonces, ¿qué nivel de protección tiene?

Por si alguien anda despitadillo, me refiero a los anillos del modo protegido de los procesadores. He escuchado que suelen haber 4. El kernel se encuentra en el nivel 0, y las aplicaciones de usuario en el 3.

Lo pregunto por saber si puedo acceder a ese buffer directamente o está en el kernel, y por tanto solo se puede acceder a el por Windows y su API (o las librerías standard de los compiladores, aunque estas a su vez requieren a la API).

Gracias
#52
Hola, muy buenas! La pregunta es bastante simple. ¿Por qué Windows no usa interrupciones para operaciones de bajo nivel? Por ejemplo, Los sistemas Unix usan su clásica interrupción 0x80 para, por ejemplo, operaciones de lectura o escritura. Sin embargo, para hacer operaciones de escritura o lectura en Windows, necesitas usar su API.

La duda se puede plantear de otra forma. ¿Tienen las interrupciones alguna desventaja clara frente al sistema que usa Windows? Gracias!
#53
Hola, muy buenas a tod@s. El problema que tengo es que al intentar cerrar un archivo de un programa que estoy creando, la función que realiza eso crashea el programa.

El código es
Código (c++) [Seleccionar]
cPath.append(".bmp");
cFilteredImage.open(cPath,
                   std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
if(cFilteredImage.is_open() == true) {
       cFilteredImage.write(lpbyHeader, 54);

       for(unsigned int i = 0; i < stBmpData.uDataSize; i += stBmpData.uBitsPerPixel/8) {
               fVectorLength = calculateLength(&(stBmpData.lpbyData[i]));

               if(fVectorLength <= 100.0)
                       lpbyImageData[i/3] = true;
               else
                       lpbyImageData[i/3] = false;

               if(lpbyImageData[i/3] == true)
                       cFilteredImage.write("\xFF\xFF\xFF", 3);
               else
                       cFilteredImage.write("\x00\x00\x00", 3);
       }

       cFilteredImage.close();
}


A lo mejor la respuesta es obvia, pero no la veo :P Gracias por prestar atención

PD.: El archivo se escribe correctamente. El problema es al cerrarlo
#54
Hola, muy buenas a tod@s. Espero que esto lo lea algún moderador para que pueda solucionar ese error que voy a comentar y a ver si puede responderme a esto.

Bueno, la primera parte es que ahora, cuando hago click sobre ciertas áreas de esta página, de forma aleatoria me aparece publicidad en un pop-up o nueva pestaña. La pregunta es: ¿es normal, o es alguna clase de "virus"? Me parecería normal porque tenéis que obtener dinero (de algo se come), pero me resulta raro que sea con pop-ups y demás.

La segunda parte es para comentar un error. En el editor, cuando intento usar cualquiera de las ayudas que ofrece, no funciona (por ejemplo, las etiquetas GeSHI las tengo que poner manualmente, o las palabras remarcadas en negrita, o cualquiera de los botones encima del editor de texto de este foro). No sé si es solo a mí, por eso pregunto :P

PD.: Uso Google Chrome en Windows 10 de 64 bits. No tengo ningún tipo de extensión instalada (ni siquiera AdBlock). He pasado el AdwCleaner (para limpiar este tipo de "extensiones" que te añaden publicidad a las páginas que no tienen).

PD2.: En chrome, en su consola (pulsando F12), me aparece como que se han producido 1000 errores xD. Unos ejemplos de esos mil errores que me aparecen:
Uncaught ReferenceError: surroundText is not defined
post.html;board=10.0:378 Uncaught ReferenceError: bbc_highlight is not defined
VM183 post.html;msg=2050893;topic=445635.10;sesc=02dd5f80a8108345c2d72ee8898cf90f:427 Uncaught ReferenceError: storeCaret is not defined
post.html;board=10.0:378 Uncaught ReferenceError: bbc_highlight is not defined
post.html;board=10.0:322 Uncaught ReferenceError: bbc_highlight is not defined
post.html;board=10.0:322 Uncaught ReferenceError: surroundText is not defined
post.html;board=10.0:322 Uncaught ReferenceError: bbc_highlight is not defined
post.html;board=10.0:322 Uncaught ReferenceError: surroundText is not defined
301VM183 post.html;msg=2050893;topic=445635.10;sesc=02dd5f80a8108345c2d72ee8898cf90f:427 Uncaught ReferenceError: storeCaret is not defined
post.html;board=10.0:378 Uncaught ReferenceError: bbc_highlight is not defined


Muchas gracias por su atención y por este gran foro :D
#55
Hola, muy buenas. Estoy aprendiendo ensamblador y para ello lo estoy enlazando con las librerías estandar de C++. No sé mucho sobre la sintaxis de intel (estoy aprendiendo NASM), pero he conseguido el siguiente código (el cual está guardado en el archivo intercambiar.s)

Código (asm) [Seleccionar]
.file "intercambiar.cpp"
.text
.globl __Z12intercambiarPiS_
.def __Z12intercambiarPiS_; .scl 2; .type 32; .endef
__Z12intercambiarPiS_:
LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5

movl 8(%ebp), %eax
movl 12(%ebp), %ebx
movl %eax, 12(%ebp)
movl %ebx, 8(%ebp)

popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE0:
.ident "GCC: (GNU) 4.8.1"


Lo que he hecho es conseguir el código base gracias al compilador g++ de MinGW y añadir el intercambiador de variables.

Lo que sería el intercambiador es el siguiente:

Código (asm) [Seleccionar]
pushl %ebp
movl %esp, %ebp

movl 8(%ebp), %eax
movl 12(%ebp), %ebx
movl %eax, 12(%ebp)
movl %ebx, 8(%ebp)

popl %ebp
ret


Lo que he hecho después es ejecutar el siguiente comando:
g++ -Wall -c intercambiador.s

Con el, he obtenido un fichero objeto

Ahora bien, cuando ejecuto el programa principal, no me intercambia las variables.

Aquí tenéis el programa principal en C++:

Código (c++) [Seleccionar]
#include <iostream>

void intercambiar(int* lpnValorA, int* lpnValorB);

int main() {
int nValorA, nValorB;

std::cout << "Introduzca el valor A: ";
std::cin >> nValorA;
std::cout << "Introduzca el valor B: ";
std::cin >> nValorB;

intercambiar(&nValorA, &nValorB);

std::cout << "\nnValorA = " << nValorA << std::endl;
std::cout << "nValorB = " << nValorB;

std::cin.get();
std::cin.get();
return 0;
}


Pues eso, el intercambiador no hace nada

Soy novato en ASM, por lo que no seáis duros :D Gracias
#56
Hola, muy buenas a tod@s. Mi pregunta (aunque no sé si debería ir en este subforo) es la siguiente: ¿Se puede crear un acceso directo de Windows que te rellene los cuadros de texto que están nombrados por un nombre?
Por ejemplo, una página tiene los siguientes recuadros:

Código (html4strict) [Seleccionar]
<input id="consultaNotaForm:nifnie" type="text" name="consultaNotaForm:nifnie" class="submenu" maxlength="9" size="15">
...


Gracias por ver el tema
#57
Programación C/C++ / (Consulta) Operador const_cast
30 Noviembre 2015, 08:29 AM
(Aquí cuento un poco como he llegado a mi duda, puedes leer un resumen abajo)

Hola, muy buenas. El caso es que acabo de encontrarme con este operador, el cual me parece un tanto curioso. Bueno, supongo que cada uno, cuando ha visto este operador, se ha hecho la pregunta ¿podré modificar el valor de una constante? Bueno, pues para probarlo, he elaborado el siguiente código:

Código (cpp) [Seleccionar]
#include <iostream>

int main() {
   const int value_a = 5;
   int *value_b = NULL;

   value_b = const_cast<int *>(&value_a);
   *value_b = 6;

   std::cout << "&value_a = " << &value_a << std::endl; // Imprimimos direcciones
   std::cout << " value_b = " << value_b << std::endl;
   std::cout << std::endl;
   std::cout << " value_a = " << value_a << std::endl; // Imprimimos valores
   std::cout << "*value_b = " << *value_b;

   std::cin.get();
   return 0;
}


El resultado que he obtenido, es cuanto menos curioso:
Citar&value_a = 0x9ffe34
value_b = 0x9ffe34

value_a = 5
*value_b = 6

Bueno, analicemos. Las dos variables, efectivamente, tienen la misma dirección (así que el casting parece haberse computado correctamente). La cosa es que para dos mismas direcciones de dos variables, ¡tenemos dos valores diferentes!

La duda, en resumidas cuentas es, ¿cómo es posible que para una misma dirección de memoria haya dos valores diferentes almacenados? ¿o a lo mejor sucede otra cosa?

Gracias :D
#58
Hola, muy buenas. En mi rato libre, quise mirar un poco el standard de C++. Una cosa de las que he mirado es los operadores definidos para los streams definidos en este (lo he mirado tanto en cplusplus como en el propio archivo de mi compilador MinGW.

Un ejemplo de lo que encontré en el archivo "ostream" es el siguiente:
Código (cpp) [Seleccionar]
__ostream_type& operator<<(long __n);

La duda es: ¿No necesita una clase o estructura en los parámetros del operador para ser correcto?

Bueno. Para intentar no tener que preguntar, he hecho el siguiente ejemplo:

Código (cpp) [Seleccionar]
#include <cstdio>

struct stream {
    int null;
};

stream& operator<< (int val);

int main() {
    stream ostream = {0};

    ostream << 123 << 5;

    return 0;
}


stream& operator<< (int val) {
    printf("%i", val);
}


Pero en las definiciones del operador he tenido que poner esto, porque si no me daba error:

Código (cpp) [Seleccionar]
stream& operator<< (stream& ostream, int val);

Esto no esclarece nada :S Gracias por su ayuda!
#59
Hola. Estoy buscando un libro en español para aprender C++11. No sé si existe en español. En caso de que no haya, ¿cuál me recomiendan en inglés? Gracias de antemano.
#60
Hola a todos. He visto que muchos de mis amigos y que algunas personas de Internet no comprenden muy bien que es lo que hacen cuando usan std::cin >> variable. Por esto mismo, y pareciendo ser una tontería, he diseñado un pequeño diagrama de flujo para que así vea la gente como funciona. Aquí os lo dejo



Procedo a explicarlo. Lo primero que tenemos que saber es que hay un buffer por ahí que guarda lo que metemos por consola. Entonces, lo primero que hace std::cin>> es comprobar que no haya datos en ese buffer. Si no los hay, entonces procedemos a pedir datos por la consola. Si le damos a enter sin meter nada, entonces se imprimirá un espacio de línea y te pedirá de nuevo que ingreses datos (pues no has ingresado nada), y así hasta que introduzcas algún dato. Entonces, sabiendo que el buffer que maneja std::cin tiene algo, procedemos a comprobar. Lo primero que tenemos que saber es que std::cin recogerá datos de su buffer (que es como una cadena de caracteres) hasta que se encuentre con un espacio (' ') o un salto de línea ('\n'). Entonces, comprobamos si esos datos pueden ser almacenados en la variable que queríamos modificar. Por ejemplo, si la variable es de tipo entero pero "Hola", entonces se determina que no son datos compatibles. En ese caso, a esa variable se le asigna el valor 0 y se establece una bandera de error para que así sepamos que ha habido un error. Date cuenta que si los datos no corresponden, el buffer no se limpia, sino que permanece con los datos introducidos. Pero si los datos concuerdan, entonces se transforman al tipo de variable de entrada y se eliminan esos datos del buffer que maneja std::cin (se eliminan los datos hasta el espacio o salto de línea) y en último lugar se imprime un salto de línea.

Espero que lo hayan entendido y que despeje muchas dudas :D

Ejemplos prácticos de las consecuencias de este diagrama:

Código (cpp) [Seleccionar]
#include <iostream>
#include <limits>

int main() {
   int nValor = 1;
   std::string cString;

   std::cout << "Introduzca un número: ";
   std::cin >> nValor;

   std::cin >> cString;
   
   std::cout << "nValor = " << nValor << std::endl;
   std::cout << "cString = \"" << cString << "\"";

   std::cin.clear();
   std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
   std::cin.get();
   return 0;
}


Si compilamos y ejecutamos este código, obtendremos la siguiente salida (la salida está enmarcada. Lo otro son explicaciones):

Introduzca un número:
Puesto que inicialmente el buffer que maneja std::cin está vacio, entonces el programa se detiene ahí para que introduzcas algo.
Vamos a teclear Hola (que evidentemente no es un entero como se pide) para ver que pasa:

Vamos a comprobar si estáis atentos. ¿Qué debería pasar ahora?

Bien, lo que va a pasar ahora es que std::cin >> cString va a ver que el buffer ya tiene datos guardados (no se han eliminado puesto que se ha producido un error), por lo que el thread no se va a detener como esperaríamos desde un principio, sino que directamente va a asignar esos datos a cString (aquí no hay ningún error, pues "Hola" es un string)

Entonces, una vez pulsado enter al introducir hola, la salida quedaría así:

Introduzca un número: Hola
nValor = 0
cString = "Hola"


Como veis, la variable 'nValor' tiene un valor de 0, pese a que la hemos inicializado como 1. Eso quiere decir que std::cin ha cambiado el valor de esta variable a 0 (tal y como sale en el diagrama).

Bueno, eso es todo. La mejor manera de que lo veáis es que ejecutéis el código por vosotros mismos y experimentéis. Un último apunte: la función std::cin.clear() lo que hace es limpiar la lista de errores producidos, no limpia el buffer!

Gracias por su atención.

Se aceptan sugerencias y/o optimicaciones :D