[Consulta] ¿Se desaprueba este código?.

Iniciado por sabeeee, 28 Enero 2015, 01:47 AM

0 Miembros y 1 Visitante están viendo este tema.

sabeeee

Código (cpp) [Seleccionar]
/*
¿Porque se ultiliza goto? Porque si, reduzco codigo.
*/

#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;

FILE *archivo;
  FILE *ccmd;

char *pos;

char caracteres[150];

int main( int argc, char **argv) {
    char ArchivoAbrir[21];
char ArchivoSaliente[21];

        if ( argc < 3 ) {
cout<<"Ejemplo: programa \"Archivo a Abrir.cmd\" -c \"ArchivoSaliente.c\" "<<endl;
return 1;
}
if ( !strcmp( argv[2], "-c" ) ) {

strncpy( ArchivoAbrir, argv[1], 20 );
ArchivoAbrir[21] = '\0';

strncpy( ArchivoSaliente, argv[3], 20 );
ArchivoSaliente[21] = '\0';
}

archivo = fopen(argv[1],"r");
ccmd = fopen(argv[3],"wt");

if (archivo == NULL)
exit(1);

while (!feof(archivo))
{
fgets( caracteres, 150, archivo );
if ((pos=strchr(caracteres, '\n')) != NULL)
*pos = '\0';

while (!strcmp(caracteres,"PAUSE>NUL"))
{
goto PAUSANULA;
}

while (!strcmp(caracteres,"PAUSE"))
{
fprintf(ccmd,"\tputs(\"Presione una tecla para continuar.\");\n");
PAUSANULA:
fprintf(ccmd,"\tgetchar();\n");
caracteres[0] = '\0';
}

while (!strcmp(caracteres,"EXIT"))
{
fprintf(ccmd,"\treturn 0 ;\n");
caracteres[0] = '\0';

}

while (!strcmp(caracteres,"CLS"))
{
goto LIMPIADO;
}
while (!strcmp(caracteres,"CLEAR"))
{
LIMPIADO:
fprintf(ccmd,"\tputs(\"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\");\n");
caracteres[0] = '\0';
}

while (!strcmp(caracteres,"FIN"))
                {
goto FIN;
caracteres[0] = '\0';
                }

if (!strcmp(caracteres,"\0"))
                {
}else{
fprintf(ccmd,"\tsystem(\"%s\");\n",caracteres);
caracteres[0] = '\0';
}
  }
FIN:
        fclose(archivo);
fclose(ccmd);
cout<<"Compilado.."<<endl;
getchar();
}


¿Alguna razón para que no sea así?
"Vengándose, uno iguala a su enemigo; perdonando, uno se muestra superior a él."
Francis Bacon

engel lex

si se desaprueba... en lugar de usar goto puedes perfectamente usar funciones y estructurar tu código correctamente, menos codigo no hará tu programa más eficiente, ni legible, solo lo hará confuso y complicado
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

sabeeee

#2
Y como se podría simplificar, o mejorar. Dijkstra se debe estar levantando de la tumba para matarme, dice en wikipedia:

Respecto a su carácter árido y ácido, conocidas son su oposición a la instrucción GOTO y al lenguaje BASIC («mutila la mente más allá de toda recuperación»). Alan Kay expuso que en informática, la arrogancia se mide en nanodijkstras.
"Vengándose, uno iguala a su enemigo; perdonando, uno se muestra superior a él."
Francis Bacon

BlackM4ster

El uso de goto es una práctica muy mala... el código se hace ilegible
- Pásate por mi web -
https://codeisc.com

exploiterstack

#4
Hola sabeeee,

Mira hacer uso de goto esta totalmente desaconsejado ya que crea muy mal abito y rompe por completo lo que es la programación estructurada, ahora por ejemplo no lo veras pero si analizar tu código o lo  depuras lo entenderás mucho mas fácilmente, ya que puede darse el caso que instrucciones nunca se lleguen a ejecutar cosa que va en contra de los fundamentos de la programación estructurada como bien describió Dijkstra.

Si quieres saber mas de por que no utilizar esta instrucción te aconsejo que leas sobre programación espagueti.

Espero haberte ayudado, un saludo! ;)

Orubatosu

Todo esto es muy técnico a veces, y puede parecer purismo, pero tengamos un par de cosas en cuenta.

"Goto" es una sentencia muy antigua, y proviene de lenguajes interpretados con Basic.

