Dar nombre de una variable por un usuario en c++

publicado por: Anonymous

Buenas días;

Solo una pregunta que llevo mucho tiempo haciéndomela. En un programa de c++ podemos declarar con un nombre a una variable de forma muy sencilla, por ejemplo:

int operando_uno;

Sin embargo, mi pregunta es si se puede dar ese nombre “operando_uno” pero que sea el usuario el que la introduzca para que posteriormente sea usada. Por ejemplo, algo así;

cout<<“intro nombre de variable”; //El usuario introduce operando_uno
/Aquí introducir código para asignar a operando_uno un valor/
suma= operando_uno + operando_dos; //Ahora hacemos uso de operando_uno

Se podría hacer???

solución

No, no se puede.

Sí, sí que se puede hacer en lenguajes que soportan reflexión.
Pero C++ no soporta reflexión. Soporta RTTI, que es un subconjunto de reflexión, pero no es suficiente para hacer esto.

Sí se puede desde un punto de vista funcional.

Puedes implementar esta funcionalidad de cara al usuario. La herramienta apropiada es el diccionario, std::map en C++. Trauma da un ejemplo de uso en su respuesta. No tendrás variables añadidas al programa a nivel del código del lenguaje, sino a nivel de datos, pero esto no es importante.

Sí que se puede.

Con un programa que se modifique a sí mismo.

El siguiente programa permite al usuario añadir nuevas variables, asignarles valores e imprimir su suma.
Cuando el usuario introduce un nuevo nombre de variable el programa copia su propio código C++ que está en unos ficheros de plantilla y añade las líneas necesarias para las nuevas variables. Después compila el programa y ejecuta el nuevo programa substituyendo al antiguo.
El programa necesita de 4 ficheros auxiliares.
Está hecho con GNU g++ sobre linux, pero se puede adaptar a cualquier sistema.

He usado nombres de variables y funciones que empiezan por _ para que no entren en conflicto con los que use el usuario. Pero igualmente hay nombres de variable prohibidos como int o main. Esto se detecta porque el programa no compila.

Si a alguien se le ocurre usar esta loca idea para software real debe tener en cuenta que es vulnerable a ataques de inyección C++.

El programa programa.cpp:

#include <unistd.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>

// Variables definidas por el usuario

// Lista de nombres de variables
std::vector<std::string> _nombresVar;

int* _obtenerPuntero( std::string _nombre) {
    auto _it = std::find(_nombresVar.begin(), _nombresVar.end(), _nombre);
    int _pos = _it - _nombresVar.begin();
    switch ( _pos ) {
    }
}

void _componerListaNombresDeVariable() {
}

std::string _pideNombre()
{
    std::cout << "Introduzca nombre de variable:";
    std::string _nombre;
    std::cin >> _nombre;
    return _nombre;
}

void _crearCodigoCpp( std::string _nombreNuevaVar ) {
    std::ofstream _fich;

    system( "rm -f prog generado.cpp");
    system( "cat plantilla1.cpp >> generado.cpp");

    // Escribir codigo que declara las variables.
    _fich.open ("generado.cpp", std::ofstream::out | std::ofstream::app);
    for( auto _it=_nombresVar.begin(); _it!=_nombresVar.end(); ++_it)
        _fich << "int " << *_it << " = " << *_obtenerPuntero(*_it) << ";n";
    _fich << "int " << _nombreNuevaVar << " = 0;n";
    _fich.close();

    system( "cat plantilla2.cpp >> generado.cpp");
    
    // Escribir codigo para obtener un puntero a una variable. Usado por _obtenerPuntero()
    _fich.open ("generado.cpp", std::ofstream::out | std::ofstream::app);
    for ( int _i = 0; _i<_nombresVar.size(); ++ _i )
        _fich << "case " << _i << ": return &" << _nombresVar[_i] << ";n"; 
    _fich << "case " << _nombresVar.size() << ": return &" << _nombreNuevaVar << ";n"; 
    _fich.close();

    system( "cat plantilla3.cpp >> generado.cpp");

    // Escribir codigo que añade nombres de variables a la lista.
    _fich.open ("generado.cpp", std::ofstream::out | std::ofstream::app);
    for( auto _it=_nombresVar.begin(); _it!=_nombresVar.end(); ++_it)
        _fich << "_nombresVar.push_back("" << *_it << "");n";
    _fich << "_nombresVar.push_back("" << _nombreNuevaVar << "");n";
    _fich.close();
    
    system( "cat plantilla4.cpp >> generado.cpp");
}

