powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
12 сообщений из 12, страница 1 из 1
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38574891
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.

K&RУпражнение 5-7.
Напишите программу ADD, вычисляющую обратное польское выражение из
командной строки. Например,
ADD 2 3 4 + *
вычисляет 2*(3+4).

Код написал ещё вчера на листочке. Сегодня проверял, возникло несколько вопросов. Программа не дописана до конца. Ещё разбираюсь.
Сам код:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
//Операция ли я на входе ? 
bool isOperation(char* start)//принимает указатель на начало строки
//1.1 1.2
{
	switch (*start)
	{
	case '*':
		return true;
	case '/':
		return true;
	case '-':
		return true;
	case '+':
		return true;
	default:
		return false;
	} 
}

//выполнение 1 бинарной операции над 2 числами float
float operation_by_2f(float a, float b, char* operation)//принимает 2 числа и указатель на операцию над ними
{
	//2.1 2.2 2.3
	//2.4
	switch (*operation)
	{
	case '*':
		return a*b;;
	case '/':
		return a/b;
	case '-':
		return a-b;
	case '+':
		return a+b;
	default:
		return 0;
	}
}


int main(int argc, char* argv[]) //_TCHAR  _tmain
{
		
	char** end_numbers = argv-1;//элемент до '\0' в argv
	argv--;//сдвигаю с null так как сейчас argv на последней позиции
	//3
	while (argc>1 && isOperation(*argv--))//иду с конца массива. Пока операции над числами
	{
		printf("%i", isOperation(*(argv+1)));
		--end_numbers;
		--argc;//может и не надо. Пока пусть будет дополнительная проверка
	}
	char** start_operations = end_numbers + 1;//начиная с этого адреса, до argv+argc-1 
					       //в закрытом промежутке хранятся операции над числами 
	
	//float result = operation_by_2f(**end_numbers, **(end_numbers - 1), *start_operations);
	float result = operation_by_2f((float)**end_numbers, 3, *start_operations);//проверяю что не так выше
	//4
	//**end_numbers = -2;
	//**start_operations = +1;
	/*
	while (end_numbers>argv)//этот цикл я называю "цветок одна сторона которого обращена к солнцу"
	{
		result = operation_by_2f(result, **(end_numbers - 1), *start_operations);
		**end_numbers = -2;
		**start_operations = +1;
	}*/
	printf("\n%f", result);

	return 0;
}



У меня возникли следующие вопросы:

1.1 Не нравится алгоритм. Как бы сделали вы ?
1.2 Не нравится реализация. Как бы сделали вы ?

2.1 Как бы её назвать лучше?
2.2 Существует ли другой алгоритм ? Как бы мне вставить в код значение char, или так лучше не делать ?
Но в любом случае, как это сделать ?
2.3 Обратите внимание что в функциях 1 и 2 основная часть кода повторяется, как бы от этого избавить, да и
проверка на то какой символ на входе происходит дважды. Мне это не нравится.
2.4 Если на входе int то нужно ли явное преобразование к float ?

3. Час потратил пытаясь понять почему argv+argc-1 не указывает на предпоследний элемент (если посл '\0')
! Почему ? .

4. А вот тут начались проблемы с преобразованием, я понял что прибавляю код числа из ASCII. Читать K&R дальше ?
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38574896
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercury,

1. У вас алгоритм неверный.
Вычислить польскую запись можно двумя способами.
1) Слева направо с использованием явного стека.
2) Справа налево с использованием рекурсии.

Вы пытались реализовать второй, но без рекурсии. Это не работает.

Алгоритм для 1)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
цикл
   читаем следующий арг слева направо
   если число то 
      вставляем его на вершину стека
   если операция то 
      извлекаем из вершины стека 2 числа (или одно, смотря какая операция), 
      вычисляем операцию, 
      вставляем результат на вершину стека
конец цикла
результат  - число на вершине стека
(если стек пустой или там больше одного значения, значит выражение было некорректным)



Алгоритм для 2)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
функция eval (массив)
  извлечь последний элем-т массива (с укорочением массива)
  если это число то
     вернуть его
  если операция то
     вычислить арг2 = eval(массив)
     вычислить арг1 = eval(массив)
     вычислить операцию с арг1 и арг2
     вернуть результат вычисления  
конец функции



3.
Код: plaintext
1.
2.
	char** end_numbers = argv-1;//элемент до '\0' в argv
	argv--;//сдвигаю с null так как сейчас argv на последней позиции


Это ересь. Нелья уменьшать argv. Это выход за границы массива (перед началом).
Изначально argv указывает на 0-й аргумент, которым является имя программы.
Обычно это имя никому не нужно, поэтому чтобы не путаться первым действием можно выполнить
Код: plaintext
1.
2.
argv++;
argc--;


После этого argv будет указывать на реальный первый арг, а argc содержать кол-во арг-ов.

Если вы идете с конца массива аргументов то, делайте так
Код: plaintext
1.
2.
argv[argc - 1] // обращение к последнему элементу
argc--  // удаление последнего элемента




4. Чтобы из строки char* получить float используйте ф-ю atof()
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38574923
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercury4. А вот тут начались проблемы с преобразованием, я понял что прибавляю код числа из ASCII. Читать K&R дальше ?
Тут почитай про преобразования http://www.sql.ru/forum/1077384/kak-pravilno-privesti-tip-v-funkcii-konvertacii-sistemy-ischisleniya

Хотя тебе вполне хватит функции strtol()
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38574949
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
оййй. указатель на argv был на конце, тк я выше оставил код для вывода массива аргументов на экран, а в нём argv++ была запись
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38574951
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
while (end_numbers>argv)//этот цикл я называю "цветок одна сторона которого обращена к солнцу"
	{
		result = operation_by_2f(result, **(end_numbers - 1), *start_operations);
		**end_numbers = -2;
		**start_operations = +1;




вообще бред написал
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38574955
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Написал ! Алгоритм не переделывал, всё работает вроде-бы. Проверьте пожалуйста.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
//Операция ли я на входе ? 
bool isOperation(char* start)//принимает указатель на начало строки
//1.1 1.2
{
	switch (*start)
	{
	case '*':
		return true;
	case '/':
		return true;
	case '-':
		return true;
	case '+':
		return true;
	default:
		return false;
	} 
}

//выполнение 1 бинарной операции над 2 числами float
float operation_by_2f(float a, float b, char* operation)//принимает 2 числа и указатель на операцию над ними
{
	//2.1 2.2 2.3
	//2.4
	switch (*operation)
	{
	case '*':
		return a*b;;
	case '/':
		return a/b;
	case '-':
		return a-b;
	case '+':
		return a+b;
	default:
		return 0;
	}
}

//обратное польское выражение
int main(int argc, char* argv[]) //_TCHAR  _tmain
{
	char** end_numbers = argv+argc-1;//элемент до '\0' в argv
	printf("%s", *argv);
	while (argc>1 && isOperation(*(argv+argc-1)))//иду с конца массива. Пока операции над числами
	{
		printf(" %i", isOperation(*(argv + argc - 1)));//вывод на экран,для себя
		--end_numbers;
		--argc;//иду к следующему элементу
	}
	char** start_operations = end_numbers + 1;//начиная с этого адреса, до argv+argc-1 
										     //в закрытом промежутке хранятся операции над числами 
	
	float result = operation_by_2f(atof(*end_numbers), atof(*(end_numbers - 1)), *start_operations);
	//4
	end_numbers -= 2;
	start_operations += 1;
	printf("%s %s", *end_numbers, *start_operations);
	while (end_numbers>argv)//этот цикл я называю "цветок одна сторона которого обращена к солнцу"
	{
		result = operation_by_2f(result, atof(*(end_numbers)), *start_operations);
		end_numbers -= 2;
		start_operations += 1;
	}
	printf("\n%f", result); 

	return 0;
}
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38574964
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky 1. У вас алгоритм неверный.

фраза "вроде-бы работает", мне не нравится. Вы имели ввиду что он неоптимальный ?

Dima T, спасибо. я про них почитаю конечно, но мне хочется сначала понять как бы я сам написал такую функцию, потому пока не буду читать как они уже работают. В том числе и atof, на выходных буду думать
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38574975
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Только вот так должно быть

Код: plaintext
1.
2.
3.
4.
5.
6.
while (end_numbers>argv)//этот цикл я называю "цветок одна сторона которого обращена к солнцу"
	{
		result = operation_by_2f(result, atof(*(end_numbers)), *start_operations);
		[color=red] end_numbers -= 1; [/color]
		start_operations += 1;
	}



не окрашивается код (
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38575288
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryфраза "вроде-бы работает", мне не нравится. Вы имели ввиду что он неоптимальный ?
Нет, я имел в виду что он вообще неверный. (Хотя в вашем случае работает, но только потому что числа у вас в примере все слева от операций)
А например, попробуйте вычислить вашим алго. такое выражение:
3 4 + 2 *
по нашему (3+4)*2

SashaMercuryне окрашивается код (
В теге SRC используйте пару >>> <<< для выделения текста.
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38575877
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Согласен, не получится. Но и те алгоритмы выше, не вычислят то выражение что я подаю на вход. Разве нет ? Это просто немного разные задачи. Классический задача, и задача в K&R ?
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38575891
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryСогласен, не получится. Но и те алгоритмы выше, не вычислят то выражение что я подаю на вход. Разве нет ? Это просто немного разные задачи. Классический задача, и задача в K&R ?Алгоритмы которые показал Анатолий - вычислят.
Реализуй первый (он проще) и сам увидишь. Заодно со стеком разберешься.
...
Рейтинг: 0 / 0
K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
    #38576525
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlАлгоритмы которые показал Анатолий - вычислят.
Реализуй первый (он проще) и сам увидишь. Заодно со стеком разберешься.

Уезжаю в конце недели на месяц, приеду, изучу структуры и реализую на стеке.
Спасибо.

Я писал

SS
Код: plaintext
1.
char** end_numbers = argv+argc-1;//элемент до '\0' в argv



Справа у меня указатель на указатель, потому слева тип переменной имеет такой тип данных. Но по факту я храню адрес памяти размером в 4 байта. Можно ли объявить какой-нибудь указатель общего вида в этом случае, а при использовании сделать приведение типов ?
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / K&R 5.11 ex 5.7 Обратное польское выражение. Преобразование типов. Алгоритм.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]