Ir ao conteúdo

Posts recomendados

Postado

Quero fazer uma comparação de enquanto o numero de clientes não for um inteiro retorne sempre para o printf("Quantos clientes deseja cadastrar")

 

#include <stdio.h>

#include "cliente.c"

#include <stdlib.h>



<int main(void){

    int n; //Variável que determina o número de clientes a serem cadastrados

    printf("Quantos clientes deseja cadastrar? ");

    scanf("%d", &n);

    Cliente *clientes = (Cliente*) malloc(n * sizeof(Cliente)); //Alocação dinâmica do ponteiro clientes do tipo Cliente



    for(int i = 0; i < n; i++){

        printf("Informe o nome do cliente: ");

        scanf(" %[^\n]", clientes[i].nome); //Cadastro do nome do cliente

        getchar(); //Função para absorver o \n

        printf("Informe o endereço do cliente: ");

        scanf(" %[^\n]", clientes[i].endereco); //Cadastro do enedereço do cliente

        getchar();

        printf("informe o código do cliente: ");

        scanf("%d", &clientes[i].codigo_cliente); //Cadatro do código do cliente

        getchar();

    }



    atribuirDados(clientes, n);



    //CRIAR FUNÇÃO QUE APAGA O ARQUIVO TXT

    free(clientes); //Esvaziamento da memória alocada pelo ponteiro clientes



    return 0;

}>

 

  • Curtir 1
Postado

Você poderia fazer assim

    /* Pega a quantidade de clientes */
    do {
        printf("Quantos clientes deseja cadastrar?\n");
        fgets(buffer_teclado, TAMANHO_BUFFER, stdin);
        sscanf(buffer_teclado, "%i", &numero_clientes);
        /* Checa se o primeiro caractere é uma letra do alfabeto
         * isalpha e uma função que pertence a biblioteca ctype 
         */
        if (isalpha(*buffer_teclado)) {
            printf("Entrada Invalida!\n");
        }
    } while ((isalpha(*buffer_teclado) != 0) || (numero_clientes <= 0));

Checando toda vez se a entrada do teclado não começa com uma letra.

 

Quando for postar no fórum utilize o botão code e poste todos os arquivos do programa.

 

exemplo completo

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

#include "cliente.c"

#define TAMANHO_BUFFER 256

int main(void) {
    char buffer_teclado[TAMANHO_BUFFER];
    int
        numero_clientes = 0,
        contador;

    /* Pega a quantidade de clientes */
    do {
        printf("Quantos clientes deseja cadastrar?\n");
        fgets(buffer_teclado, TAMANHO_BUFFER, stdin);
        sscanf(buffer_teclado, "%i", &numero_clientes);
        /* Checa se o primeiro caractere é uma letra do alfabeto
         * isalpha e uma função que pertence a biblioteca ctype 
         */
        if (isalpha(*buffer_teclado)) {
            printf("Entrada Invalida!\n");
        }
    } while ((isalpha(*buffer_teclado) != 0) || (numero_clientes <= 0));
    
    //Alocação dinâmica do ponteiro clientes do tipo Cliente
    Cliente *clientes = malloc(sizeof(*clientes)*numero_clientes); 
    for (int contador = 0; contador < n; contador++) {
        //Cadastro do nome do cliente
        printf("Informe o nome do cliente: ");
        fgets(buffer_teclado, TAMANHO_BUFFER, stdin);
        buffer_teclado[strlen(buffer_teclado)] = '\0';
        strcpy(clientes[contador].nome, buffer_teclado);
        
        //Cadastro do enedereço do cliente
        printf("Informe o endereço do cliente: ");
        fgets(buffer_teclado, TAMANHO_BUFFER, stdin);
        buffer_teclado[strlen(buffer_teclado)] = '\0';
        strcpy(clientes[contador].endereco, buffer_teclado);
        
        //Cadatro do código do cliente
        printf("informe o código do cliente: ");
        fgets(buffer_teclado, TAMANHO_BUFFER, stdin);
        sscanf(buffer_teclado, "%i", &clientes[contador].endereco);
    }

    atribuirDados(clientes, numero_clientes);
    //CRIAR FUNÇÃO QUE APAGA O ARQUIVO TXT
    free(clientes); //Esvaziamento da memória alocada pelo ponteiro clientes 
    clientes = NULL;
    return(0);
}

 

  • Curtir 1
  • Obrigado 1
