[Ajuda] Por que nгo se deve usar o goto ?
#1

Eu estava dando uma olhada na wiki do SA-MP,e notei o goto,a wiki diz que nгo se deve usa-lo,mas nгo diz por que..

Caso alguйm puder explicar o motivo disso,eu ficaria grato.

E caso nгo seja incomodo,peзo tambйm alguns exemplos de uso do mesmo. (sem ser em loops,por favor)
Reply
#2

Boa leitura.
Reply
#3

Entгo nгo passa de um mito...

O uso do goto nгo traz prejuнzos,mais pode confundir programadores mais desatentos..

No caso,eu usei o goto para checagens,nгo hб como fechar um label,pelo menos,nгo de cara,entгo,eu suponho que,todos os labels devem ser colocados no final da callback para evitar conflitos e confusхes dentro do cуdigo:

PHP код:
public OnPlayerText(playeridtext[])
{
        
/*
            Let's try the basics,QUESTIONS.
        */
        
if(!strcmp(text[0],"How",true) && !strcmp(text[2],"can",true)) goto question_Handler;
        else if(!
strcmp(text,"Pilar",true) || !strcmp(text[0],"Pilar",true) && !strcmp(text[1],".",true)) goto conversation_Handler;
        
//Labels - Yes,I'm gonna try it.
        
question_Handler:printf("Pilar: %s made a question to me,can't answer because I'm not able to do that now."GetPlayerExactlyName(playerid));
        
conversation_Handler:printf("Pilar: %s is starting a conversation with me,I'm so nervous.."GetPlayerExactlyName(playerid));
        return 
1;

Ok,mas,e se eu passar pra uma outra linha e tentar continuar meu cуdigo fora da label ?

PHP код:
public OnPlayerText(playeridtext[])
{
        
/*
            Let's try the basics,QUESTIONS.
        */
        
if(!strcmp(text[0],"How",true) && !strcmp(text[2],"can",true)) goto question_Handler;
        else if(!
strcmp(text,"Pilar",true) || !strcmp(text[0],"Pilar",true) && !strcmp(text[1],".",true)) goto conversation_Handler;
        
//Labels - Yes,I'm gonna try it.
        
question_Handler:printf("Pilar: %s made a question to me,can't answer because I'm not able to do that now."GetPlayerExactlyName(playerid));
        
conversation_Handler:printf("Pilar: %s is starting a conversation with me,I'm so nervous.."GetPlayerExactlyName(playerid));
        
SendClientMessage(playerid, -1"Pilar: That's me,how can I help ?");
        return 
1;

No caso,ele vai continuar dentro da label,ou jб era ?
Porque se for,eu teria que fazer tudo inline,e isso nгo й uma boa coisa..
Reply
#4

Nesse caso, nгo й necessбrio usar goto. Vocк sу faz dar saltos desnecessбrios, o que pode consumir mais tempo de execuзгo.

PHP код:
if(!strcmp(text[0],"How",true) && !strcmp(text[2],"can",true)) printf("Pilar: %s made a question to me,can't answer because I'm not able to do that now."GetPlayerExactlyName(playerid));
        else if(!
strcmp(text,"Pilar",true) || !strcmp(text[0],"Pilar",true) && !strcmp(text[1],".",true)) printf("Pilar: %s is starting a conversation with me,I'm so nervous.."GetPlayerExactlyName(playerid)); 
Fora o que vocк chegou a ler no tуpico que linkei, eu recomendaria evitar o uso de goto. Nгo que ele traga malefнcios, mas que seu mal uso pode gerar problemas, fora a velocidade. Estamos tratando de uma linguagem imperativa, e dar "saltos" no cуdigo pode fugir um pouco deste conceito.
Reply
#5

Sim mas,se caso eu procure usar o goto em algo,como eu saberia que tudo que digitei depois do cуdigo que fora planejado para a label estaria fora da mesma ?

Й por isso que eu digo que pode ser melhor deixar as labels para o final da callback para garantir pelo menos que,elas serгo fechadas quando vocк fechar a callback.

PHP код:
public OnPlayerText(playeridtext[]) 

        if(!
strcmp(text[0],"How",true) && !strcmp(text[2],"can",true)) goto question_Handler
        else if(!
strcmp(text,"Pilar",true) || !strcmp(text[0],"Pilar",true) && !strcmp(text[1],".",true)) goto conversation_Handler;
        
question_Handler:
        
printf("Pilar: %s made a question to me,can't answer because I'm not able to do that now."GetPlayerExactlyName(playerid));
        
//Code stays on that label     -    O cуdigo abaixo deve continuar nessa label
        
SendClientMessage(playerid, -1"Pilar: That's me,how can I help ya ?");
        
//Another label to close the question label
        
conversation_Handler:
        
printf("Pilar: %s is starting a conversation with me,I'm so nervous.."GetPlayerExactlyName(playerid));
        
SendClientMessage(playerid, -1"Pilar: Yes ?");
        
//The next code can't be a part of the actual label
       //code...

EDIT: Serб que iria ser necessбrio fazer outra label para o resto do cуdigo ?

PHP код:
public OnPlayerText(playeridtext[]) 

        if(!
strcmp(text[0],"How",true) && !strcmp(text[2],"can",true)) goto question_Handler
        else if(!
strcmp(text,"Pilar",true) || !strcmp(text[0],"Pilar",true) && !strcmp(text[1],".",true)) goto conversation_Handler;
        else goto 
continueCode;    // <-----   No,just...no.
        
question_Handler:
        
printf("Pilar: %s made a question to me,can't answer because I'm not able to do that now."GetPlayerExactlyName(playerid));
        
//Code stays on that label     -    O cуdigo abaixo deve continuar nessa label
        
SendClientMessage(playerid, -1"Pilar: That's me,how can I help ya ?");
        
//Another label to close the question label
        
conversation_Handler:
        
printf("Pilar: %s is starting a conversation with me,I'm so nervous.."GetPlayerExactlyName(playerid));
        
SendClientMessage(playerid, -1"Pilar: Yes ?");
        
//The next code can't be a part of the actual label
        
continueCode:
       
//code...

Reply
#6

Eu nгo entendi muito bem onde deseja chegar, mas tenha em mente que goto serve para dar saltos no cуdigo.

Vejamos... Vocк tem todo um cуdigo estruturado, e deseja pular todo ele, ir direto para o final, vocк pode usar goto. No entanto, nгo й a melhor forma de se fazer isto. Vocк pode fazer com if, com switch(default), etc.
Reply
#7

Vamos dizer que,alguйm se interesse pelo goto,um scripter novato (ou um scripter cleo,eles tambйm usam goto,sу que lб,a funзгo se chama jump,mas isso nгo importa no momento),esse cara vai lб e usa o goto,cria suas labels normalmente,mas deixa todas elas no inнcio do script:

PHP код:
public OnPlayerConnect(playerid)
{
    new 
playerName[MAX_PLAYER_NAME];
    
GetPlayerName(playeridplayerNameMAX_PLAYER_NAME);
    
//Labels
    
PLAYER_ADMIN:
    new 
clientMessage[144];
    
format(clientMessage,sizeof clientMessage,"Administrador %s entrou no servidor.",playerName);
    
SendClientMessageToAll(-1,clientMessage);
    
    
PLAYER_NORMAL:
    new 
clientMessage[144];
    
format(clientMessage,sizeof clientMessage,"%s entrou no servidor.",playerName);
    
SendClientMessageToAll(-1,clientMessage);
    
    
//Checagens
    
if(IsPlayerAdmin(playerid)) goto PLAYER_ADMIN;//Pelo que sei,vocк pode entar como administrador inserindo a senha direto no launcher
    
else goto PLAYER_NORMAL;
    return 
1;

Esse й o problema Dolby,se vocк tentar compilar esse cуdigo,o compilador vai te dizer que a variavel clientMessage jб foi criada,mas como ela foi criada,sendo que a outra label nгo foi chamada para criar essa variavel antes ?

Isso pode ser um erro de interpretaзгo do compilador ou o goto nгo deve funcionar direito no caso,nгo hб como fecha-lo,e isso й um problema..
Reply
#8

Como as labels estгo acima do goto, o fluxo de execuзгo vai executa-las normalmente. Como eu disse, o goto faz apenas um pulo, ou seja, volta ou avanзa pra um determinado local do cуdigo, e nгo cria um "bloco de cуdigo".

Quem cria bloco de cуdigo й if.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)