Incluso en lenguajes interpretados, se puede programar de forma eficiente sin algo tan contrario a la claridad como es un salto incondicional, pero en algunos interpretes muy antiguos, cabe la posibilidad de que tuviera algún sentido (poco), desde el momento en que el lenguaje interpretado va leyendo secuencialmente una lista de instrucciones.

En lenguajes compilados, usar "goto", funciones, acciones o cualquier otra estructura no va a influir en su velocidad de ejecución, porque el compilador "ya se las apaña" para desmenuzar tu código y convertirlo en "otra cosa". En lenguaje máquina si que existen obviamente los saltos incondicionales (ahí son algo diferente). Tu código en realidad solo va a ser mas eficiente y rápido mediante la elección de los tipos de variables adecuadas, la resolución mas eficiente de un algoritmo y otras, entre las cuales pueden estar (por ejemplo) que compiles específicamente para un tipo determinado de procesador y otras.

Pero, que pongas mas o menos comentarios, que definas las funciones delante o detrás del main, que uses variables globales o locales exclusivamente y otras no van a hacer que tu programa "corra mas".

Dado que tu programa en principio, puede ser igual de eficiente si usas goto que si no lo usas, ¿porque esa manía y odio furibundo hacia esa instrucción?

Por una razón muy simple. Tu código no siempre es "definitivo". Cuando se crea una aplicación grande "seria", digamos que dedicas 3 meses a completarla. ¿Ya has terminado?

No, claro que no, esa aplicación probablemente requiera retoques en el futuro, ampliaciones, corregir potenciales errores que se te hayan colado, incluir nuevas características, etc.

E incluso es posible que quien haga esas modificaciones no seas tu, sino otra persona, y que a ti te toque modificar el código de otra persona.

Y aquí es donde se justifican esas cosas. Tu trabajarás siempre sobre ese código fuente. Si esta estructurado, es claro, documentado correctamente y sigue una serie de convenciones, tu trabajo será infinitamente mas sencillo y rápido. Si el código es confuso, con saltos incondicionales a punta pala, mal documentado (o sin comentarios), aunque el programa sea rápido, eficiente y haga lo que se espera de el, modificarlo será mucho mas difícil.

Es la diferencia entre trastear con un código claro, organizado y debídamente documentado, y trabajar con un código que no lo está. En un caso es fácil, en el otro no lo es en absoluto.

Y la verdad, las personas rara vez se acuerdan perfectamente de como funciona un código que hicieron hace meses, o años incluso.

Vamos, es como si tienes que revisar un libro, y este libro está bien organizado, tiene su indice general, indice de materias, etc... y sigue un orden lógico. El otro libro tiene las páginas al azar, con señales que indican a donde debes de saltar a cada momento, no tiene índice y además está escrito de forma poco clara.

Y no hay mas misterio
"When People called me freak, i close my eyes and laughed, because they are blinded to happiness"
Hideto Matsumoto 1964-1998

exploiterstack

#6
Por eso digo que es totalmente desaconsejado utilizar la instrucción goto, ya que puse solo uno de los motivos por los que no hay que acostumbrarse a utilizarlo.

Todos los que hemos estudiado programación sabemos que hay que evitar utilizar esa instrucción por x motivos entre ellos los que menciona Orubatosu de que raramente en una empresa seras el único en trastear el código fuente o por si en un futuro sera alguien el que se ara cargo, es aun dándoselo medio mascado con comentarios y con una buena costumbre de programación aun se le atraganta a mas de uno.

Haciendo uso de esa instrucción es una forma rápida de acceder a etiqueta que especifiques, no es cuestión de rapidez sino de como internamente trabaja. Te invito que a tu programa lo pases por un debugger. ves creando br(breakpoint) en la salida de cada instrucción goto y observa la ejecución sentencia por sentencia hasta que finalice el programa veras de lo que te hablo ;)

Te pongo por ejemplo lo que se menciona del código espageti, mira si haces un salto incondicional hacia una etiqueta estas rompiendo por completo lo que es la ejecución normal de cualquier programa estructurado ya que una vez se haya ejecutado el bloque de la etiqueta tienes que especificar de manera explicita por donde debería seguir la ejecución de la aplicación. Y para eso ya están las funciones ;)

Un saludo!

sabeeee

#7
¿Esto desestabiliza terriblemente mi código? Porque en linux que es un código de millones de lineas y que hay varios colaboradores tengo entendido hasta hace un par de años se utilizaba el goto, en realidad mi código es otro pero lo modifique como para hacer la pregunta, porque veo que es muy cuestionado sin argumentos realmente convincentes, tampoco lo vi que este en cosas que no se pueden hacer.
"Vengándose, uno iguala a su enemigo; perdonando, uno se muestra superior a él."
Francis Bacon

_Enko

#8
Destabilizar el codigo?

Esa afirmacion es bastante confusa.

Si con codigo estable se refiere a codigo que produce ejecutables estables... entonces goto no seria un problema alli siemper y cuando la ejecutable sea estable.

Ahora, si tienes algo asi:

if(blablabla())
  goto ALGUN_LUGAR_MUY_LEJANO_DE_AQUI;
/*
5.000 lineas de codigo mas abajo:
ALGUN_LUGAR_MUY_LEJANO_DE_AQUI:


Eso si seria molesto. Extremadamente molesto. Muy extremadamente molesto. Demasiado extremadamente molesto.

Si el goto salta 2,3 lineas... para que?  Si con sentencias de control tranquilamente se puede generar el mismo resultado.

No se me ocurre ningun caso donde un goto sea util. Es mas te digo, cuando se programa en ensamblador normalmente se utilizan saltos condicionales: jz, jnz, je, jne, etc...  Tranquilamente se puede programar evitando usar un salto incondicional (JMP) que seria el goto.

Es mas, el programa que usa goto esta desperdiciando bytes...
si pones algo como:

if(algo())
 goto ALGO;

estarias haciendo  algo asi:

  call algo
  test eax, eax
  jnz NEXT:
  JMP ALGO
NEXT:
  ;salida next


Mientras sin el goto, seria simplemente:

if(algo())
  algo2();

seria algo como

  call algo
  test eax, eax
  jnz NEXT
  call algo2
NEXT:


un JMP innecesario menos y no hay que volver a la prehistoria.


Citarya que puede darse el caso que instrucciones nunca se lleguen a ejecutar
eso no seria culpa del goto.

if(1==2){
codigo_que_nunca_se_va_a_ejecutar();
}


Saludos.


PD: una consulta...

Que pasa con C++,  destructores y goto?

{
  MYCLASS my_class; //se llamo al constructor
  goto AVOID_DESTRUCTOR
} //<< aqui la runtime llamaria al destructor del objeto my_class
AVOID_DESTRUCTOR:

O sea, lo entiendo bien? al usar un goto y salirse del scope, el destructor nunca seria llamado?

Acabo de hacer la prueba y el destructor es llamado... raro?

#include <iostream>
using namespace std;



class CClass {
public:
   ~CClass(){
       cout << "destructor" << endl;;
   }
   CClass(){
       cout << "constructor" << endl;
   }
};


int main(int argc, char *argv[]) {
   
   {
       CClass test;
       goto AVOID;
       
   }
AVOID:
   int i;
   cin >> i;
   return 0;
}

Orubatosu

A nivel de eficacia no tiene porque dar problemas. Que demonios, es una instrucción oficial de C++, debe de funcionar como se pretende.

Pero, no te va a aportar mas velocidad ni código mas eficiente. De manera que en realidad la cuestión es la que se te a comentado varias veces.

No se usa porque el código resultante puede ser confuso, sobre todo cuando la gente usa demasiado a menudo "goto" en lugar de usar otros mecanismos.

El problema real es que simplemente, la programación estructurada es mas simple, mas legible y mas fácil de mantener. El meter montones de saltos incondicionales no hace la programación mas sencilla (es hacer las cosas de otro modo). No hace el código mas legible, y no lo hace desde luego mas fácil de mantener.

De hecho incluso en lenguajes interpretados, donde muy teóricamente "goto" podría llegar a tener algún uso (echándole imaginación) se desaconseja energicamente su uso por todos los problemas antes comentados.

Si alguna vez has tenido que depurar un programa en BASIC, con docenas y docenas de saltos condicionales, incondicionales y otras lindezas, y te has vuelto majara intentando ver por donde narices anda la ejecución entenderás porque terminas odiando esa instrucción.

En C++ simplemente no tiene sentido, es innecesario su uso
"When People called me freak, i close my eyes and laughed, because they are blinded to happiness"
Hideto Matsumoto 1964-1998