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 - Loretz

#91
Citarcurioso.. pero por que sucede esto?, acaso el compilador se confunde cuando copio memoria de un puntero?
No, el compilador hace lo que le dices.

char * nombre; es un puntero a char, una variable que puede guardar una dirección de memoria. Dependiendo de la plataforma; su tamaño suele ser de 32 bits o de 64 bits.

char nombre[16]; es un array de caracteres de estilo C; puede guardar una sucesión de caracteres, muchas veces con un cero al final; su tamaño es siempre de 16 Bytes (128 bits).

No es lo mismo guardar en un archivo una dirección de memoria que guardar una sucesión de caracteres. En el primer caso podrías estar guardando algo como  2127788540 y en el segundo algo como  castellanamente.

#92
Hola; ¿por qué no pones un ejemplo completo pero mínimo que se pueda compilar? Así creo que va a ser más fácil.
#93
CitarEl resultado es que cuando 0!=0 entonces ocurrirá que 0 < 0. No dice que 0!=0, sino que cuando 0!=0, absurdo, entonces 0<0 (otro absurdo). Genial!  Pura lógica.

Una proposición falsa implica a todas las proposiciones, verdaderas o falsas. Que uno se encuentre con una aparente consistencia puede favorecer el entusiasmo pero no aporta prueba de nada; lamentablemente la pura lógica no se conmueve con expresiones emocionales :)

Pero bueno, este es tu acertijo y tus reglas. Por mí está bien, como digas.
#94
Respuesta aquí:
https://en.cppreference.com/w/cpp/io/basic_ios/operator_bool

En particular, en el caso 2) el operator bool devuelve true cuando el stream no tiene ninguno de los bits de error activos.
Citar"2) Returns true if the stream has no errors and is ready for I/O operations. Specifically, returns !fail()."


#95
En tu ejemplo, la declaración de f_obtenerEdad() y su definición son distintas (en otros bares podrían decirte que es más respetuoso poner ejemplos que compilen).

Yo veo dos cosas, una es que las formas habituales de definir una función friend son
1) "inline", directamente en el cuerpo de la clase, y
2) en un archivo cpp, ampliando el mismo namespace. (Abajo pongo esta alternativa).

La otra es que puedes tener dos funciones (sobrecarga) con la misma firma, una friend en el mismo namespace de la clase, y otra no friend y global, y en este caso con using namespace... el compilador no sabría a cuál de las dos te refieres.

Acá abajo va un ejemplo:

Código (cpp) [Seleccionar]
// en Agenda.h
namespace Agenda {
    class Persona {
        int edad = 42;
        friend int f_obtenerEdad(Persona& _p);

    public:
        int sumaEdad(int i)
        {
            return edad + i;
        }
    };
}

// Mejor que la de abajo
// en Agenda.cpp
namespace Agenda {
    int f_obtenerEdad(Persona& p)
    {
        return p.edad;
    }
}

/*
// Menos mejor que la de arriba
int Agenda::f_obtenerEdad(Agenda::Persona& _p)
{
    return _p.edad;
}
*/


// otra pero global:
int f_obtenerEdad(Agenda::Persona& _p)
{
    return _p.sumaEdad(5);
}




#include <iostream>

int main()
{
    Agenda::Persona p;
    std::cout << Agenda::f_obtenerEdad(p) << '\n';

    std::cout << ::f_obtenerEdad(p) << '\n'; // usa la versión global
}
#96
El primer caso a mí me parece lo mismo; para el segundo lo único que se me ocurre es que alguien ha estado jugando con <assert>, así que si yo también...

#include <stdio.h>
#include <string.h>

#define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)

#define assert(expression) (void)((!(expression)) || (mostrar(#expression, __FILENAME__, (unsigned)(__LINE__), __func__), 0))

#define for(a) while(0)

void mostrar(const char* message, const char* file, int line, const char* function)
{
    printf("%s: %s:%i: %s: Assertion \'%s\' failed\n", function, file, line, function, message);
}

int main()
{
    for( ;1; );

    assert(1);
}
#97
En C (y en C++) una struct puede tener un "puntero a función" como miembro, que no es lo mismo que una "función miembro" por supuesto, pero es la forma que puede usarse en C para asociar comportamiento a una struct.

Va un ejemplo:

#include <stdio.h>

struct foo {
    int bar;
    int(*pfun)(int, int); // puntero a función que devuelve int y que toma dos ints como parámetros.
};

int sumar(int x, int y)
{
    return x + y;
}

int multiplicar(int x, int y)
{
    return x * y;
}

int main()
{
    struct foo asd;
    asd.bar = 3;
    asd.pfun = &sumar;

    printf("suma = %i\n", asd.pfun(5, 5));

    asd.pfun = &multiplicar;
    printf("producto = %i\n", asd.pfun(5, 5));

    return 0;
}
#98
Debe haber por ahí alguna fórmula genial, de esas del tipo (a+b)^2  que nos deje a todos con la boca abierta, pero andando a pie, siguiendo la descripción más pedestre posible, mi algoritmo es este:

#include <iostream>
#include <cmath>
#include <array>

int main()
{
    // el primer círculo empieza en 2 y termina en 9
    // el segundo empieza en 10 y termina en 25
    // el tercero ... de 26 a 49 ...

    // Claramente, cada círculo empieza donde termina el anterior y
    // terminan en 9 (3*3) o en 25 (5*5) o en 49 (7*7) ... [los cuadrados del número de elementos de sus lados]

    // También, cada círculo tiene elementos que están más próximos al centro y están ubicados en cruz:

    // Se ve que en la rama de la derecha de esa cruz están:
    // el 2 (primer círculo),
    // el 11 (su número de círculo + los elementos del círculo anterior = 2 + 9),
    // el 28 (su número de círculo + los elementos del círculo anterior = 3 + 25).
    // y lo mismo para los siguientes...

    // Mirando también en las otras direcciones,
    // el primer círculo tiene en esa cruz al 2, que es por donde empieza,
    // y en las otras ramas al 4 (o sea, el 2 + su número de elementos por lado = 4),
    // tiene también al 6 (4 + su número de elementos por lado = 6)
    // y al 8 (6 + su número de elementos por lado -1 == 8).
    // Así que para el primer círculo esa cruz está formada por el 2, 4, 6, 8.

    // Lo mismo para los otros círculos:
    // el segundo círculo tiene al 11, 15, 19 y 23.

    // Cada círculo va a tener 4 números sobre la cruz:
    // el primero que está en el brazo horizontal de la derecha
    // y los otros tres distando entre sí la cantidad de elementos en cada lado.

    // Bueno, eso es todo.


    // Para calcular la distancia al centro de un número cualquiera habrá que calcular
    // la distancia a la rama más próxima de la cruz y sumar su número de círculo.

    // Por ejemplo: dado un númeo cualquiera:

    int n;
    std::cout << "numero: ";
    std::cin >> n;

    // Se puede determinar a qué círculo pertenece:
    int c = 0;
    for (int i = 1; ; i += 2, ++c) {  // 1, 3, 5, 7, ...
        if (i*i >= n) {
            break;
        }
    }
    std::cout << n << " pertenece al circulo " << c << '\n';

    // Este círculo tiene 4 números sobre la cruz central:
    std::array<int, 4> cruz;

    // El primero (rama de la derecha) es:
    cruz[0] = c + (2 * c - 1)*(2 * c - 1);  // su número de círculo más los elementos del círculo anterior

    // y los otros tres van a ser:
    for (int i = 1; i < 4; ++i) {
        cruz[i] = cruz[i - 1] + c * 2; // número anterior en la cruz + cantidad de elementos del lado
    }

    std::cout << "los elementos de la cruz son: ";
    for (const auto& i : cruz) {
        std::cout << i << "  ";
    }
    std::cout << '\n';

   
    // Ahora, la distancia al centro de este número es:
    // la distancia al elemento de la cruz más cercano + su número de círculo:

    int dist_cruz = 1000; // absurdamente grande
    for (int i = 0; i < 4; ++i) {
        if(abs(cruz[i] - n) < dist_cruz) {
            dist_cruz = abs(cruz[i] - n);
        }
    }
    int distancia = dist_cruz + c;

    std::cout << "distancia al centro = " << distancia << '\n';
}


#99
Pregunta:
Es esto necesario?

Citarvoid Persona::IngresarNombre(const char * nombre){
     strcpy(this->nombre, nombre);

     delete nombre;   //Es esto necesario?
}

Respuesta:
¿Cómo saberlo?

Se podría intentar responder primero a algunas cuestiones preliminares, por ejemplo:

¿Está claro en la documentación de cada función que invoca a IngresarNombre() que este parámetro va a ser destruido (delete) (y que cualquiera que vaya a usarla jure primero no volver a usar ese puntero después del punto de llamada).

Este puntero "nombre" ¿fue creado con new? ¿Seguro? (¿no habrá sido con malloc?)

¿No convendría llamar a esta función de alguna manera que deje más claro su comportamiento, por ejemplo,  IngresarNombreYCuidadoQueAcaMuereElPunteroNombre() ?

Cuando una función recibe un puntero "final", se dice que esa función recibe el "ownership", la responsabilidad del "delete", y se la suele llamar "sink function".

Ejemplo:

void sink_f(const char* p) // ¡¡ATENCIÓN!! ESTA FUNCIÓN DESTRUIRÁ A p ¡¡CUIDADO!! ¡¡ALERTA!!
{
    // hacer algo con p, y después
    delete[] p;
}


Y una forma de llamarla sería:

int main()
{
    char* str = new char[12];
    strcpy(str, "hola mundo!");
    sink_f(str);
    // delete[] str; // QUÉ SUERTE QUE LEÍ EL COMENTARIO DE sink_f(), uffff!!

}



Francamente... ¿qué opinas?

Por suerte ya nadie hace cosas como esa, espero.