Postado

Quando postar um programa poste algo completo, que se possa compilar.

 

Deve imaginar que fica difícil ajudar sem ler o que tem em Cliente.h, certo?

 

Use o botão Code, como explicado no primeiro post desse forum.

 

  //CRIAR FUNÇÃO QUE APAGA O ARQUIVO TXT
    free(clientes); //Esvaziamento da memória alocada pelo ponteiro clientes

 

Mesmo ser ler cliente.h, dá pra entender que free(clientes) não cria uma função e nem apaga o arquivo txt. clientes é apenas uma estrutura alocada no início do programa, está na memória.

 

Entenda que scanf é um scanner, dá pra ver pelo nome. scanf (e fscanf e sscanf) tentar ler (scan) algo da entrada a partir dos especificadores. Essas funções retornam um int com o número de valores que conseguiu ler. Pode não ler nada e não é um erro. Veja o manual: se retornar zero é porque não leu nada e essa é a resposta para sua pergunta.

 

Em 21/02/2024 às 13:53, kgin disse:
//Alocação dinâmica do ponteiro clientes do tipo Cliente
    Cliente *clientes = malloc(sizeof(*clientes)*numero_clientes); 

 

O ponteiro já foi alocado, estáticamente. O que está alocando aí é uma area, O tamanho dela é a expressão que passou para malloc. malloc() retorna um endereço, que será atribuido ao ponteiro, estático clientes, cujo tipo é Cliente* como seu compilador ou IDE pode mostrar. malloc() retorna void* então pode atribuir a qualquer ponteiro.

 

 

        fgets(buffer_teclado, TAMANHO_BUFFER, stdin);
        sscanf(buffer_teclado, "%i", &numero_clientes);
        /* Checa se o primeiro caractere é uma letra do alfabeto
         * isalpha e uma função que pertence a biblioteca ctype 
         */
        if (isalpha(*buffer_teclado)) {
            printf("Entrada Invalida!\n");
        }

 

Isso está errado

 

fgets() pode não ler nada e é por isso que retorna um NULL se não ler nada ou o endereço do buffer se leu algo. Só que o programa não testa. Todo dia programas de iniciantes entram em loop por esse erro: coninuam rodando com os valores que já estavam em buffer_teclado quando fgets() não lê nada.

 

sscanf() com % tenta ler um int. Se nã ler retorna zero. Só que não testou então não adianta nada

 

E aí volta a testar *buffer_teclado para ver se é uma letra? Então porque não usa atoi() siimplesmente, em *buffer_teclado? 

 

Em 21/02/2024 às 13:53, kgin disse:
 int
        numero_clientes = 0,
        contador;

 

Evite declarar mais de uma variável por linha. Linhas são grátis.

 

E evite usar int para valores que não podem ser negativos, porque é mais uma coisa prá testar sem necessidade. Seu insrutor pode digitar -42 para o número de clientes e aí seu programa já era. Use unsigned.

 

 

Em 21/02/2024 às 13:02, clara leal disse:

Cliente *clientes = (Cliente*) malloc(n * sizeof(Cliente)); //Alocação dinâmica do ponteiro clientes do tipo Cliente

 

Entenda que está declarando aí uma variável: clientes.

 

Em C variáveis tem um tipo. Qual o tipo de clientes? clientes é Cliente*.

 

É isso que está declarando.

 

Espaços não fazem diferença em C. O compilador não se importa.

 

Mas se declara 

 

	char** ** coisa = NULL;

 

Isso quer dizer que

 

	***coisa é do tipo char*
	**coisa é to tipo char**
	*coisa é do tipo char***
	coisa é do tipo char****

 

Isso é C. Isso se chama dereference, de-referência. Cada asterisco à esquerda usa o valor apontado para o ponteiro, como uma variável do tipo ao qual ele aponta. 

 

EXEMPLO

 

Considere esse programa

 

#include <stdio.h>
int main(void)
{
    int* p     = NULL; // não aponta para nada
    int  algum  = 30;
    int  valor = 42;
    p          = &algum;
    printf("*p = %d, valor = %d\n", *p, valor);
    valor = *p; 
    printf("*p = %d, valor = %d\n", *p, valor);
    p = &valor;  
    printf("*p = %d, valor = %d\n", *p, valor);        
    return 0;
}

 

E a saída

 

*p = 30, valor = 42
*p = 30, valor = 30
*p = 30, valor = 30

 

E acompanhe o efeito dos operadores * e &. É essencial em C

 

Porque estou escrevendo isso? 

 

Veja as declarações abaixo

 

 

    int*                p1    = &valor;
    int                 *p2   = &valor;
    int*p3=&valor;
    int                 *  p4 = &valor;

 

p1 p2 p3 e p4 são ponteiros para int, apontam para o mesmo lugar e as declarações são equivalentes. Mas só a primeira expressa a realidade de imediato para quem está lendo isso.

 

De todo modo quem decide é sempre a empresa ou a instituição: empresas e escolas tem regras para código, alinhamento, posição de chaves e parenteses, nomenclatura, máximo de linhas por função, o 😈

  • Curtir 1
Postado

Olá!

Em 21/02/2024 às 13:02, clara leal disse:

Quero fazer uma comparação de enquanto o numero de clientes não for um inteiro retorne sempre para o printf("Quantos clientes deseja cadastrar")

    Suponho haver semelhança entre o queres e o que necessitas.
    
    Portanto…
    Há necessidade (duma informação), sendo ela um elemento no
    conjuntos dos números inteiros positivos (Z+).
    
    Daí…
    Essa analise superficial foca numa variável de controle,
    porque, interessa-nos, talvez, o valor nela e não noutra.
    
    Logo…
    Parafraseando-se tua indagação, mais exemplo de interação
    num caso de uso comum; expressamos o código-fonte assim:

 

 

C'11 in GCC

/* main.c --- Uma exemplificação duma variável de controle
    
    
    @ESPECIFICAÇÃO
     Exemplificação e verificação de user-prompt da informação
    
     [#] Agora para continuar com essa operação,
     diga-nos A QUANTIA de fichas Cliente"s no cadastramento.
    
     (0 = anulará operação)? 
    
    '''BUGs:
    Caso falhem -especificamente- na informação (digitação),
    imprima-se:
    
     [!] erro--- quantia inválida.
     *sendo 'erro' aquela string faltosa.
    
     e repetir.
    
    
    @EXPRESSÃO
     C'11 into GCC 5.2.0 ***
     by Mauro B.
     2024-2 */

#include <stdio.h>


int main(void) {

    int nfichas = (-1); /* sendo quantia de f- Cliente no cadastramento */
    char prompt [BUFSIZ]; /* sendo mediador de tipos no cadastramento */
    
    
    /* Como na interação user-prompt ... */
    printf ("%s", "[#] Agora para continuar com essa operação,\n"
     "diga-nos A QUANTIA de fichas Cliente's para cadastramento.\n\n");
    
    
    for (;
        printf ("%s", "(0 = anulará operação)? "),
        fgets (prompt, BUFSIZ - 1, stdin),
        sscanf (prompt, " %i", &nfichas),
        (nfichas <= 0)
        ;)
        
        if (nfichas) /* SE difere do 0 */
            printf ("[!] %s--- quantia inválida.\n"
             "Dê-me quantia >= 0.\n\n", prompt),
            prompt [0] = '\0';
            
        else /* SE 0 */
            return (-1); /* retonar status FAILURE */
    
    
    return 0;
}   /* retornar status SUCCESS */

 

 

