Errei em alguma coisa? [RESOLVIDO]

1. Errei em alguma coisa? [RESOLVIDO]

Pangas Millenium
Lerub

(usa Debian)

Enviado em 17/07/2013 - 05:14h

Estoou fazendo um curso de C e estou na seção sobre vetores e matrizes. Compilei um código e executei o programa, mas ao executar o mesmo só aparece um monte de simbolos aleatórios.

Segue-se o código.

#include <stdio.h>
void StrCpy (char *destino,char *origem)
{
while (*origem)
{
*destino=*origem;
origem++;
destino++;
}
*destino='{TTEXTO}';
}
int main ()
{
char str1[100],str2[100],str3[100];
printf ("Entre com uma string: ");
gets (str1);
StrCpy (str3,"Você digitou a string ");
printf ("\n\n%s%s",str3,str2);
return(0);
}



  


2. Re: Errei em alguma coisa? [RESOLVIDO]

???
gokernel

(usa Linux Mint)

Enviado em 17/07/2013 - 07:03h

Olá !

str2 e str3 não foram zeradas/inicializadas, portanto pode conter lixo de memória por ser essas variaveis locais.

Em variáveis globais não teriam esses "problemas".

Forma de zerar:
char str1[100] = {0}; // str2, str3 ... bla bla bla

ISAIAS 1:19:
"Se quiserdes, e ouvirdes, comereis o bem desta terra."


