Ir ao conteúdo

Posts recomendados

Postado

Olá pessoal,

estou fazendo uma atividade usando switch...case e deu um erro que nunca tinha dado pra mim antes, já pesquisei como resolver e alguns falaram para usar aspas simples ao invés de aspas duplas mas não funcionou...

 

Segue o código, juntamente com o enunciado da questão:
 

//Uma empresa vende o mesmo produto para quatro diferentes estados. Cada estado possui uma taxa diferente de
//imposto sobre o produto. Faça um programa em que o usuário entre com o valor e o estado de destino do produto
//e o programa retorne o preço final do produto acrescido do imposto do estado em que ele será vendido. Se o 
//estado digitado não for válido, mostrará uma mensagem de erro.
//MG 7% SP 12% RJ 15% MS 8%
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
int main(){
	setlocale(LC_ALL,"Portuguese");
	char estado;
	float val_prod,val_final;
	printf("Insira o valor do produto: ");
	scanf("%f",&val_prod);
	printf("Insira o Estado de destino do produto (MG, SP, RJ ou MS): ");
	scanf("%s",&estado);
	switch (estado){
		case 'mg' :
		case 'MG' :
			val_final=val_prod*0.07;
			printf("Para MG, o produto com imposto fica por R$%.2f.\n",val_final);
			break;
		case 'sp' :
		case 'SP' :
			val_final=val_prod*0.12;
			printf("Para SP, o produto com imposto fica por R$%.2f.\n",val_final);
			break;
		case 'rj' :
		case 'RJ' :
			val_final=val_prod*0.15;
			printf("Para RJ, o produto com imposto fica por R$%.2f.\n",val_final);
			break;
		case 'ms' :
		case 'MS' :
			val_final=val_prod*0.08;
			printf("Para MS, o produto com imposto fica por R$%.2f.\n",val_final);
			break;
		default:
			printf("Por favor, insira um estado entre MG, SP, RJ ou MS.\n");
	}
	printf("\n\n");
	printf("Obrigada pela preferência!\n");
	system("pause");
}

 

O erro que está dando:

  [Warning] multi-character character constant [-Wmultichar]
  [Warning] case label value exceeds maximum value for type

 

Detalhe: quando coloco número com casa decimal, o programa pula tudo e vai direto pro system("pause").
 

WhatsApp Image 2022-02-18 at 4.51.26 PM (1).jpeg

WhatsApp Image 2022-02-18 at 4.51.26 PM.jpeg

Postado

@Leucosia

Antes de mais nada:

19 minutos atrás, Leucosia disse:
char estado;

`estado` não é uma string, como imagino que desejasse que fosse.

A string deveria ter espaço para 2 caracteres? Ok, mas deixe espaço para o terminador da string também:

char estado[3];

O que é o terminador da string?

Citação

Na linguagem de programação C existe um significado especial para este caractere. Ele é utilizado para indicar o final de strings de caracteres. O caractere nulo é freqüentemente representado como "\0" no código fonte escrito em C. As strings finalizadas com o caractere nulo são conhecidas como "terminadas em nulo" (null-terminated).

Fonte.

 

22 minutos atrás, Leucosia disse:
scanf("%s",&estado);

Se tratando de uma string, dê para scanf() o endereço do elemento no qual deverá ser iniciada a gravação dos dados, ou então apenas esqueça o &, `&estado[0]` dá no mesmo que apenas `estado`, a gravação se dá no início da string.

 

19 minutos atrás, Leucosia disse:

pesquisei como resolver e alguns falaram para usar aspas simples ao invés de aspas duplas mas não funcionou

Se tratando de um caractere, então sim, o coloque entre aspas simples.

Não vai conseguir usar switch com uma string como expressão.

Se tratando de 2 caracteres apenas, mais fácil seria comparar manualmente:

//case 'mg' :
//case 'MG' :
if((estado[0] == 'm' && estado[1] == 'g') || (estado[0] == 'M' && estado[1] == 'G'))
{
  
}

De qualquer forma, caso queira comparar strings, pode usar a função strcmp() da string.h. A função compara caractere por caractere e retorna 0 se as strings forem idênticas.

  • Curtir 2
Postado

@Leucosia O tipo char só recebe um caractere entre aspas simples. Acima disso se torna string como no caso dos estados do seu código que tem dois caractres. E para strings você deve usar aspas duplas (e não simples como fez). Além disso o comando switch só aceita inteiros (char também é um inteiro com o código da letra).

  • Curtir 1
  • Obrigado 1