Ilustração no MS Windows

image.png.37e576c2cc7a109da02f31f3371788c0.png

 

 

— Note a expressão / sentença para inteiro positivo (Z+) ou zero, onde qualquer diferente, hipoteticamente, será FALHA e continuará no seu laço.

Isso talvez inspire uma expressão para o teu problema @clara leal

  • Obrigado 1
Postado
Em 25/02/2024 às 14:19, mauro_b disse:
    for (;
        printf ("%s", "(0 = anulará operação)? "),
        fgets (prompt, BUFSIZ - 1, stdin),
        sscanf (prompt, " %i", &nfichas),
        (nfichas <= 0)
        ;)
        
        if (nfichas) /* SE difere do 0 */
            printf ("[!] %s--- quantia inválida.\n"
             "Dê-me quantia >= 0.\n\n", prompt),
            prompt [0] = '\0';
            
        else /* SE 0 */
            return (-1); /* retonar status FAILURE */

 

Um comando for tem 3 partes.Todas as 3 são opcionais. 

 

No programa acima só se usa a segunda parte, o teste, e assim é algo como

 

	for ( ; condicao ; ) { /* comandos */ }

 

e a tal condição será simplesmente 

 

    for (; nfichas <= 0; )

 

 

 

isso pelo uso folclórico do operador `,`, vírgula, que faz com que todos os comandos da lista sejam executados, e o resultado da expressào seja o resultado do último comando. Nesse caso a lista

 

          printf ("%s", "(0 = anulará operação)? "),
          fgets (prompt, BUFSIZ - 1, stdin),
          sscanf (prompt, " %i", &nfichas),
          (nfichas <= 0)

 

E nenhum comando foi usado, e a llista completamente omitida. Isso quer dizer que esse for não tem comandos, nem inicializaçao nem incremento.

 

Talvez pudesse escrever assim

 

    for (
		;
        printf ("%s", "(0 = anulará operação)? "),
        fgets (prompt, BUFSIZ - 1, stdin),
        sscanf (prompt, " %i", &nfichas),
        (nfichas <= 0)
        ;
    )   {};

 

Ao menos para deixar claro que é de propósito que não há comandos.

 

É válido programar assim, mas provavelmente não faria bem para sua nota ou seu emprego. E nem para quem viesse depois de você trabalhar com esse tipo de programa. Ou mesmo para você daqui uma semana.

 

De todo modo está errado.

 

Note o que eu escrevi na resposta anterior:

 

Em 23/02/2024 às 11:56, arfneto disse:

fgets() pode não ler nada e é por isso que retorna um NULL se não ler nada ou o endereço do buffer se leu algo. Só que o programa não testa. Todo dia programas de iniciantes entram em loop por esse erro: coninuam rodando com os valores que já estavam em buffer_teclado quando fgets() não lê nada.

 

sscanf() com % tenta ler um int. Se nã ler retorna zero. Só que não testou então não adianta nada

 

Pois é.

 

Se 

 

        fgets (prompt, BUFSIZ - 1, stdin),


fgets não ler nada o valor de prompt fica inalerado e sscanf vai ler sempre a mesma coisa. Teste o retorno.

 

        sscanf (prompt, " %i", &nfichas),

 

E se sscanf não ler nada nfichas vai ficar com o valor de antes. Teste o retorno

 

	(nfichas <= 0)

 

E ESSE VALOR NÃO VAI MUDAR NUNCA, ENTÃO O PROGRAMA NÃO VAI TERMINAR NUNCA...

 

Sobre isso:

 

Em 25/02/2024 às 14:19, mauro_b disse:
       if (nfichas) /* SE difere do 0 */
            printf ("[!] %s--- quantia inválida.\n"
             "Dê-me quantia >= 0.\n\n", prompt),
            prompt [0] = '\0';
            
        else /* SE 0 */
            return (-1); /* retonar status FAILURE */

 

Tmbém não faira nada bem para sua nota ou emprego:

 

