Me estoy volviendo un poco loco intentando una función de operación muy simple en C como principiante, pero parece que todo lo que intento falló, aunque se supone que funciona.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int     calcul(int nb1, int nb2, char *av)
{
        int nb = 0;
        if (av[2] == '*')
                nb = nb1 * nb2;
        if (av[2] == '%')
                nb = nb1 % nb2;
        if (av[2] == '/')
                nb = nb1 / nb2;
        if (av[2] == '+')
                nb = nb1 + nb2;
        if (av[2] == '-')
                nb = nb1 - nb2;
        return (nb);
}

int     atoi();

int     main(int ac, char **av)
{
        printf("%s", av[2]);
        if (ac == 4)
                printf("%d", calcul(atoi(av[1]), atoi(av[3]), av[2]));
        return (0);
}

Parece que tan pronto como el segundo argumento, que es el operador, pasa por la función calcul, cambia el carácter real a su valor ASCII u otra cosa, por lo que no se detecta correctamente en la condición.

He intentado manipular el violín de muchas formas y buscar otro fragmento, pero esto es exactamente lo que estaban haciendo y cómo se supone que funciona (incluso si elimino el printf), entonces, ¿qué estoy haciendo mal?

EDITAR Lo siento, cambié intencionalmente el número de argumentos para obtener un error de segmentación para otra cosa, aquí está la función "correcta" que estoy probando para la que obtengo el problema.

Además, la forma en que estoy usando esta función es ejecutando un programa compilado simple bajo este formato en el shell:

./a.out 2 * 3

SOLUCIONADO Como @Mike señaló al ingresar a la función calcular, av [2], que es el operador, ahora se consideraba el primer y único argumento de carácter, por lo que debía identificarse con av [0]. Lo cual es un poco confuso / complicado.

1
yazze 15 ago. 2016 a las 21:43

2 respuestas

La mejor respuesta

Tiene su indexación incorrecta. Cambié un poco el código asumiendo que querías imprimir el carácter del operador para asegurarte de que funcionaba.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int     calcul(int nb1, int nb2, char *av)
{
        int nb = 0;
        printf("%c\n", av[0]);
        if (av[0] == '*')
                nb = nb1 * nb2;
        if (av[0] == '%')
                nb = nb1 % nb2;
        if (av[0] == '/')
                nb = nb1 / nb2;
        if (av[0] == '+')
                nb = nb1 + nb2;
        if (av[0] == '-')
                nb = nb1 - nb2;
        return (nb);
}

int     main(int ac, char **av)
{
        printf("%s\n", av[2]);
        if (ac == 4)
                printf("%d\n", calcul(atoi(av[1]), atoi(av[3]), av[2]));
        return (0);
}

Observe en su función calcul que estaba llamando a av[2], que es el intento de obtener el tercer índice de una cadena que contiene solo su carácter de operador, que es NULL.

ETA:

También una nota sobre el operador *. Para que funcione, debe llamarlo con un carácter de escape \.

ETA2:

Se modificó el código para que coincida con las ediciones en la respuesta para que se pueda llamar con:

./a 3 + 4
./a 3 '*' 9
2
yano 16 ago. 2016 a las 00:36

Solo un seguimiento de tu pregunta en los comentarios ...

Los argumentos se pasan a los programas c como una matriz de cadenas; es decir, una lista de cadenas. Una cadena c es una lista de caracteres, por lo que una lista de cadenas es una matriz bidimensional o una matriz de caracteres. Cada cadena tiene un índice. Cada char dentro de una cadena tiene un índice. Puedes visualizarlo como una cuadrícula:

                           Index of char in string
                         _|_0_|_1_|_2_|_3_|_4_|_5_| ... etc
                         0|___|___|___|___|___|___|___
                         1|___|___|___|___|___|___|___
                         2|___|___|___|___|___|___|___
Index of string in list  3|___|___|___|___|___|___|___
                         4|___|___|___|___|___|___|___
                         5|___|___|___|___|___|___|___
                        ... etc

Entonces, si llama a su programa ./a.out 3 '*' 9, char** av contendrá 4 cadenas:

av[0] = "a.out"
av[1] = "3"
av[2] = "*"
av[3] = "9"

Por supuesto, las cadenas c tienen terminación NULL, por lo que en la vista de cuadrícula, verá

                           Index of char in string
                         _|_0_|_1_|_2_|_3_|_4_|_5_| ... etc
                         0|_a_|_._|_o_|_u_|_t_|\0_|___
                         1|_3_|\0_|___|___|___|___|___
                         2|_*_|\0_|___|___|___|___|___
Index of string in list  3|_9_|\0_|___|___|___|___|___
                         4|___|___|___|___|___|___|___
                         5|___|___|___|___|___|___|___    
                        ... etc

El primer carácter de cada cadena comienza en el índice 0; por ejemplo, string 0, char 0 es 'a', o

av[0][0] = 'a'
av[1][0] = '3'
av[2][0] = '*'
av[3][0] = '9'

Entonces, cuando pasa av[2] a su función, está pasando un char* a todo el argumento de la tercera cadena (que en este caso solo consta de 1 char, el * personaje). Por lo tanto, en la función calcul, Mike está verificando correctamente el primer char de la cadena, que es donde reside el operador. En la función calcul, av[1] contiene el byte NULL del terminador de cadena \0, y av[2] y superiores son índices no definidos. Recomendaría cambiar el nombre del argumento av en la función calcul a otra cosa para que no lo confunda con el argumento av de main.

Solo recuerde, en este caso, char** av es una lista de cadenas (donde cada índice 0, 1, 2, etc., se dirige a una cadena en esa lista, y char* av es una sola cadena (donde cada índice 0, 1, 2, etc., se dirige a un carácter en esa cadena).

0
yano 16 ago. 2016 a las 18:04