Postado

Seu programa ainda tem muitos erros e talvez não seja o melhor caminho este que está tentando.

 

Alguns  problemas:

 

  • você marcou a linguagem como C++ mas postou um programa em C
     
  •  não existe switch case. O comando é switch. Apenas switch. case é o prefixo do label. Label é aquilo que vem antes dos ':'. Veja a documentação.
     
        char estado;
        // ...
        scanf("%s",&estado);

     

  • Você declarou estado como char, uma letrinha, e espera ler via scanf() uma string usando "%s". Não vai funcionar:
    • use %c para ler uma letra
    • declare uma string para ler com %s
       
  • TESTE sempre o retorno de scanf(). Veja a documentação. É ingênuo não testar. em especial se está aprendendo: se não ler nada encerre o programa. Mais simples. 

Seu switch

    switch (estado){
        case 'mg' :
        case 'MG' :


Pois é: dois erros aqui:

  • estado é uma letra só.
  • apóstrofes delimitam uma constante char, uma letra, como declarou estado. Não pode usar duas letras aí.

Se quer uma string tipo MG deve usar aspas "MG" e declarar como tal. E aí não poderá usar em um case. Para comparar strings use strcmp() de string.h

 

No geral não deve usar scanf() para ler do teclado. Não sei porque ensinam assim. scanf() foi escrita para ler entrada formatada, como tabelas. Por isso o nome: scan formatted...

 

Use fgets() que é muito mais simples.

 

Não use system(). Nunca. Não vai estar aprendendo nada nem fazendo nada.

 

Se seu IDE não pode parar o programa se rodar na console USE OUTRO IDE. 


Veja um exemplo mais seguro e rode em sua máquina:

 

#define MG (0)
#define MS (1)
#define RJ (2)
#define SP (3)

#include<stdio.h>

int main(void)
{
    const char* sigla[] = {"MG", "MS", "RJ", "SP"};
    char        linha[80];
    char        estado = 0;
    do {
        printf(
            "Insira a sigla do estado de destino do "
            "produto: ");
        char* p = fgets(linha, sizeof(linha), stdin);
        if (p == NULL) return -1;  // não leu nada
        estado = 5;
        switch (linha[0])
        {
            case 'M':
            case 'm':
                switch (linha[1])
                {
                    case 'G':
                    case 'g':
                        estado = 0;
                        break;
                    case 'S':
                    case 's':
                        estado = 1;
                        break;
                    default:
                        break;
                };  // switch 2
            case 'R':
            case 'r':
                if ((linha[1] == 'J') || (linha[1] == 'j'))
                    estado = 2;
                break;
            case 'S':
            case 's':
                if ((linha[1] == 'P') || (linha[1] == 'p'))
                    estado = 3;
                break;
            default:
                break;
        }
    } while (estado > 3);
    printf("Estado: \"%s\"\n", sigla[estado]);
    return 0;
}

 

Esse exemplo

  • roda um loop até identificar um estado válido.
  • É mais fácil de ler porque tem constantes para achar a sigla do estado certo na tabela e mostrar ao final.
  • Trata qualquer combinação de maiúsculas/minúsculas.
  • Consome toda a linha e é mais seguro se for ler dados depois

Sugiro testar e comparar.

 

Exemplo da execução:

 

Insira a sigla do estado de destino do produto: teste
Insira a sigla do estado de destino do produto: rf
Insira a sigla do estado de destino do produto: rj
Estado: "RJ"
  • Curtir 1
Postado

@Leucosia Olá tudo bem...

 

14 horas atrás, Leucosia disse:

uma atividade usando switch...case e deu um erro que nunca tinha dado pra mim antes

 

Há muitos anos outro usuário escreveu dúvida semelhante, me lembro que ele rejeitou as soluções que usaram mais que uma camada de condicionais, ou seja, tinha que ser somente uma camada switch e case. Foram dadas duas propostas:

 

#A consiste em multiplicar o primeiro padrão por um decimal de modo que define outro composto com o segundo padrão. Uma combinação de produto e soma

e.g: C language

#include"stdio.h"
#include"stdlib.h"
int
main (void) {
  printf ("Ola, digite uma das siglas dos estados do Basil [SP MG RJ MS]: ");
  
  char estado[4] = { "" };
  scanf ("%2s", estado);

  switch (estado[0]*100 + estado[1]) {
  case   'S'*100 + 'P':
                      printf ("Sao Paulo - %s\n", estado);
                      break;
  case   'M'*100 + 'G':
                      printf ("Minas Gerais - %s\n", estado);
                      break;
  case   'R'*100 + 'J':
                      printf ("Rio Janeiro - %s\n", estado);
                      break;
  case   'M'*100 + 'S':
                      printf ("Mato Grosso Sul - %s\n", estado);
                      break;
  default:
         printf ("Sigla inexistente!\n");
  }
  return 0;
}

 

#B consiste em deslocar a sequência de 8 bits do segundo padrão por um inteiro de modo que define outro integrando o primeiro padrão.

e.g: C language

#include"stdio.h"
#include"stdlib.h"
int
main (void) {
  printf ("Ola, digite uma das siglas dos estados do Basil [SP MG RJ MS]: ");
  
  char estado[4] = { "" };
  scanf ("%2s", estado);

  switch (*(int *) estado) {
  case   'S'|'P' << 8:
                     printf ("Sao Paulo - %s\n", estado);
                     break;
  case   'M'|'G' << 8:
                     printf ("Minas Gerais - %s\n", estado);
                     break;
  case   'R'|'J' << 8:
                     printf ("Rio Janeiro - %s\n", estado);
                     break;
  case   'M'|'S' << 8:
                     printf ("Mato Grosso Sul - %s\n", estado);
                     break;
  default:
         printf ("Sigla inexistente!\n");
  }
  return 0;
}

 

— Essa é minha recomendação veja que expressão da cláusula simula 'multi-character constant' (uma “strings”).

Sugeri também que se usar uma estrutura union ocultaria o cast na expressão da switch.

#include"stdio.h"
#include"stdlib.h"
int
main (void) {
  printf ("Ola, digite uma das siglas dos estados do Basil [SP MG RJ MS]: ");
  
  union { char Chars[sizeof(int)]; int Int; } estado;
  scanf ("%2s", estado.Chars);

  switch (estado.Int) {
  case   'S'|'P' << 8:
                     printf ("Sao Paulo - %s\n", estado.Chars);
                     break;
  case   'M'|'G' << 8:
                     printf ("Minas Gerais - %s\n", estado.Chars);
                     break;
  case   'R'|'J' << 8:
                     printf ("Rio Janeiro - %s\n", estado.Chars);
                     break;
  case   'M'|'S' << 8:
                     printf ("Mato Grosso Sul - %s\n", estado.Chars);
                     break;
  default:
         printf ("Sigla inexistente!\n");
  }
  return 0;
}

[SAÍDA]

286437944_Semttulo1.png.4854b28bb77a6afd7a4a9f7b60f48ad8.png

 

É possível substituir os operadores por multiplicação e adição, mas lógica binária é, para mim, muita mais elegante.

[🙂] — Espero que ajude.

 

  • Curtir 2
Postado
4 horas atrás, mauro_b disse:

rejeitou as soluções que usaram mais que uma camada de condicionais, ou seja, tinha que ser somente uma camada switch e case

 

É uma razão afinal: uma aposta, um desafio ou simples teimosia em não fazer o simples 🙂 

 

Sobre o primeiro exemplo, @mauro_b

 

    char estado[4] = { "" };

 

é a mesma coisa que 

 

    char estado[4] = {0};

 

Que

  • é mais fácil de ler e entender.
  • E economiza uma tecla. Um zero e não DUAS aspas.
  • E em muitos teclados aspas são maiúsculas então ainda tem que apertar o shift
  • E aspas mudam de lugar de um teclado para outro. O 0 não
   switch (estado[0]*100 + estado[1]) {

 

Talvez pudesse usar 256 como fator para facilitar ler isso na memória, mantendo os valores em cada posição... O mesmo que fez no segundo exemplo usando <<8. Veja:
 

    estado[0] = 'S';
    estado[1] = 'P';
    switch (estado[0] * 256 + estado[1])

 

E como sabe fica na memória:
 

image.png.4188a04e02edd5282e8f5cb3f5a29bd1.png

 

Pode ser útil.

 

Talvez pudesse evitar essas coisas

 

case   'S'*100 + 'P':

 

que afinal vão ser resolvidas em tempo de compilação e usar o pré-processador escrevendo

 

#define SP ('S' * 256 + 'P')

 

Para poder ter no switch algo mais legível como

 

        case SP:
            printf("Sao Paulo - %s\n", estado);
            break;

 

4 horas atrás, mauro_b disse:

Essa é minha recomendação veja que expressão da cláusula simula 'multi-character constant' (uma “strings”).

 

Uma string seria uma sequência de bytes terminada por um NULL. Não é bem o caso aqui. Apenas está gerando um número a partir dos 2 bytes da string.

 

5 horas atrás, mauro_b disse:

Sugeri também que se usar uma estrutura union ocultaria o cast na expressão da switch

 

Tem razão. É a mesma coisa mas fica mais fácil de ler. Provavelmente se escrever assim:

 

    union
    {
        char estado[sizeof(int)];
        int  numero;
    } Dual = {0};

 

seja mais fácil de entender o uso.

 

Usando essas constantes:

 

#define MG 'M' | ('G' << 8)
#define MS 'M' | ('S' << 8)
#define RJ 'R' | ('J' << 8)
#define SP 'S' | ('P' << 8)

 

E essa tabela:

 

    const char* estados[] = {
        "Minas Gerais",
        "Mato Grosso Sul",
        "Rio Janeiro",
        "Sao Paulo",
        "Sigla inexistente!"
    };

 

Poderia escrever o comando switch assim:

 

    int indice = 0;
    if (1 != scanf("%2s", Dual.estado)) indice = 4;
    switch (Dual.numero)
    {
        case SP: indice = 3;
            break;
        case MG: indice = 0;
            break;
        case RJ: indice = 2;
            break;
        case MS: indice = 1;
            break;
        default: indice = 4;
            break;
    }
    printf("%s\n", estados[indice]);

 

E ficar com algo provavelmente mais legível.

 

Exemplo

 

#define MG 'M' | ('G' << 8)
#define MS 'M' | ('S' << 8)
#define RJ 'R' | ('J' << 8)
#define SP 'S' | ('P' << 8)

#include "stdio.h"
#include "stdlib.h"

int main(void)
{
    union
    {
        char estado[sizeof(int)];
        int  numero;
    } Dual = {0};

    const char* estados[] = {
        "Minas Gerais",
        "Mato Grosso Sul",
        "Rio Janeiro",
        "Sao Paulo",
        "Sigla inexistente!"
    };

    printf( "Ola, digite uma das siglas dos estados do Brasil "
        "[SP MG RJ MS]: ");
    int indice = 0;
    if (1 != scanf("%2s", Dual.estado)) indice = 4;
    switch (Dual.numero)
    {
        case SP: indice = 3;
            break;
        case MG: indice = 0;
            break;
        case RJ: indice = 2;
            break;
        case MS: indice = 1;
            break;
        default: indice = 4;
            break;
    }
    printf("%s\n", estados[indice]);
    return 0;
}

 

Postado
5 horas atrás, arfneto disse:

Talvez pudesse usar 256 como fator para facilitar ler isso na memória, mantendo os valores em cada posição... O mesmo que fez no segundo exemplo usando <<8

Isso, fica a gosto, já que  o resultado é certamente igual;

 

Por exemplo, 

5 horas atrás, arfneto disse:

Que

  • é mais fácil de ler e entender.
  • E economiza uma tecla. Um zero e não DUAS aspas.
  • E em muitos teclados aspas são maiúsculas então ainda tem que apertar o shift
  • E aspas mudam de lugar de um teclado para outro. O 0 não

São argumentos para fazer o que dizem ser "mais simples", mas ambos são igualmente simples a graduação de simplicidade (que para mim) nem existe é mera questão de gosto. Dizer que uma coisa é mais fácil de ler porque tem 0 ou '/0' ou "" e ridiculamente preferencial. Ridiculamente porque o limite do irrelevante.

 

* "Mais fácil de ler" é tão evasivo quanto "mais simples" porque se trata  de uma limitação pessoal.

Todas as notações são igualmente fáceis ter isso ou aquilo de mais fácil/simples é excluir um por motivo de preferências 😄 

É bem mais honesto quando dizem: eu prefiro isso do que aquilo.

 

 

* Economizar teclas, estamos

por Acaso numa crise de teclas 😄 

 

* "são maiúsculas então ainda tem que apertar o shift" 

Preocupação com a Lesão por Reforço Repetitivo — LER é razoável e advirto ser um problema que não se evita na "economias teclas" ou qualquer outra regra esdruxula, se não com bom descanso. Descanso será também útil na produtividade.

 

São observações divertidas SIM, que não faz de ninguém um programador melhor/produtivo.

 

#0

5 horas atrás, arfneto disse:

Uma string seria uma sequência de bytes terminada por um NULL. Não é bem o caso aqui. Apenas está gerando um número a partir dos 2 bytes da string.

A constante é um inteiro de 4 “bytes”, no caso é também uma sequência de ‘bytes’ 🙂 e sua estrutura ou configuração na memória do computador também são iguais. Determinante na solução que usa (somente) uma camada de switch e case  para aquele "desafio".

 

5 horas atrás, arfneto disse:

Tem razão. É a mesma coisa mas fica mais fácil de ler. Provavelmente se escrever assim:

Nossa odeio quando os meus alunos (os mais "fraquinhos") dizem o mesmo... poque isso 😞  é evasiva (sem justificativa) porque é uma limitação pessoal/ gosto pessoal no caso estilo. Sempre digo que estilo é algo que só importa alguém se esse trabalha na sua equipe, pois cada equipe define as configurações de estilo e com isso evita discussões inúteis.

 

Uma união é uma categoria de dado especial disponível em C que permite armazenar diferentes categorias de dados no mesmo local de memória.

#include"stdio.h"
#include"stdlib.h"
int
main (void) {
  union {char Chars[sizeof(int)]; int Int;} estado = {"SP"};
  printf ("O resultado e igual: %s\n", estado.Int == ('S'|'P' << 8) ? "SIM" : "não");
  (void) estado;
  return 0;
}

O conceito de “strings” aqui é mais abstrato que aquele dos antigos e adeptos  programadores/experientes em C  ensinam... o inteiro do lado oposto da varável é sim uma "strings" porque em sua memória há dois ‘bytes’ não nulos seguindo de outros nulos igual à variável 'estado'.

 

#1

5 horas atrás, arfneto disse:
int indice = 0;
    if (1 != scanf("%2s", Dual.estado)) indice = 4;
    switch (Dual.numero)
    {
        case SP: indice = 3;
            break;
        case MG: indice = 0;
            break;
        case RJ: indice = 2;
            break;
        case MS: indice = 1;
            break;
        default: indice = 4;
            break;
    }

Essa condicional IF inicial não tem sentido porque faz o que a 'default'  existe para fazer. Digamos que importa saber que toda switch e case são condicionais que um pouco mais analiticamente pode ter o seguinte aspecto:

int indice = 0;
    if (1 != scanf("%2s", Dual.estado)) indice = 4;
    if (Dual.numero == SP) {
       indice = 3;
    }
    else if (Dual.numero == MG) {
       indice = 0;
    }
    else if (Dual.numero == RJ) {
        indice = 2;
    }
    else if (Dual.numero == MS) {
        indice = 1;
    }
    else {
         indice = 4;
    }
    printf("%s\n", estados[indice]);

A primeira condicional examina o 'return' da 'scanf' de 1 especificador, para quê? Para atribuir último índice de um vetor, cuja utilidade persiste durante a função, mas só é útil em uma ocasião e está logicamente acobertado pelo que se chama "Otherwise" (por outro lado)/último else de uma cascata de IF-ELSE.

 

Melor ficou por último

*E aspas mudam de lugar de um teclado para outro. O 0 não,

[🙂] — sem comentários... Mas, digo que achar as "" é problema pessoal (de poucos) e se resolve.

 

 

 

 

 

Postado
12 horas atrás, .if disse:

off...

@mauro_b corrija a gramática da sua assinatura. Está me incomodando e não, não quero 'ignorá-la' 😁

Tive numa discussão pouco semelhante (mais acalorado) com 5 pessoas de um fórum fechado em Portugal que até a moderação entrou na lista de desleixados, é sério! Revendo postagens antigas, notei que aqui também houve discussões semelhantes (no tempo do AnsiC há ~10 anos e outras recentemente no privado: para piorar... odeio privado), mas diferente de ti, que foste de uma observação divertida, outro foi para ridicularizar/constranger.

 

Eu faço o meu melhor sem cobrar muito de mim 😄 

Esses que curtem ridicularizar o fazem naturalmente porque todos nós procuramos o destaque. Entendo ser perfeitamente normal quando é um jovem, já para os demais eu não tenho paciência mesmo.

 

[🙂 Off-tópico  assim é bem legal.

 

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