Sempre teste antes a condição definitiva, e não use else para um return. Não precisa desses parenteses: -1 é o mesmo que (-1) ou (((-1)))

 

Em C 0 é falso, todo o resto é verdadeiro. Por isso pode usar 

 

       if (nfichas) /* SE difere do 0 */

 

Mas se usa o teste sem o sinal é porque sabe o que (nfichas) é a mesma coisa que (nfichas == 0), e então não precisa do comentário "Se difere do 0". Mas se vai colocar o comentário é muito mais simples usar o óbvio

       if (nfichas != 0)

 

Prefira

 

       if ( nfichas == 0) return -1;
       printf ("[!] %s--- quantia inválida.\n"
       "Dê-me quantia >= 0.\n\n", prompt),
       prompt [0] = '\0';

 

Mas considere que esse printf com metade da mensagem no argumento e mensagem como uma string constante e usada uma única vez também é dispensável:

prefira

 

       printf ("[!] Dê-me quantia >= 0.\n\n%s--- quantia inválida.\n");
// ou
	  printf ("%s\n", "[!] Dê-me quantia >= 0.\n\n%s--- quantia inválida.\n");

 

E considere que '\0' é a mesma coisa que 0. E colocar um zero na primeria posição de prompt de nada vai servir no programa. 

 

 

  • Curtir 1
Postado
6 horas atrás, arfneto disse:

É válido programar assim, mas provavelmente não faria bem para sua nota ou seu emprego. E nem para quem viesse depois de você trabalhar com esse tipo de programa. Ou mesmo para você daqui uma semana.

 

De todo modo está errado.

Se diz provavelmente, então prove...

Contudo, tuas opiniões (comentário mínimo) talvez ajude outro alguém… (senão tanto faz)

 

 

6 horas atrás, arfneto disse:

não precisa do comentário "Se difere do 0". Mas se vai colocar o comentário é muito mais simples usar o óbvio

Devemos e podemos COMENTAR TUDO.; até expressões simples e quem diz o contrário, quase sempre tem pouco ou quase nenhuma autoridade.

Se estou errado, prove!

 

Ex:

c = a + b;
/*c sendo soma de a e b */

 

c = a + b; /*c sendo soma de a e b */

— Excelentes Programadores \ professores \ tutores \ iniciantes com um pouco de experiência e até mesmo IA sabem ignorar esses comentários, independentemente de que os escreveu.

 

 

De todo modo, agradeço à tentativa!

  • Obrigado 1
Postado

@clara leal , Olá (outra vez), por motivos didáticos acrescentarei a mensagem (exemplificação) que, talvez, reforça a percepção de que o cerne não são os números inteiros (Z), porém -especificamente- os positivos (Z+).

 

 

C'11 in GCC

/* main.c --- Uma exemplificação duma variável de controle
    
    
    @ESPECIFICAÇÃO
     Exemplificação e verificação de user-prompt da informação
    
     [#] Agora para continuar com essa operação,
     diga-nos A QUANTIA de fichas Cliente"s no cadastramento.
    
     (0 = anulará operação)? 
    
    @BUGs
    Caso falhem -especificamente- na informação (digitação),
    imprima-se:
    
     [!] erro--- quantia inválida.
     *sendo 'erro' aquela string faltosa.
    
     e repetir.
    
    
    @EXPRESSÃO
     C'11 into GCC 5.2.0 ***
     by Mauro B.
     2024-2 v2 */

#include <stdio.h>


int main (void) {


    int nfichas = (-1); /* sendo quantia de f- Cliente no cadastramento */
    char prompt [BUFSIZ]; /* sendo mediador de tipos no cadastramento */
    
    
    /* Como na interação user-prompt ... */
    printf ("%s", "[#] Agora para continuar com essa operação,\n"
     "diga-nos A QUANTIA de fichas Cliente's para cadastramento.\n"
     "\n");
    
    
    for (;
        printf ("%s", "(0 = anulará operação)? "),
        fgets (prompt, BUFSIZ - 1, stdin),
        sscanf (prompt, " %i", &nfichas),
        (nfichas <= 0)
        ;)
        
        if (nfichas) /* SE difere do 0 */
            printf ("[!] %s--- quantia inválida.\n"
             "Dê-me quantia >= 0.\n\n", prompt);
            
        else /* SE 0 */
            return (-1); /* retonar status FAILURE */
    
    
    printf ("%s%d%s", "[#] Informou-nos A QUANTIA de: ", nfichas, " fichas.\n"
     "\n");
    
    
    return (0);
}   /* retornar status SUCCESS */

 

 

Ilustração in MS Windows

image.png.564dea4438668f076ddf43ae081a3c0e.png

 

 

— Numa situação de uso comum, hipoteticamente, o laço encerra na informação de inteiro positivo ou 0 encerra.

Entendeu-me nessa lógica /expressão ?

 

  • Obrigado 1
Postado

@mauro_b como te disse, seu programa tem erros e vai entrar em loop

 

concentre-se no fato de que fgets retorna um ponteiro e imagine que tenha uma razão para isso. Leia o manual. Não vou provar nada. Entenda que seu programa entra em loop se fgets não ler nada

 

concentre-se no fato de que sscanf retorna um int com o total de especificadores lidos e imagine que  tenha uma razão para isso. Leia o manual. Não vou provar nada. Entenda que seu programa entra em loop se sscanf não escanear nada

 

quanto ao estilo e opções de código, não pretendi te ofender ou criticar e me desculpo se dei essa impressão. Não trabalha pra mim tampouco sou seu instrutor. Apenas levantei essas coisas porque escreveu em um forum público e esses erros e práticas podem levar outros usuários a problemas, outros usuários que se reportem a chefes ou comites de revisão de código e que não tenham sua "liberdade de estilo". E outros que possam perder tempo por não observar o simples funcionamento de fuinções básicas em C.

 

Todos os dias programas de iniciantes e profissionais entram em loop ou cancelam por essas razões.

  • Obrigado 1
Postado

Você tem ideia da razão de fgets() retornar char*?

 

Você tem ideia da razão de sscanf() retornar int?

 

Acha mesmo que pode desprezar esses valores sem qualquer consequência?

  • Curtir 1
Postado

@clara leal     para fazer uma validação do que foi digitado , você pode usar uma string para pegar os dados , pois a string aceita qualquer caractere, e depois converter essa string em um número inteiro "int"  usando para isso a função atoi que verifica se os caracteres iniciais da string são numéricos  (de 0 a 9) , até encontrar um caractere que não seja numérico . e converte a parte válida . e se não houver nenhuma parte válida retorna zero mesmo   .

#include    <stdio.h>
#include    "cliente.c"
#include    <stdlib.h>
char ax[10] = "";
int  ret    =  0;
int  n      =  0;
FILE* arq = fopen("Clientes.txt","w"); /// cria e reseta / Deleta o arquivo
do                                     /// para escrever desde o inIcio dele
{
  printf("Quantos clientes deseja cadastrar? ");
  ret = scanf("%s" , ax );             /// se leu algo o valor de ret será maior que zero
  n = atoi(ax);                        /// se digitou caracteres numericos no inicio
  printf("val AX --= %s\n"             /// converte para int senAo a variAveL n recebe zero
         "val RET -= %d\n"             /// aqui apenas p/ ver o que foi digitado
         "val N ---= %d\n",
         ax , ret , n    );
}while( ret == 0 || n == 0 );
Cliente* clientes = (Cliente*) malloc( n * sizeof(Cliente)); /// Alocação dinâmica do ponteiro clientes do tipo Cliente

 

  • Curtir 1
  • Obrigado 1
Postado

Uma alternativa é fazer um loop infinito com break no caso da entrada válida,

 

while(1){
    printf("Quantos clientes deseja cadastrar? ");
    if(scanf("%d", &n)){
        break;
    }
    while(getchar() != '\n');
}

 

  • Obrigado 2
Postado

Erros Internos associados ao fluxo (Input/Output)

nos são irrelevantes na compreensão da Lógica, é por esse motivo que, consideramos certas as expressões de @Midori @devair1010  

 

Checar os estados dos fluxos padrões, por exemplo, com uso da função 'ferror', pouco ou quase nada adicionará as suas lógicas / expressões.

 

Sendo mais didático, por exemplo: no caso da expressão do @Midori há pequeníssima possibilidade de ficarmos presos num laço infinito, bem ali, na expressão que nos aponta um descarregar do fluxo de entrada (padrão):

while(getchar() != '\n');

 

# Um tratamento de erro

while (getchar () != '\n' && ferror (stdin) == 0)
	;

 

Se, potencialmente, a getchar indicasse erro, veríamos o laço sem fim; apesar de tratável, o tratamento é irrelevante na compreensão dessa expressão, de sua lógica e entendimento.

  • Obrigado 1
  • 2 semanas depois...
Postado
Em 28/02/2024 às 15:27, Midori disse:
while(1){
    printf("Quantos clientes deseja cadastrar? ");
    if(scanf("%d", &n)){
        break;
    }
    while(getchar() != '\n');
}

 

3 horas atrás, devair1010 disse:

sim , realmente ,  creio que nunca haverá erro nesse caso , pois o último caractere sempre será o '\n' , já que a tecla "Enter" é que finaliza as entradas .

 

Sim, @devair1010 pode haver erro e pode sim entrar em loop. Está lendo menos do que tem no programa.

 

Em C só zero é falso.

 

Condições implícitas deveriam ser evitadas, especialmente em programas de ou para iniciantes. Essa linha

 

	if(scanf("%d", &n))

 

Significa

 

	if(scanf("%d", &n) != 0)

 

Isso quer dizer que se scanf() der erro vai sair do loop. Isso porque se der erro scanf() retorna -1 que não é ZERO. O retorno de scanf() deve ser comparado com o numero de especificadores. Esse é um erro comum, uma mania que afeta estudantes, instrutores e profissionais. Teste se scanf() retornou 1 porque só tem um especificador e é o que importa: tem um valor para n ou não. E mesmo assim se n for zero provavelmente deveria continuar no loop.

 

Se scanf() der erro provavelmente getchar() vai dar erro tambem. E adivinhe o que ela vai retornar? -1

 

E aí vai ficar assim por toda a eternidade.

 

Esse é um erro comum. Pode demorar pra acontecer, mas errado está. Sugiro fazer o simples. Sempre. Imagine que está usando a entrada a partir de um arquivo, tipo 

 

	programa < X:entrada.txt

 

Em Windows. Se X for um pen-drive e você desconectar o drive com o programa rodando, parado lá no prompt do scanf() o que vai acontecer?

 

 

  • Obrigado 1
Postado
14 horas atrás, devair1010 disse:

@mauro_b    sim , realmente ,  creio que nunca haverá erro nesse caso , pois o último caractere sempre será o '\n' , já que a tecla "Enter" é que finaliza as entradas .

Claro, e qual é probabilidade de erro nessa situação? Dum erro que é quase inexistente.

 

Entretanto,

culturalmente essa expressão vem com mais uma sentença -- c != EOF

Ex.

/*Um discarte mais seguro da linha*/


int c = 0;
//isso declara a palavra auxiliar no discarte */

while (c != '\n' && c != EOF)
/*isso expressa um discarte mais seguro da linha (por ciclo)
enquanto a palavra diferir de 'ENTER' e EOF */
        c = getchar ();
        //isso pega uma palavra (int) na linha 

 

É mais ou menos assim que os manuais expressão essas coisas, né? Para lógica não faz diferença, não é erro, com ou sem o tratamento.

  • Obrigado 1
Postado

 

 

Não são erros internos. São externos. O Input de Input/Output. Uma situação comum é, como eu expliquei, a entrada padrão estar redirecionada para um arquivo e ele dar erro. Pode ser por exemplo que o instrutor tenha um arquivo de entrada para teste, em um endereço de rede na própria escola. E usa esse arquivo para testar os programas dos alunos. Bem na hora do teste dá um erro ---ou o instrutor provoca um erro de propósito --- só para ver se o aluno tinha testado isso... Alguns não tinham testado porque acharam irrelevante... 

 

Em 15/03/2024 às 22:04, Ansi C disse:

Entretanto,

culturalmente essa expressão vem com mais uma sentença -- c != EOF

 

Não é uma questão cultural: se scanf() falhar getchar() provavelmente vai falhar também, no trecho em questão. E o programa vai entrar em loop, quer o aluno entenda a lógica ou não.

 

Em 15/03/2024 às 22:04, Ansi C disse:
palavra auxiliar no discarte

 

traduzir WORD por "palavra auxiliar" está ok, um pouco rebuscado talvez. Apenas int já seria a precisa descrição da variável:
 

 	int c = 0;

 

E a grafia correta é "descarte" , no entanto.

 

Sobre a pergunta inicial

 

Em 21/02/2024 às 13:02, clara leal disse:

Quero fazer uma comparação de enquanto o numero de clientes não for um inteiro retorne sempre para o printf("Quantos clientes deseja cadastrar")

 

A linguagem tem um comando para isso: while e uma condição para isso: >0

 

Seria natural que essa determinação fosse de um valor não negativo e fosse algo assim então:
 

	int n = 0;
	while (< 1)
	{
      	//tenta ler
	}
            


Sim, n deveria ser unsigned.

 

Sobre esses programas interativos
 

Num programa interativo comum, que vá ser usado por outros que não só o autor até entregar e esperar a nota, o normal é ler as teclas diretamente, sem mostrar na tela nem mover o cursor, e conforme o cara vai digitando números (e só nesses casos) se mostra o número que o cara digitou, até o limite estabelecido de dígitos. 

 

Um número negativo não faz sentido, então n deveria ser unsigned. O total de clientes não poderia ser da ordem de centenas então 2 dígitos estariam bem. Zeros a esquerda seriam descartados... Sim, é um porre escrever programas interativos.

 

E sempre tem que ter uma maneira de cancelar.

 

E nunca se pede antes o total, apenas DEPOIS se tem mais... 

 

Se o cara diz que vai entrar com 8, entra com 6 e descobre que não tem os dados dos outros 2, ou se ele já digitou 5 de 8 e descobre nessa hora que são 9, ele vai ficar muito furioso com quem escreveu um programa que espera o total ANTES.

 

Ninguém faz isso, só os instrutores de linguagens criam essas maravilhas.

 

Um exemplo trivial

 

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int n = 0;
    while (n < 1)
    {
        char linha[20] = {0};
        printf("\n\
        [tecle ENTER para cancelar]\n\
        Total de clientes a cadastrar: ");
        char* p   = fgets(linha, sizeof(linha), stdin);
        if (*p == '\n') break;
        n = atoi(p);
        if (n < 1) continue;
        printf("\n\tTotal de %d clientes\n", n);
        return 0;
    }   // while()
    printf("\n\tCancelado!\n");
    return -1;
}

 

Que mostra por exemplo

 

        [tecle ENTER para cancelar]
        Total de clientes a cadastrar: Forum CDH
        
        [tecle ENTER para cancelar]
        Total de clientes a cadastrar: -123
        
        [tecle ENTER para cancelar]         
        Total de clientes a cadastrar: xyz   
        
        [tecle ENTER para cancelar]         
        Total de clientes a cadastrar: 0   
        
        [tecle ENTER para cancelar]         
        Total de clientes a cadastrar: 12
        
        Total de 12 clientes

 

ou

 

	[tecle ENTER para cancelar]
	Total de clientes a cadastrar:
    
	Cancelado!

 

Se o cara teclou enter.

 

Assim aceita ENTER para cancelar, rejeita letras, 0,  e valores negativos e tal.

 

 

  • Obrigado 2

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!