2016-08-15 4 views
1

Я немного схожу с ума, пытаясь использовать очень простую операционную функцию в C как новичок, но кажется, что все, что я пробовал, не удалось, хотя и должно работать.Пытаясь сделать простую функцию do_operation в C

#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); 
} 

Похоже, в ближайшее время в качестве второго аргумента, который является оператором, проходит через функцию calcul, это изменить фактический характер в либо это значение ASCII или что-то другое, что не распознано в состоянии ,

Я пробовал возиться со многими способами и искать другие фрагменты, но это именно то, что они делали и как оно должно работать (даже если я удалю printf), так что я делаю неправильно?

EDIT Извините, я намеренно изменяю количество аргументов, чтобы получить segfault для чего-то еще, вот «правильная» функция, которую я тестирую, для которой у меня возникает проблема.

Кроме того, как я буду использовать эту функцию посредством выполнения простой скомпилированной проги под этим форматом в скорлупе:

./a.out 2 * 3 

решаемых Как отметил @ Mike при входе в функции высчитывает, ава [2 ], который является оператором, теперь считался первым и единственным символьным аргументом, поэтому он должен был отождествляться с av [0]. Это немного запутанно/сложно.

+0

Если вы используете оболочку, это может быть интерпретация вашего оператора как шаблона и замена вашего расширения, когда вы его получите в своей программе. – jxh

+0

Как точно эта программа должна быть вызвана? – dbush

+0

также появляется, что вы обращаетесь за пределы массива 'char ** av'. Если' ac == 4', то единственными действительными индексами для 'av' являются 0 до 3. – yano

ответ

2

У вас неверное индексирование. Я немного изменил код, предположив, что вы хотите напечатать символ оператора, чтобы убедиться, что он работает.

#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); 
} 

Обратите внимание на ваш calcul Funciton вы называли av[2] который является пытается получить третий индекс строки, содержащей только ваш символ оператора, который является NULL.

ETA:

Также примечание на оператора *. Чтобы заставить его работать, вам нужно вызвать его с помощью escape-символа \.

ETA2:

Измененный код в соответствии с правок в ответ, чтобы он мог быть вызван:

./a 3 + 4 
./a 3 '*' 9 
+1

Вы также можете использовать одинарные кавычки: вокруг звездочки при вызове программы 'calculate '*'' 5 4 – FredK

+0

Я компилирую и запускаю программа в этой форме: ./a.out 2 * 3 Таким образом, оператор должен быть av [2], но он его не читает. – yazze

+0

@yazze Простое исправление. Изменим вычисление линии (atoi (av [3]), atoi (av [2]), av [1])), чтобы вернуться к вычислению (atoi (av [1]), atoi (av [3]), av [ 2])) с тем же кодом в ответе и измените инструкции printf соответственно, чтобы показать 'av [2]'. Однако сохраните оператор «av [0]» как есть в операторах if. – Mike

0

Просто прослеживание на свой вопрос в комментариях ...

Аргументы передаются c программам в виде массива строк; то есть список строк. Строка c - это список символов, поэтому список строк - это 2-й массив или матрица символов. Каждая строка имеет индекс.Каждый char в строке имеет индекс Вы можете визуализировать его в виде сетки:

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

Так что, если вы звоните программа ./a.out 3 '*' 9, char** av содержит 4 строки:

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

Конечно, c струны NULL-terminated, поэтому в виде сетки вы увидите

      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 

Первый символ каждой строки начинается при индексе 0; например, строка 0, символ 0 «а», или

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

Итак, когда вы передаете av[2] к вашей функции, вы передаете char* на весь третий-строковый аргумент (который в данном случае состоит только из 1 char, символ *). Поэтому в функции calcul Майк правильно проверяет первую строку char строки, в которой находится оператор. В функции calculav[1] содержит строку-терминатор NULL byte \0 и av[2] и выше - неопределенные индексы. Я бы рекомендовал изменить имя аргумента av в функции calcul на что-то другое, чтобы вы не путали его с аргументом av от main.

Просто помните, что в этом случае char** av представляет собой список строк (где каждый индекс 0, 1, 2 и т. Д. Адресует строку в этом списке, а char* av - это одна строка (где каждый индекс 0, 1, 2, и т. Д., Обращается к символу в этой строке).