Ir ao conteúdo

C Operador "OR" dentro do while


Ir à solução Resolvido por RPGStreamer,

Posts recomendados

Postado

Estou tentando fazer uma função que recebe uma cadeia de caracteres, contendo letras e operadores aritméticos. A ideia é contar quantas letras há antes de encontrar um operador. Exemplo

abc* (3 letras)

abcde+- (5 letras)

Para isso, fiz um while que escaneia a cadeia, incrementando um contador, até encontrar um dos operadores:

int n=0;
while (cadeia[n]!='+' || cadeia[n]!='-' || cadeia[n]!='*' || cadeia[n]!='/') {
n++; //Incrementa o contador até encontrar um dos operadores
}

O programa compila, porém retorna zsh: segmentation fault (core dumped) quando testo alguma cadeia. Entretanto, se eu remover os OR e deixar apenas while (cadeia[n]!='+'), ele funciona como deveria (porém, limitado ao operador de soma). Já consegui fazer uma alternativa usando condicionais, mas gostaria de saber o que está acontecendo.

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

int Qnt_Operandos (char cadeia[]) { //Verifica a quantidade de operandos na cadeia
    int n=0;
    while (cadeia[n]!='+' || cadeia[n]!='-' || cadeia[n]!='*' || cadeia[n]!='/') {
        n++; //Incrementa o contador até encontrar um dos operadores
    }
    return n;
}

//------------------------------------

int main () {
    char cadeia[50];
    gets (cadeia);
    printf ("%d", Qnt_Operandos(cadeia));

    return 0;
}

 

  • Solução
Postado

Ele está acessando memória além do array. Seu while tem que parar antes de acabar a string.

@Pedroernesto64 Aliás, gets está deprecated. Está fora do standard e não precisa ser implementada mais. use fgets (com stdin como o handle do arquivo, pra ler do console).

  • Curtir 1
Postado
1 hora atrás, RPGStreamer disse:

Ele está acessando memória além do array. Seu while tem que parar antes de acabar a string.

@Pedroernesto64 Aliás, gets está deprecated. Está fora do standard e não precisa ser implementada mais. use fgets (com stdin como o handle do arquivo, pra ler do console).

Mas uma vez que ele encontra um dos operadores (+-*/), ele não deveria parar de acessar a memória? Funcionou assim quando fiz o teste do while usando apenas o operador de soma.

Update: O erro estava na minha lógica. Troquei || por &&, e funcionou. Pelo que entendi, ele só parava quando identificava SÓ o +, ou SÓ o -... E por isso estourava a memória.

Obrigado pela dica do fgets também. Vou procurar.

  • Curtir 1
Postado

Eu acho que pra ficar mais seguro, seria algo assim

int n = 0;

for(size_t i = 0; cadeia[i] != '\0'; ++i)
{
	if(cadeia[i] == '+' || cadeia[i] == '-' || cadeia[i] == '*' || cadeia[i] == '/')
	{
		++n;
	}
}

Isso se voce tiver certeza que a funcao nunca vai ser mal usada (ou seja, sempre vão mandar um ponteiro pra char com o caractere nulo '\0' no final, chamado de uma "c-string")

  • Amei 1
Postado

@Pedroernesto64

1 hora atrás, Pedroernesto64 disse:

Pelo que entendi, ele só parava quando identificava SÓ o +, ou SÓ o -... E por isso estourava a memória.

O que acontece é que `n` é incrementado em um loop infinito:

2 horas atrás, Pedroernesto64 disse:
cadeia[n]!='+' || cadeia[n]!='-' || cadeia[n]!='*' || cadeia[n]!='/'

Certo caractere em questão não tem como tornar as 4 condições falsas para que o valor total da expressão seja 0: 0 OU 0 OU 0 OU 0 = 0.

O que você estabeleceu é que caso um caractere seja diferente de + ou de - ou de * ou de /, `n` é incrementado. Você pode tornar uma das condições falsas, não as quatro de uma vez, dessa forma você acaba acessando memória além da que foi alocada para a string conforme `n` é incrementado.

 

1 hora atrás, Pedroernesto64 disse:

O erro estava na minha lógica. Troquei || por &&, e funcionou.

Sim, é isso mesmo. Enquanto certo caractere em questão for diferente dos 4 operadores, você incrementa `n`, e assumindo que os operadores estão posicionados após os demais caracteres, pode usar `n` como índice na string.

No mais, esqueça gets(), é obsoleta. Duas possíveis substitutas aqui pra você:

char cadeia[50];

// Usando fgets
if(fgets(cadeia, sizeof(cadeia), stdin) != NULL) {
    if(cadeia[strlen(cadeia) - 1] == '\n') {
        // '\n' na penultima posição da string
        cadeia[strlen(cadeia) - 1] = '\0';
    } else {
        int ch;
        while((ch = fgetc(stdin)) != '\n' && ch != EOF);
    }
}

// Usando scanf
scanf(" %49[^\n]%*c", cadeia);

 

@RPGStreamer

1 hora atrás, RPGStreamer disse:
int n = 0;

for(size_t i = 0; cadeia[i] != '\0'; ++i)
{
	if(cadeia[i] == '+' || cadeia[i] == '-' || cadeia[i] == '*' || cadeia[i] == '/')
	{
		++n;
	}
}

Acho que assim se está contando os operadores.

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