Мне поручено написать программу, которая спрашивает пользователя, сколько денег ему нужно потратить, а затем спрашивает пользователя, сколько билетов он хочет купить. У меня должна быть функция main() и функция PurchaseTickets(). Я новичок в указателях и совершенно не понимаю, как их использовать для назначения локальных переменных и использования этих локальных переменных в вычислениях. Могу ли я получить некоторое представление о том, где я ошибаюсь, и как превратить это в полезную программу?
Обновлено: должно быть две функции: основная и покупка билетов. необходимо использовать указатель для переменной оставшихся денег, и программа должна вернуть 0, если у пользователя недостаточно денег для покупки билетов.
#include <stdio.h>
#define ADULT_TICKET_PRICE 69.00 //define constants
#define CHILD_TICKET_PRICE 35.00
int PurchaseTickets(double *pRemainingCash, int adultTickets, int childTickets); //declare function PurchaseTickets()
int main(void)
{
double funds;
int childTickets;
int adultTickets;
printf("How much money do you have to purchase tickets?\n");
if (scanf("%lf", &funds) != 1) //check for errors in user input
{
printf("Invalid input, exiting program.\n");
return 1; //will exit program if invalid characters are entered
}
printf("How many child tickets would you like to purchase?\n");
if (scanf("%d", &childTickets) != 1) //check for errors in user input
{
printf("Invalid input, exiting program.\n");
return 1; //will exit program if invalid characters are entered
}
printf("How many adult tickets would you like to purchase?\n");
if (scanf("%d", &adultTickets) != 1) //check for errors in user input
{
printf("Invalid input, exiting program.\n");
return 1; //will exit program if invalid characters are entered
}
double *pfunds = &funds;
PurchaseTickets(pfunds, adultTickets, childTickets);
return 0;
}
/*****************************************************************************************
*
* Function: PurchaseTickets()
*
* Parameters:
*
* pRemainingCash - points to a variable containing the amt of cash from user
* adultTickets - specifies the number of adult tickets the user wants to buy
* childTickets - specifies the number of child tickets the user wants to buy
*
* Description:
*
* The function will determind if the user has enough money to purchase the
* specified number of tickets. If they do, the function deducts the proper funds
* from their remaining cash and returns the total number of tickets purchased.
* if they do not the function returns 0.
*
*****************************************************************************************/
int PurchaseTickets(double *pRemainingCash, int adultTickets, int childTickets)
{
double adultCost = (adultTickets * ADULT_TICKET_PRICE);
double childCost = (childTickets * CHILD_TICKET_PRICE);
double totalCost = adultCost + childCost;
int totalTickets = adultTickets + childTickets;
double remainingCash = *pRemainingCash;
pRemainingCash = &remainingCash;
pRemainingCash = remainingCash - totalCost;
if (*pRemainingCash >= totalCost)
{
printf("You have purchased %d tickets, and you have %.2f remaining.",totalTickets, pRemainingCash);
}
else
{
printf("You do not have enough money to purchase the tickets.");
return 0;
}
return 1;
}





Я просмотрел ваш код и, судя по тому, что я видел как желаемое решение, указатели действительно не нужны для контекста цели этой программы. Во-первых, поскольку функция «PurchaseTickets» на самом деле не возвращает никакой необходимой информации, имеет смысл настроить ее с помощью возвращаемой записи void. Во-вторых, поскольку все необходимые входные переменные для функции можно просто передать как значения, в отправке ссылок на указатели действительно нет необходимости.
Чтобы минимально внести минимальные изменения в ваш код, следующие операторы можно закомментировать в вашей функции вместе с рефакторингом оператора printf.
//double remainingCash = *pRemainingCash; // Not needed
//pRemainingCash = &remainingCash;
//pRemainingCash = remainingCash - totalCost;
if (*pRemainingCash >= totalCost)
{
printf("You have purchased %d tickets, and you have %.2f remaining.",totalTickets, *pRemainingCash - totalCost); // Note remainder calculation
}
Это привело к следующему тестовому выводу на терминале.
craig@Vera:~/C_Programs/Console/TicketPurchase/bin/Release$ ./TicketPurchase
How much money do you have to purchase tickets?
800
How many child tickets would you like to purchase?
4
How many adult tickets would you like to purchase?
4
You have purchased 8 tickets, and you have 384.00 remaining.
Принимая во внимание наблюдения за кодом и упрощая ситуацию, ниже приведена реорганизованная версия вашей программы.
#include <stdio.h>
#define ADULT_TICKET_PRICE 69.00 //define constants
#define CHILD_TICKET_PRICE 35.00
void PurchaseTickets(double pRemainingCash, int adultTickets, int childTickets); //declare function PurchaseTickets()
int main(void)
{
double funds;
int childTickets;
int adultTickets;
printf("How much money do you have to purchase tickets? ");
if (scanf("%lf", &funds) != 1) //check for errors in user input
{
printf("Invalid input, exiting program.\n");
return 1; //will exit program if invalid characters are entered
}
printf("How many child tickets would you like to purchase? ");
if (scanf("%d", &childTickets) != 1) //check for errors in user input
{
printf("Invalid input, exiting program.\n");
return 1; //will exit program if invalid characters are entered
}
printf("How many adult tickets would you like to purchase? ");
if (scanf("%d", &adultTickets) != 1) //check for errors in user input
{
printf("Invalid input, exiting program.\n");
return 1; //will exit program if invalid characters are entered
}
PurchaseTickets(funds, adultTickets, childTickets);
return 0;
}
/*****************************************************************************************
*
* Function: PurchaseTickets()
*
* Parameters:
*
* pRemainingCash - points to a variable containing the amt of cash from user
* adultTickets - specifies the number of adult tickets the user wants to buy
* childTickets - specifies the number of child tickets the user wants to buy
*
* Description:
*
* The function will determind if the user has enough money to purchase the
* specified number of tickets. If they do, the function deducts the proper funds
* from their remaining cash and returns the total number of tickets purchased.
* if they do not the function returns 0.
*
*****************************************************************************************/
void PurchaseTickets(double pRemainingCash, int adultTickets, int childTickets)
{
double adultCost = (adultTickets * ADULT_TICKET_PRICE);
double childCost = (childTickets * CHILD_TICKET_PRICE);
double totalCost = adultCost + childCost;
int totalTickets = adultTickets + childTickets;
pRemainingCash -= totalCost;
if (pRemainingCash >= 0.00)
{
printf("You have purchased %d tickets, and you have %.2f remaining.\n",totalTickets, pRemainingCash);
}
else
{
printf("You do not have enough money to purchase the tickets.\n");
}
return;
}
Обратите внимание на следующие уточнения:
После этих доработок последовала серия дополнительных тестов программы и функции покупки билетов.
craig@Vera:~/C_Programs/Console/TicketPurchase/bin/Release$ ./TicketPurchase
How much money do you have to purchase tickets? 300.00
How many child tickets would you like to purchase? 4
How many adult tickets would you like to purchase? 4
You do not have enough money to purchase the tickets.
craig@Vera:~/C_Programs/Console/TicketPurchase/bin/Release$ ./TicketPurchase
How much money do you have to purchase tickets? 600
How many child tickets would you like to purchase? 4
How many adult tickets would you like to purchase? 4
You have purchased 8 tickets, and you have 184.00 remaining.
Напомним, что будут веские причины для передачи адресов переменных вместо значений переменных внутри функций, но всегда следует учитывать контекст функции, чтобы определить, необходимо это или нет. Вероятно, было бы разумно поискать дополнительные руководства по определению функций и тому, когда указатели полезны.
Это путаница. Не повторяя комментарии @NoDakker, ниже приведена сокращенная версия кода, показывающая необходимые операции. Обратите внимание, что некоторые переменные были переименованы (а комментарии удалены) для большей ясности.
// heading stuff omitted for brevity
int main(void)
{
double funds;
int childTickets;
int adultTickets;
/* Get funds */ // omitted for brevity
/* Get # of Child tickets */
/* Get # of Adult tickets */
int totTckts = PurchaseTickets( &funds, adultTickets, childTickets );
// Notice that the function performs its task.
// Reporting those results belongs in the calling function
if ( totTckts )
printf( "%d tickets, and you have %.2f remaining.", totTckts, funds );
else
printf( "Insufficient funds to purchase those tickets." );
return 0;
}
int PurchaseTickets( double *pFunds, int nAdult, int nChild )
{
double Cost
= (nAdult * ADULT_TICKET_PRICE)
+ (nChild * CHILD_TICKET_PRICE);
if ( *pFunds < Cost ) // Insufficient available funds?
return 0; // no show
*pFunds -= Cost; // subtract cost from "double funds;" variable in main()
return nAdult + nChild; // return # of purchased tickets
}
Я ценю ваш вклад! Я новичок в C и определенно все еще учусь. Спасибо вам за помощь! Я думаю, что мой код запутался, когда из-за неправильного понимания указателей я создал переменные, которые использовались неправильно/не были нужны.
Однажды я работал с парнем, который, кажется, думал, что ему «платят фунтами» за количество набранного им кода... Добавление дополнительных переменных, использование длинных имен и бесполезных комментариев (например, «выйдем из программы, если она недействительна»). вводятся символы") только усложнят чтение вашего кода (и для нас, и для вас...) Правильный, чистый, четкий и понятный — вот искомые прилагательные.
Большое спасибо! Я понимаю, насколько излишни мои комментарии, лол. Все мои преподаватели напоминают нам (студентам) о необходимости постоянно комментировать наш код, что, я думаю, заставило меня слишком много комментировать, и я не учел, какое влияние это оказало на общую чистоту программы. Впредь буду более избирательным в своих комментариях!
В «Элементах стиля программирования» авторы приводят пример в программе на Фортране, где комментарий из 4 строк объясняет отсутствие «END», обозначающего конец исходного кода некоторой программы... Предположим, что ваши читатели знакомы с C, но, возможно, захочется узнать, почему в коде были сделаны определенные выборы... Почему, а не что. Наилучшие пожелания вам в будущем... (PS: Выбор 4 строк комментария вместо "КОНЕЦ" был плохим выбором...)
@LeilaJones Чем больше вы пишете кода, тем лучше вы будете комментировать. Я склонен много писать во время написания кода, потому что я делаю своего рода набросок, чтобы разбить задачу, а затем кодирую ее, но мне лучше это очистить, когда я закончу. Вы узнаете, какие из них важны, когда возвращаетесь к написанному ранее коду и не понимаете, почему вы сделали что-то определенным образом. Объяснять, почему вы что-то сделали, — это хорошо, но кода должно быть достаточно, чтобы объяснить, как это сделать. К счастью, чем больше вы пишете кода, тем лучше вы будете давать последовательные имена вещам.
@RetiredNinja Слышишь, слышишь!! :-)
В функции PurchaseTickets есть несколько проблем.
double remainingCash = *pRemainingCash;
pRemainingCash = &remainingCash;
Этот код создает копию значения pRemainingCash, на которое указывает, а затем указывает на локальную копию. Этот код правильный, но кажется, что это неправильно.
pRemainingCash = remainingCash - totalCost;
Здесь вы столкнетесь с ошибкой из-за синтаксиса. Он пытается присвоить указателю значение с плавающей запятой, а не то, на что указывает указатель. Для этого вам нужно *pRemainingCash = remainingCash - totalCost;
Это решит ошибку, но не проблему, поскольку изменяется локальная копия, а не переданное значение.
Другая проблема заключается в том, что вам следует проверить, могут ли они позволить себе билеты, прежде чем вычитать стоимость. Я ожидаю, что если стоимость превысит доступные средства, вы оставите доступные средства без изменений.
Вот очищенная версия:
int PurchaseTickets(double *pRemainingCash, int adultTickets, int childTickets)
{
double adultCost = (adultTickets * ADULT_TICKET_PRICE);
double childCost = (childTickets * CHILD_TICKET_PRICE);
double totalCost = adultCost + childCost;
int totalTickets = adultTickets + childTickets;
if (*pRemainingCash >= totalCost)
{
// Subtract cost here
*pRemainingCash -= totalCost;
// Note *pRemainingCash in the next line.
// You need to dereference to obtain the value pointed at.
printf("You have purchased %d tickets, and you have %.2f remaining.",
totalTickets, *pRemainingCash);
// Return success
return totalTickets;
}
// This code won't be reached in the success case because of the return.
// Removing the else avoids the possibility of the compiler warning that
// all paths do not return a value.
printf("You do not have enough money to purchase the tickets.");
return 0;
}
Еще одно небольшое предложение в main.
Вместо double *pfunds = &funds; просто вызовите функцию, например PurchaseTickets(&funds, adultTickets, childTickets);
То, что у вас есть, работает, но я думаю, что лучше не создавать дополнительную переменную только для этого. Если бы после этого был еще код, можно было бы запутаться, какой из них использовать.
Да, для присваивания необходим указатель на оставшуюся переменную Cash, прошу прощения за путаницу! Я отредактирую основной пост, чтобы сделать требования к заданию более понятными. Я по-прежнему ценю ваш вклад, поскольку он дает мне лучшую отправную точку для дальнейших попыток выяснить указатели!