void _anyadirVar() {
    std::string _nombre = _pideNombre();
    auto it = std::find(_nombresVar.begin(), _nombresVar.end(), _nombre);
    if ( it!=_nombresVar.end() ) {
        std::cout << "¡Incorrecto! Ese nombre ya está usado.n";
        throw 1;
    }
    _crearCodigoCpp(_nombre);
    int _res = system( "g++ -std=c++11 -o generado generado.cpp > /dev/null 2>/dev/null");
    if ( _res!=0 ) {
        std::cout << "No se puede usar ese nombre de variable.n";
        throw 1;
    }
    _nombresVar.push_back(_nombre);
    execl( "./generado", NULL);
}

void _asignarValor() {
    std::string _nombre = _pideNombre();
    auto _it = std::find(_nombresVar.begin(), _nombresVar.end(), _nombre);
    if ( _it==_nombresVar.end() ) {
        std::cout << "¡Incorrecto! Esa variable no existe.n";
        throw 1;
    }
    int _valor;
    std::cout << "Introduzca valor entero:";
    std::cin >> _valor;
    if ( std::cin.fail() )
        throw 2;
    int* _p = _obtenerPuntero( _nombre );
    *_p = _valor;
}

void _calcularSuma() {
    int _suma = 0;
    
    for ( auto _it=_nombresVar.begin(); _it!=_nombresVar.end(); ++_it ) 
        _suma += *_obtenerPuntero(*_it);
    
    std::cout << "Las variables suman " << _suma << "n";
}

int main() {
    _componerListaNombresDeVariable();
    for(;;) {
        try {
            std::cout << "Elija opción y pulse INTRO:n";
            std::cout << "1.- Añadir variablen"; 
            std::cout << "2.- Asignar valor a variablen"; 
            std::cout << "3.- Calcular suman"; 
            std::cout << "4.- Salirn"; 
            std::cout << "Opcion:" << std::flush;
            int _opcion;
            std::cin >> _opcion;
            if ( std::cin.fail())
                throw 2;
            switch ( _opcion ) {
                case 1: _anyadirVar(); break;
                case 2: _asignarValor(); break;
                case 3: _calcularSuma(); break;
                case 4: return 0;
                default :
                    std::cout << "Opcion incorrectan";
            }
        }
        catch( int _err ) {
            if ( _err==2 ) {
                std::cout << "Eso no es un numeron";
                std::cin.clear();
                std::cin.ignore(256,'n');            
            }
        }
    }
    
    return 0;
}

Fichero plantilla1.cpp :

#include <unistd.h>
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>

// Variables definidas por el usuario

Fichero plantilla2.cpp :

// Lista de nombres de variables
std::vector<std::string> _nombresVar;

int* _obtenerPuntero( std::string _nombre) {
    auto _it = std::find(_nombresVar.begin(), _nombresVar.end(), _nombre);
    int _pos = _it - _nombresVar.begin();
    switch ( _pos ) {

Fichero plantilla3.cpp :

    }
}

void _componerListaNombresDeVariable() {

Fichero plantilla4.cpp :

}

std::string _pideNombre()
{
    std::cout << "Introduzca nombre de variable:";
    std::string _nombre;
    std::cin >> _nombre;
    return _nombre;
}

void _crearCodigoCpp( std::string _nombreNuevaVar ) {
    std::ofstream _fich;

    system( "rm -f prog generado.cpp");
    system( "cat plantilla1.cpp >> generado.cpp");

    // Escribir codigo que declara las variables.
    _fich.open ("generado.cpp", std::ofstream::out | std::ofstream::app);
    for( auto _it=_nombresVar.begin(); _it!=_nombresVar.end(); ++_it)
        _fich << "int " << *_it << " = " << *_obtenerPuntero(*_it) << ";n";
    _fich << "int " << _nombreNuevaVar << " = 0;n";
    _fich.close();

    system( "cat plantilla2.cpp >> generado.cpp");
    
    // Escribir codigo para obtener un puntero a una variable. Usado por _obtenerPuntero()
    _fich.open ("generado.cpp", std::ofstream::out | std::ofstream::app);
    for ( int _i = 0; _i<_nombresVar.size(); ++ _i )
        _fich << "case " << _i << ": return &" << _nombresVar[_i] << ";n"; 
    _fich << "case " << _nombresVar.size() << ": return &" << _nombreNuevaVar << ";n"; 
    _fich.close();

    system( "cat plantilla3.cpp >> generado.cpp");

    // Escribir codigo que añade nombres de variables a la lista.
    _fich.open ("generado.cpp", std::ofstream::out | std::ofstream::app);
    for( auto _it=_nombresVar.begin(); _it!=_nombresVar.end(); ++_it)
        _fich << "_nombresVar.push_back("" << *_it << "");n";
    _fich << "_nombresVar.push_back("" << _nombreNuevaVar << "");n";
    _fich.close();
    
    system( "cat plantilla4.cpp >> generado.cpp");
}

void _anyadirVar() {
    std::string _nombre = _pideNombre();
    auto it = std::find(_nombresVar.begin(), _nombresVar.end(), _nombre);
    if ( it!=_nombresVar.end() ) {
        std::cout << "¡Incorrecto! Ese nombre ya está usado.n";
        throw 1;
    }
    _crearCodigoCpp(_nombre);
    int _res = system( "g++ -std=c++11 -o generado generado.cpp > /dev/null 2>/dev/null");
    if ( _res!=0 ) {
        std::cout << "No se puede usar ese nombre de variable.n";
        throw 1;
    }
    _nombresVar.push_back(_nombre);
    execl( "./generado", NULL);
}

void _asignarValor() {
    std::string _nombre = _pideNombre();
    auto _it = std::find(_nombresVar.begin(), _nombresVar.end(), _nombre);
    if ( _it==_nombresVar.end() ) {
        std::cout << "¡Incorrecto! Esa variable no existe.n";
        throw 1;
    }
    int _valor;
    std::cout << "Introduzca valor entero:";
    std::cin >> _valor;
    if ( std::cin.fail() )
        throw 2;
    int* _p = _obtenerPuntero( _nombre );
    *_p = _valor;
}

void _calcularSuma() {
    int _suma = 0;
    
    for ( auto _it=_nombresVar.begin(); _it!=_nombresVar.end(); ++_it ) 
        _suma += *_obtenerPuntero(*_it);
    
    std::cout << "Las variables suman " << _suma << "n";
}

int main() {
    _componerListaNombresDeVariable();
    for(;;) {
        try {
            std::cout << "Elija opción y pulse INTRO:n";
            std::cout << "1.- Añadir variablen"; 
            std::cout << "2.- Asignar valor a variablen"; 
            std::cout << "3.- Calcular suman"; 
            std::cout << "4.- Salirn"; 
            std::cout << "Opcion:" << std::flush;
            int _opcion;
            std::cin >> _opcion;
            if ( std::cin.fail())
                throw 2;
            switch ( _opcion ) {
                case 1: _anyadirVar(); break;
                case 2: _asignarValor(); break;
                case 3: _calcularSuma(); break;
                case 4: return 0;
                default :
                    std::cout << "Opcion incorrectan";
            }
        }
        catch( int _err ) {
            if ( _err==2 ) {
                std::cout << "Eso no es un numeron";
                std::cin.clear();
                std::cin.ignore(256,'n');            
            }
        }
    }
    
    return 0;
}
Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *