Ir ao conteúdo

Posts recomendados

Postado

Preciso de um programa para cadastrar placa de um veículo, onde:

- A PLACA DEVE TER O FORMATO XXX9999, onde XXX são letras e 9999 DIGITOS

-Se o usuário digitar no formato errado deve voltar

- NÃO PODE EXISTIR 2 PLACAS IGUAIS

Alguém bom em linguagem c pode ajudar? :)

  • Obrigado 1
  • Membro VIP
Postado

Dica: mostre o que você já fez, o que tentou fazer, o que deu certo, o que não deu e etc. Isso pode dar uma ligeira motivada a quem for te ajudar...

  • Curtir 2
Postado

@nagatonie      use vetores ou matrizes ou struct para armazenar os dados informdos pelo usuário , e uma string para pegar o que o usuario digitar , assim não haverá erros se forem digitados caracteres invalidos e em seguida use o comando if para verificar se os dados digitados estão no formato adequado , pois as letras maiusculas tem o código na tabela ASCII começando em 65 e vai até 90 e as minúsculas tem os códigos de 97 até 122 , e os dígitos numéricos tem os códigos de 48 até 57 , verificando nas posições da string , que sempre começa em zero e vai até o tamanho da string , que você pode obter usando o comando , strlen(string)  , da biblioteca #include <string.h>  depois para comparar se as placa são iguais ou não use o comando strcmp , que compara string's , e depois que você fizer um código sobre esse exercício , poste ele aqui e ajudaremos , se precisar de alguma correção  .

  • Curtir 3
  • Amei 1
Postado

@devair1010 Fiz baseado na sua sugestão mas tenho uma dificuldade com a utilização do ASCII dentro de um if else.  Fiz um programa básico e mesmo assim tem algo dando errado. Também não sei como faria para pegar, por exemplo, somente os 3 primeiros caracteres digitados e depois os outros 4.

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

struct veiculo {
      char placa[8];
      int i;
};

int main(){
   veiculo v;
   int i;

   for (;;) {
      printf("Insira a placa do seu carro no formato XXX9999: ");
      scanf("%s", v.placa);
      strupr(v.placa);
          if(strlen(v.placa) == 0)
            break;
         if (v.placa[i] >= 65 && v.placa[i] <= 90) 
         printf("Formato valido!\n");
         else 
         printf("formato invalido");
         break;
      }
return 0;
}

 

  • Curtir 1
Postado

@nagatonie

32 minutos atrás, nagatonie disse:

não sei como faria para pegar, por exemplo, somente os 3 primeiros caracteres digitados e depois os outros 4

Limite a entrada.

Em 15/09/2021 às 11:26, nagatonie disse:

A PLACA DEVE TER O FORMATO XXX9999, onde XXX são letras e 9999 DIGITOS

Leia as letras e armazene em uma string, e depois leia os dígitos e armazene em um inteiro.

Basta testar o retorno da scanf() pra saber se tudo foi lido e gravado corretamente:

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

typedef struct
{
    char letras[4];
    int digitos;
} PLACA;

int main()
{
    PLACA placas[5];
    
    printf("Digite a placa de um veiculo no formato XXX9999:\n");
    if((scanf("%3[a-zA-Z]%4d", placas[0].letras, &placas[0].digitos) == 2)
        && (strlen(placas[0].letras) == 3))
    {
        printf("\nTudo nos conformes :)");
    }
    else
    {
        printf("\nPlaca incorreta :(");
    }

    return 0;
}

Se o usuário digitar abc0001 ou abc1 vai dar no mesmo.

Se quer ter certeza que ele digitou 4 números, então leia uma string para os dígitos também, mas dessa vez usando scanset para números somente, e por fim avalie o tamanho da string com strlen() da mesma forma já feita acima :)

  • Curtir 3
Postado
3 horas atrás, nagatonie disse:

Fiz baseado na sua sugestão mas tenho uma dificuldade com a utilização do ASCII dentro de um if else

'

Que significa "utilização do ASCII? Se refere aos códigos Não precisa e não devia usar isso. Esses números mágicos no meio do programa não ajudam em nada.

 

"if else" não existe. if é um comando, else é uma cláusula opcional do comando if.

 

Use o botão code como está descrito no primeiro tópico do forum.

 

Veja a diferença:

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

struct veiculo
{
    char placa[8];
    int i;
};

int main()
{
    veiculo v;
    int i;
    for (;;)
    {

        printf("Insira a placa do seu carro no formato XXX9999: ");
        scanf("%s", v.placa);

        strupr(v.placa);
        if (strlen(v.placa) == 0)  break;

        if (v.placa[i] >= 65 && v.placa[i] <= 90)
            printf("Formato valido!\n");
        else
            printf("formato invalido");
        break;
    }
    return 0;
}

 

Seu programa está ainda muito complicado e frágil.

 

  • tem uma estrutura global, pra que?
  • tem um i na estrutura e outro global em main(). Precisa?
  • Teste sempre o retorno de scanf(). Quando não ler nada pra que vai seguir?
  • E use isso para encerrar o programa e evite o folclórico for(;;)
  • se usa strupr porque não usa isdigit(), isalpha()? 
  • não use esses números mágicos tipo 65, 90. Use constantes, literais como ´a´
  •  
3 horas atrás, Lucca Rodrigues disse:

Se o usuário digitar abc0001 ou abc1 vai dar no mesmo

 

bem lembrado :)

 

3 horas atrás, Lucca Rodrigues disse:

Se quer ter certeza que ele digitou 4 números, então leia uma string para os dígitos também, mas dessa vez usando scanset para números somente, e por fim avalie o tamanho da string com strlen() da mesma forma já feita acima 

 

Talvez pudesse ter dito que d1@b0 é scanset. 

 

E explicado esse 🚃

 

    "%3[a-zA-Z]%4d"

 

Como não vai operar com esses números provavelmente deva usar simplesmente fgets() e ler a linha.

 

Escreva em torno dos dados

 

Está claro que falta um nível de composição aqui: trata-se de uma coleção de placas. Use uma estrutura para conter as placas. É muito mais simples já que não deve aceitar placas repetidas.

 

 

 

  • Curtir 4
Postado

@nagatonie          seu código com algumas modificações está funcionando assim  :

#include <stdio.h>
#include <string.h>
struct veiculo
{
    char placa[10];
    int i;
};
int main()
{
    struct veiculo v[100];                          // vetor para armazenar até 100 placas
    int i,cont = 99;
    int flg = 1;
    char placa[10];
    int tm;
    do                                              // repete ate digitar apenas ENTER
    {    
        do                                          // repete até estar no formato certo
        {
            printf("Insira a placa do seu carro no formato XXX9999: ou < ENTER > para finalizar ");
            fgets(placa,8,stdin);
            fflush(stdin);
            strupr(placa);
            tm = strlen(placa);
            if( tm > 1 )
            {
                flg = 0;                            // marca como formato Errado
                for(i=0; i<3; i++)                  // verifica as 3 Letras
                {
                    if
                    (
                        placa[i] >= 'A' &&
                        placa[i] <= 'Z'
                    );;;
                      flg       = 1;                // marca como Letras no formato certo
                }
                for(i=3; i<8; i++)                  // verifica os 4 digitos ( numeros )
                {
                    if
                    (
                        placa[i] >= '0' &&
                        placa[i] <= '9'
                    ); ;;  ;
                    flg       = 2;                  // marca como numeros no formato certo
                }
            }
            if(placa[0] != '\n')                    /// se não digitou apenas enter
                if( flg == 0 )                      // se formato errado
                    printf("formato invalido\n");
        }while( ! flg );                            // se flg não for diferente de zero , formato 
                                                    /// invaLido , tepete novamete p pegar os dados
        ///
        /// aqui use um for para verificar se no vetor tem outra placa igual a esta
        /// e se não houver nenhuma iguaL  . . .
        strcpy( v[cont].placa , placa );            // armazena a string no vetor
        cont++;                                     // digitando apenas ENTER "cont" será incrementado tambem
    }while( placa[0] != '\n' || cont < 100 );
    cont--;                                         // decrementa o contador para a qtd certa
    if(cont > 99)printf("\nO vetor de Armazenamento esta cheio\n");
    printf("\nPlaca Cadastradas Certas :\n");
    for(i=0; i<cont;i++)
        printf(" %d Placa ===> %s\n",i+1,v[i].placa);
    printf("\n\n\n");
    return 0;
}

 

  • Curtir 2
Postado

@arfneto @arfneto Esse programa tá dando certo na parte de ler as placas no formato requerido. Tem algo a melhorar? Só estou com dificuldade de usar o struct. a parte de ver se existem placas iguais vou fazer depois.

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

void lerPlaca(char placa[]);
void validaPlaca(char placa[]);
void isnum(char caractere);

int main(){
    char placa[8];
    lerPlaca(placa);
    validaPlaca(placa);
    return 0;

}

void lerPlaca(char placa[]){
    int i=0;
    printf("Digite a placa do veiculo: ");
    for(i=0;i<=6;i++){
        placa[i]=getche();
    }
    placa[8]='\0';
}

void validaPlaca(char placa[]){
    int i,k,j,correto=0;
    for(i=0;i<=2;i++){
        k=isalpha(placa[i]);
        if(k!=0 ){
            correto++;
        }else{
            break;
        }
    }
    for(i=3;i<=6;i++){
        j=isdigit(placa[i]);
        if(j!=0){
            correto++;
        }else{
            break;
        }
    }
        if(correto==7){
            printf("\nPLACA CADASTRADA COM SUCESSO!!!\n", placa);
        }
        else{
            printf("\nPLACA COM FORMATO INVALIDO.");
        }
}

 

  • Amei 1
Postado

Acho que seu programa poderia ter duas funções, uma para testar se a placa é válida e outra para verificar se é repetida. Assim em main vai ter o loop com a entrada e o teste com as funções, algo assim,

 

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

#define MAX 5

int valida(char *placa){
    if(strlen(placa) != 7){
        return 0;
    }
    for(int i = 0; placa[i] != 0; i += 1){
        if(i <= 2){
            if(!isalpha(placa[i])){
                return 0;
            }
        }else{
            if(!isdigit(placa[i])){
                return 0;
            }
        }
    }
    return 1;
}

int repetido(char placas[MAX][8], char *placa, int n){
    for(int i = 0; i < n; i += 1){
        if(strcmp(placas[i], placa) == 0){
            return 1;
        }
    }
    return 0;
}

int main(void){
    char placa[MAX][8];
    int i = 0;
    
    while(i < MAX){
        printf("Placa %d = ", i);
        scanf("%7s", placa[i]);
        if(valida(placa[i]) == 0 || repetido(placa, placa[i], i)){
            puts("PLACA INVALIDA OU REPETIDA");
            continue;
        }
        i += 1;
    }
    return 0;
}

 

  • Curtir 2
  • Amei 1
Postado

@Midori eu usei esse código como base e coloquei um while na funçao de ler placa, quando coloco a primeira placa certa ele lê e o programa funciona certo. mas se eu começar colocando no formato errado e depois colocar certo ele retorna todos os outros em invalido. olha:

#include <stdio.h>

#include <string.h>

#include <ctype.h>



void lerPlaca(char placa[]);



int main(){

    char placa[8];

    lerPlaca(placa);

    return 0;



}



void lerPlaca(char placa[]){

    int i=0;

    int k, j, correto=0;




while(correto != 7) {

    printf("\nDigite a placa no formato XXX9999: ");

    fflush(stdin);

    for(i=0;i<=6;i++){

        placa[i]=getchar();

    }

    placa[8]='\0';



    for(i=0;i<=2;i++){

        k=isalpha(placa[i]);

        if(k!=0 ){

            correto++;

        }else{

            break;

        }

    }

    for(i=3;i<=6;i++){

        j=isdigit(placa[i]);

        if(j!=0){

            correto++;

        }else{

            break;

        }

    }

        if(correto==7){

            printf("\nPLACA CADASTRADA COM SUCESSO!!!\n");

            

        }

        else{

            printf("\nPLACA COM FORMATO INVALIDO.");

        }

            

} 



}

 

  • Obrigado 1
Postado

@nagatonie     a variaveL correto continuará com o mesmo valor e assim o resultado é esse invalido ,  coloque essa variavel com valor zero :

#include <stdio.h>
#include <string.h>
#include <ctype.h>
void lerPlaca(char placa[]);
int main()
{
    char placa[8];
    lerPlaca(placa);
    return 0;
}
void lerPlaca(char placa[])
{
    int i=0;
    int k, j, correto=0;
    while(correto != 7)
    {
        printf("\nDigite a placa no formato XXX9999: ");
        fflush(stdin);
        for(i=0;i<=6;i++)
        {
            placa[i]=getchar();
        }
        placa[8]='\0';
        for(i=0;i<=2;i++)
        {
            k=isalpha(placa[i]);
            if(k!=0 )
            {
                correto++;
            }
            else
            {
                break;
            }
        }
        for(i=3;i<=6;i++)
        {
            j=isdigit(placa[i]);
            if(j!=0)
            {
                correto++;
            }
            else
            {
                break;
            }
        }
        if(correto==7)
        {
            printf("\nPLACA CADASTRADA COM SUCESSO!!!\n");
        }
        else
        {
            printf("\nPLACA COM FORMATO INVALIDO.");
            correto=0;
        }
    }
    return 0;
}

 

  • Curtir 1
  • Obrigado 1
Postado
Em 17/09/2021 às 16:00, nagatonie disse:

Esse programa tá dando certo na parte de ler as placas no formato requerido. Tem algo a melhorar? Só estou com dificuldade de usar o struct. a parte de ver se existem placas iguais vou fazer depois.

 

Esse deveria ser o começo do seu programa e não algo para fazer depois. Vai ter mais trabalho sem necessidade.

 

Em 16/09/2021 às 23:54, arfneto disse:

Escreva em torno dos dados

 

Está claro que falta um nível de composição aqui: trata-se de uma coleção de placas. Use uma estrutura para conter as placas. É muito mais simples já que não deve aceitar placas repetidas.

 

Como eu disse antes, deve considerar os dados. Ou vai perder muito tempo e ter menos resultado...

 

Do seu programa

 

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

void lerPlaca(char placa[]);
void validaPlaca(char placa[]);

int main()
{
    char placa[8];
    lerPlaca(placa);
    validaPlaca(placa);
    return 0;
}

 

Você sabe que precisa tratar não uma mas uma coleção de placas válidas, já que não pode aceitar placas duplicadas. 

 

Isso --- e nada mais --- deve estar no início do processo de escrever o programa. 

 

  • conio.h é algo dos anos 80 derivado de um programa da Borland --- hoje Embarcadero ---  que vinha em dois diskettes de 5.25", de 1.2MB cada um ;) Não é possível que precise disso em 2021
  • se usou lerPlaca devia usar validarPlaca usando a mesma convenção de nomes para as funções ou vai se confundir a toda hora: sera validaPlaca ou validarPlaca?  Será lerPlaca ou lePlaca?

Compare com essa possibilidade:

 

typedef char Placa[8];

typedef struct
{
    unsigned N;      // quanto tem agora
    unsigned size;   // quanto cabe
    Placa    pl[10]; // as placas

}   Placas;

Placa*      ler_placa();
int         placa_valida(Placa*);

image.png.ec37d372a34efbedf049b70abb03fcd8.png

  • Deixando a definição de placa assim fica trivial trocar a definição, por exemplo para usar o formato de placa do MercoSul que agora tem 3 letras 1 numero 1 letra e 2 números, como ABC9A01 ...
    Ou usar uma struct para separar o prefixo se for preciso
  • a função que lê uma placa retorna uma Placa, seja lá o que for. Isso é mais flexível e mais fácil de testar
  • a estrutura Placas já tem um contador, então é muito mais fácil de controlar no programa ou passar para funções para por exemplo listar as placas que estão cadastradas num dado momento. Fica simples  controlar por exemplo vários cadastros de placas, que pode declarar algo como
     
    	Placas		frota[8];


    e ter 8 grupos de placa sem mudar as funções. Esse é o conceito de encapsulamento na literatura, e facilita muito a vida do desenvolvedor.

  • placa_valida() retorna 1 para placa válida, ou outros valores. Lembre-se de que em C zero é falso, todo outro valor é verdadeiro.

Indo adiante

 

É claro que se tem uma coleção de placas e vai querer testar isso vai precisar de uma função que lista as tais placas cadastradas. E essa deve ser a primeira função de todas, já que precisa funcionar antes de ter alguma placa, porque precisa saber dizer que a lista está vazia

 

	int         listar_placas(Placas* cad);

 

Uma função assim recebe o endereço da coleção de placas e lista. E ao receber isso vem junto o tamanho do conjunto e o total de placas no momento: nada mais de fora da função importa. Nada mais pode dar erro.

 

Seria legal poder ter um título para ajudar a entender a saída dos testes então

 

	int         listar_placas(Placas* cad, const char* tit);

 

para poder escrever por exemplo listar_placas( cadastro, "teste com a lista ainda vazia"); A função retornar o número de placas listadas seria uma escolha comum em C e um número negativo em caso de erro, a convenção comum.

 

Inserir uma placa

 

O próximo passo é também óbvio: como inserir uma placa num conjunto de placas?

 

    int         inserir_placa(Placa* uma, Placas* conjunto);

 

Algo assim é o trivial: insere uma placa num conjunto e retorna algo. Negativo se deu erro ou o total atualizado de placas no conjunto.

 

Inserir em ordem

 

Porque inserir em ordem? Em geral se espera uma listagem por alguma ordem, e inserir na ordem ajuda na hora da busca. Ao invés de olhar placa por placa para buscar uma duplicata se pode fazer busca binária e comparar apenas no máximo umas 32 placas para um arquivo de 1 milhão delas...

 

Uma função dessas podia ser
 

    int         inserir_placa_s(Placa*, Placas*);

 

As funções e os dados até agora

 


typedef char Placa[8];

typedef struct
{
    unsigned N;      // quanto tem agora
    unsigned size;   // quanto cabe
    Placa    pl[10]; // as placas

}   Placas;


Placa*      ler_placa();
int         inserir_placa(Placa*, Placas*);
int         inserir_placa_s(Placa*, Placas*);
int         listar_placas(Placas*, const char*);
int         placa_valida(char*);

 

Ainda não se escreveu nada de programa, mas por escrever em torno dos dados já se tem uma boa ideia do rumo das coisas, e isso ajuda a escrever e testar. Escrevendo assim muitos programas rodam certinho já na primeira vez.

 

Um exemplo em C

 

Validando uma placa

 

Há claro muitas maneiras de fazer isso, mas para fazer algo simples e seguro da primeira vez s epode ler tudo que tem na linha, cortar o que deve ser a placa e testar pelas letras e dígitos. 

Não é preciso usar funções de ctype.h, só iria retardar a execução e talvez dificultar a leitura.

 

Uma versão

 

int         placa_valida(char* p)
{
    if (strlen(p) < 7) return 0;
    p[7] = 0; // trunca para 7 digitos
    // o simples com recortar e colar
    for (int i = 0; i < 3; i += 1)
    {
        if ( (p[i] < 'A') || (p[i] > 'Z') )
        {   // não maiuscula
            if ((p[i] < 'a') || (p[i] > 'z')) return 0;
            p[i] = 'A' + p[i] - 'a'; // converte 
        }
    }
    for (int i = 3; i < 7; i += 1)
    {
        if ((p[i] < '0') || (p[i] > '9')) return 0;
    }
    return 1;
}

 

E essa função já converte minúsculas para maiúsculas antes de retornar. Assim fica mais fácil de testar pela repetição.

 

Lendo uma placa

 

Placa*      ler_placa()
{   // No enunciado a placa = XXXNNNN
    char linha[80];
    char* p = linha;

    printf("Digite a PLACA no formato XXXNNNN ou ENTER para encerrar:  ");
    p = fgets(linha, sizeof(linha), stdin);

    while (p != NULL)
    {   // leu algo?
        if (p == NULL) return NULL;     // deu erro
        if (p[0] == '\n') return NULL;  // teclou ENTER
        if (placa_valida(linha))
        {   // ok: retorna essa placa
            char* nova = (char*)malloc(8*sizeof(char));
            memcpy(nova, linha, 7); // copia 
            nova[7] = 0;            // finaliza a string
            return (Placa*)nova;    // e retorna a placa lida
        }
        printf("\nPlaca INVALIDA!\7\n");
        printf(
            "Digite a PLACA no formato XXXNNNN ou ENTER para encerrar: "
            " ");
        // le a linha toda ate esse tamanho
        p = fgets(linha, sizeof(linha), stdin);
    }
    return NULL;
}

 

Essa versão retorna uma placa válida ou NULL. Para facilitar as coisas o usuário pode digiar enter para encerrar. A linha TODA é consumida com uma chamada a fgets() e assim fica tudo mais simples que usar scanf() e ter que tratar os '\n' e tal.

 

Inserindo uma placa no grupo

 

int inserir_placa(Placa* pl, Placas* cjto)
{  // o simples: insere a placa pl no conjunto cjto
    if (cjto->N == cjto->size) return -2;
    for (unsigned i = 0; i < cjto->N; i += 1)
        if (strcmp(pl, cjto->pl[i]) == 0) return PLACA_DUPLICADA;  // ja tem
    strcpy(cjto->pl[cjto->N], pl);                    // copia nova
    cjto->N += 1;                                     // conta essa
    return cjto->N;
}

 

Nada de especial, apenas coloca a placa no vetor se couber. E retorna o total corrigido, que pode ser útil em algum caso.

 

E seria complicado inserir na ordem?

 

Não. Como o programa lê uma placa de cada vez basta colocar no lugar certo, como o insertion sort. e como se faria se fossem placas físicas para colocar em ordem.

 

int inserir_placa_s(Placa* pl, Placas* cjto)
{  // o simples: insere a placa pl no conjunto cjto, em ordem
    int res = 0;
    if (cjto->N == cjto->size) return -2;
    unsigned pos = cjto->N; // posicao onde vai inserir a placa
    for (; pos > 0; pos -= 1)
        switch( res = strcmp(pl, cjto->pl[pos - 1]) )
        {   case +1: // achou a posicao
                strcpy(cjto->pl[pos], pl);  // copia nova
                cjto->N += 1;               // conta essa
                return cjto->N;
                break;
            case -1: // ainda não
                strcpy(cjto->pl[pos], cjto->pl[pos - 1]);  // desloca
                break;
            default: // ja tinha
                printf("\nPlaca DUPLICADA!\7\n");
                return PLACA_DUPLICADA;
                break;
        };  // switch()
    strcpy(cjto->pl[pos], pl);  // copia nova
    cjto->N += 1;               // conta essa
    return cjto->N;
}

 

Note que não estou usando o fato de que o que tem na lista já está em ordem... Podia usar busca binária no vetor. É só um exemplo afinal.

 

A lógica é simples: o insertion sort de ponta-cabeça: começa da última placa e vai deslocando as placas para abrir lugar para a nova. Nada mais.

 

Um teste

 

int main(void)
{
    int    res = 0;
    Placas frota;
    frota.N     = 0;
    frota.size  = 6;

    listar_placas(&frota, "Placas no inicio do teste");
    Placa* teste = ler_placa();
    while (teste != NULL)
    {
        if ( (res = inserir_placa(teste, &frota)) == frota.size)
        {
            printf(
                "\n\t==> Cheio: %u placas ja cadastradas!\n",
                frota.size);
            break;
        }
        if (res == PLACA_DUPLICADA)
            printf("\n\t==> Placa \"%s\" ja cadastrada!\n", teste);
        free(teste);  // não vai usar mais
        teste = ler_placa();
    };  // while()
    listar_placas(&frota, "Placas ao final do teste");
    return 0;
}

 

Esse teste enche o vetor de placas até não caber mais.

 

Uma saída do teste

 

Total de 0 placas [MAX 10]


Digite a PLACA no formato XXXNNNN ou ENTER para encerrar:  abc1234
Digite a PLACA no formato XXXNNNN ou ENTER para encerrar:  aBc0000 pode escrever ao final
Digite a PLACA no formato XXXNNNN ou ENTER para encerrar:  aBC0000 vai duplicar

Placa DUPLICADA!

        ==> Placa "ABC0000" ja cadastrada!
Digite a PLACA no formato XXXNNNN ou ENTER para encerrar:  AAA0002
Digite a PLACA no formato XXXNNNN ou ENTER para encerrar:  abc3456
Digite a PLACA no formato XXXNNNN ou ENTER para encerrar:  zzz2345
Digite a PLACA no formato XXXNNNN ou ENTER para encerrar:


Placas ao final do teste

Total de 5 placas [MAX 10]

 1    AAA0002
 2    ABC0000
 3    ABC1234
 4    ABC3456
 5    ZZZ2345

 

 

O programa completo de teste

 

/*
https://www.clubedohardware.com.br/forums/topic/1563000-cadastro-de-carro-linguagem-c/?tab=comments#comment-8269170
*/

#define PLACA_DUPLICADA (-1)
#define CADASTRO_CHEIO  (-2)

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

typedef char Placa[8];

typedef struct
{
    unsigned N;      // quanto tem agora
    unsigned size;   // quanto cabe
    Placa    pl[10]; // as placas

}   Placas;


Placa*      ler_placa();
int         inserir_placa(Placa*, Placas*);
int         inserir_placa_s(Placa*, Placas*);
int         listar_placas(Placas*, const char*);
int         placa_valida(char*);

int main(void)
{
    int    res = 0;
    Placas frota;
    frota.N     = 0;
    frota.size  = 10;

    listar_placas(&frota, "Placas no inicio do teste");
    Placa* teste = ler_placa();
    while (teste != NULL)
    {
        if ( (res = inserir_placa_s(teste, &frota)) == frota.size)
        {
            printf(
                "\n\t==> Cheio: %u placas ja cadastradas!\n",
                frota.size);
            break;
        }
        if (res == PLACA_DUPLICADA)
            printf("\n\t==> Placa \"%s\" ja cadastrada!\n", teste);
        free(teste);  // não vai usar mais
        teste = ler_placa();
    };  // while()
    listar_placas(&frota, "Placas ao final do teste");
    return 0;
}


Placa*      ler_placa()
{   // No enunciado a placa = XXXNNNN
    char linha[80];
    char* p = linha;

    printf("Digite a PLACA no formato XXXNNNN ou ENTER para encerrar:  ");
    p = fgets(linha, sizeof(linha), stdin);

    while (p != NULL)
    {   // leu algo?
        if (p == NULL) return NULL;     // deu erro
        if (p[0] == '\n') return NULL;  // teclou ENTER
        if (placa_valida(linha))
        {   // ok: retorna essa placa
            char* nova = (char*)malloc(8*sizeof(char));
            memcpy(nova, linha, 7); // copia 
            nova[7] = 0;            // finaliza a string
            return (Placa*)nova;    // e retorna a placa lida
        }
        printf("\nPlaca INVALIDA!\7\n");
        printf(
            "Digite a PLACA no formato XXXNNNN ou ENTER para encerrar: "
            " ");
        // le a linha toda ate esse tamanho
        p = fgets(linha, sizeof(linha), stdin);
    }
    return NULL;
}

int inserir_placa(Placa* pl, Placas* cjto)
{  // o simples: insere a placa pl no conjunto cjto
    if (cjto->N == cjto->size) return -2;
    for (unsigned i = 0; i < cjto->N; i += 1)
        if (strcmp(pl, cjto->pl[i]) == 0) return PLACA_DUPLICADA;  // ja tem
    strcpy(cjto->pl[cjto->N], pl);                    // copia nova
    cjto->N += 1;                                     // conta essa
    return cjto->N;
}

int inserir_placa_s(Placa* pl, Placas* cjto)
{  // o simples: insere a placa pl no conjunto cjto, em ordem
    int res = 0;
    if (cjto->N == cjto->size) return -2;
    unsigned pos = cjto->N; // posicao onde vai inserir a placa
    for (; pos > 0; pos -= 1)
        switch( res = strcmp(pl, cjto->pl[pos - 1]) )
        {   case +1: // achou a posicao
                strcpy(cjto->pl[pos], pl);  // copia nova
                cjto->N += 1;               // conta essa
                return cjto->N;
                break;
            case -1: // ainda não
                strcpy(cjto->pl[pos], cjto->pl[pos - 1]);  // desloca
                break;
            default: // ja tinha
                printf("\nPlaca DUPLICADA!\7\n");
                return PLACA_DUPLICADA;
                break;
        };  // switch()
    strcpy(cjto->pl[pos], pl);  // copia nova
    cjto->N += 1;               // conta essa
    return cjto->N;
}

int         listar_placas(Placas* frota, const char* tit)
{
    if (tit != NULL) printf("\n\n%s\n", tit);
    printf("\nTotal de %u placas [MAX %u]\n\n", frota->N, frota->size);
    for (unsigned i = 0; i < frota->N; i += 1)
        printf("%2d    %s\n", 1 + i, frota->pl[i]);
    printf("\n");
    return 0;
}

int         placa_valida(char* p)
{
    if (strlen(p) < 7) return 0;
    p[7] = 0; // trunca para 7 digitos
    // o simples com recortar e colar
    for (int i = 0; i < 3; i += 1)
    {
        if ( (p[i] < 'A') || (p[i] > 'Z') )
        {   // não maiuscula
            if ((p[i] < 'a') || (p[i] > 'z')) return 0;
            p[i] = 'A' + p[i] - 'a'; // converte 
        }
    }
    for (int i = 3; i < 7; i += 1)
    {
        if ((p[i] < '0') || (p[i] > '9')) return 0;
    }
    return 1;
}

 

 

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...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!