3. Re: Errei em alguma coisa? [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 17/07/2013 - 07:36h

Não faltou um StrCpy(str2, str1); em algum lugar, não?


4. Re: Errei em alguma coisa? [RESOLVIDO]

Uilian Ries
uilianries

(usa Linux Mint)

Enviado em 17/07/2013 - 10:17h

Force o esvaziamento do buffer de entrada antes de capturar com o gets(não recomendado, ver man gets)



#include <stdio_ext.h>

int main ( void )
{
.
.
.
__fpurge(stdin);
gets();
}




5. Re: Errei em alguma coisa? [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 17/07/2013 - 11:33h

É correto advertir contra o uso de gets(), que é uma função tão ruim e insegura que foi removida da revisão de 2011 do padrão da linguagem C.

Só que o problema em questão não é lixo no buffer. Mesmo que fosse, como __fpurge() não é uma função da biblioteca padrão, mas é específica do Linux, seria melhor adotar uma solução mais genérica de lidar com o problema. Por mais que este site seja o Viva o Linux, parte do público desta comunidade de C e C++ usa Windows ou outros sistemas (BSD, OSX, Solaris, AIX etc.).

Pode ser uma opinião pessoal minha, mas eu valorizo a portabilidade das soluções. Em geral, e na medida do possível, eu prefiro usar primeiro a biblioteca padrão, depois o que for POSIX, depois o que for BSD, depois o que for só GNU, depois o que for só Linux, depois o que for específico de uma única distribuição ou de determinada versão, e por último o que só funciona na minha máquina, com a minha configuração.


6. Re: Errei em alguma coisa? [RESOLVIDO]

Pangas Millenium
Lerub

(usa Debian)

Enviado em 17/07/2013 - 13:51h

paulo1205 escreveu:

É correto advertir contra o uso de gets(), que é uma função tão ruim e insegura que foi removida da revisão de 2011 do padrão da linguagem C.

Só que o problema em questão não é lixo no buffer. Mesmo que fosse, como __fpurge() não é uma função da biblioteca padrão, mas é específica do Linux, seria melhor adotar uma solução mais genérica de lidar com o problema. Por mais que este site seja o Viva o Linux, parte do público desta comunidade de C e C++ usa Windows ou outros sistemas (BSD, OSX, Solaris, AIX etc.).

Pode ser uma opinião pessoal minha, mas eu valorizo a portabilidade das soluções. Em geral, e na medida do possível, eu prefiro usar primeiro a biblioteca padrão, depois o que for POSIX, depois o que for BSD, depois o que for só GNU, depois o que for só Linux, depois o que for específico de uma única distribuição ou de determinada versão, e por último o que só funciona na minha máquina, com a minha configuração.


Ok então. Bem que aquele curso já está utrapassado mesmo. É provável que seja do começo dos anos 2000 (ou dos anos 90s). Rastreei com a ferramenta do Google em um servidor de uma faculdade brtasileira. Enfim... vou deletar aquele curso e procurar outro.


7. Re: Errei em alguma coisa? [RESOLVIDO]

Uilian Ries
uilianries

(usa Linux Mint)

Enviado em 17/07/2013 - 14:04h

Paulo,

Eu também valorizo e muito a questão de portabilidade.

Geralmente eu utiliza fflush.
Uma questão que não descobri e talvez você saiba responder.
No Windows eu conseguia descarregar o buffer usando o fflush, porém no Linux eu tive vários problemas, onde o lixo sempre permanecia.
Tentei também fpurge, mas ocorreu no mesmo resultado.
A única chamada que consegui utilizar e funcionou na época foi o __fpurge, o que utilizo até hoje por este histórico.


8. Re: Errei em alguma coisa? [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 17/07/2013 - 15:16h

Que eu saiba -- pelo menos pelo que diz a manpage -- o famigerado fflush(stdin) passou a funcionar nas versões mais recentes da glibc, com o mesmo comportamento que tinha no DOS e Windows. Calculo que essa conversão foi feita por conveniência de ajudar quem está chegando ao C no Linux vindo do Windows, ou usando material didático escrito com os compiladores para MS-DOS em mente -- até porque tal comportamento não contraria o padrão, mas apenas o estende.

Eu sou um usuário histórico de BSDs que hoje usa Linux no trabalho por necessidade e em casa por conveniência (especificamente, a conveniência de ter plugins para o Firefox, e mais recentemente para poder usar o Steam no Linux, em vez de no Windows). Nos BSDs, fflush() continua definida apenas para streams de saída, com um sentido não de descartar, mas de efetivar as alterações feitas nesses streams, garantindo que irão dos buffers locais para o local de armazenamento permanente. Quando alguém quis uma função para descartar dados, teve a prudência de lhe dar outro nome (fpurge(), no caso dos BSDs, que foi inicialmente importada para o Linux com o mesmo nome, e depois renomeada no Linux para __fpurge()).

Eu considero essa abordagem correta por causa de duas oposições de sentido: do sentido da orientação (escrita × leitura, ou "indo para o disco" × "vindo do disco") e do sentido semântico (preservar × descartar). A escolha do mundo DOS/Windows, seguida depois pelo GNU, é muito mais arbitrária e, por conta das oposições de sentido que mencionei, muito mais difícil de justificar filosoficamente. Mas não pode ser considerada errada, já que não descumpre o que o padrão prescreve, mas somente o estende num aspecto em que ele não diz coisa alguma.

Mas independentemente da minha opinião sobre as duas abordagens, não uso mais qualquer uma delas em qualquer programa meu: fflush(stdin) hoje passou a funcionar no Linux, mas continua (e espero mesmo que continue) a não funcionar no BSD, e fpurge() sequer existe no Linux ou no mundo Microsoft.

Como eu disse antes, eu prefiro ficar dentro do que o padrão prescreve. Então, se eu quiser pular espaços na leitura de dados, eu vou especificamente escrever código padrão que deixe isso bem claro. Não é tão difícil. Quando uso C, existem várias técnicas que eu uso:

* Ler sempre linhas inteiras com fgets(), e pular os eventuais espaços no início da string antes de copiar os dados para o array de caracteres onde eles ficarão definitivamente guardados, suprimrindo também, no momento da cópia, eventuais espaços no final da linha.

* Em linhas com múltiplos dados pre-formatados, ler linhas inteiras com fgets() para um buffer intermediário, e extrair desse buffer os campos de interesse usando sscanf(). Isso tem a vantagem, se comparado com usar diretamente scanf(), de que linhas que eventualmente não estejam no formato esperado não vão deixar o stream de entrada num estado inconsistente, e fica fácil fazer outras tentativas de extração dos campos desejados com outras strings de formatação, e até mesmo identificar e descartar informação não desejada.

* Usar strings de formatação mais seguras (e complexas) na própria scanf(). Em particular, essas strings raramente usam "%s", mas em seu lugar ocorrem espaços e "%[...]".

* Ler caráter a caráter com fgetc().


9. Re: Errei em alguma coisa? [RESOLVIDO]

Uilian Ries
uilianries

(usa Linux Mint)

Enviado em 17/07/2013 - 15:42h

Obrigado pela resposta!

Isso me ajudou muito.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts