Постоянно повторяйте функцию, пока пользователь не скажет «Стоп»? - PullRequest
0 голосов
/ 09 ноября 2018

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

Я пытался использовать цикл do while, а также простой цикл while. Но я не могу понять, что я делаю неправильно?

#include <iostream>
#include <iomanip>

using namespace std;

void getTime24(int& hour, int& minute);
bool daylightSavingsTime(bool& DST);
int  convertTime24to12(int hour);
void printTime24(int hour, int minute);
void printTime12(int hour, int hour12, int minute);
void printJapanTime(int hour, int minute, bool DST);
bool userWantsToContinue(bool& repeat);

int main() {
int hour = 0;
int hour12 = 0;
int minute = 0;
bool DST = false;
bool repeat = true;

while (repeat == true) {
    // Enter a time value
    getTime24(hour, minute);

    // Check for daylight savings time
    daylightSavingsTime(DST);
    cout << endl;

    // Convert to 12 hour format
    hour12 = convertTime24to12(hour);

    // Print the time in 24 hour format
    printTime24(hour, minute);
    cout << " in Portland." << endl;

    // Prints out the time and the AM/PM designation (e.g. 14:32 becomes 2:32 PM)
    printTime12(hour, hour12, minute);
    cout << " in Portland." << endl;
    cout << endl;

    // Prints out the current time in Tokyo
    printJapanTime(hour, minute, DST);
    cout << endl;

    // Continue?
    bool repeat = userWantsToContinue(repeat);
    cout << endl;
    if (repeat == false)
        break;
}

return 0;
}


//FUNCTIONS
//================================================
// This function is to take in and store the 24 hour time.  It stores the times before 
// and after the colon as hours and minutes respectivly, and reads the colon as a char
// then passes all three parts as an input.  The colon is ignored.

void getTime24(int& hour, int& minute) {
char ch;
if (minute == '0') {
    minute = printf("00");
}
else {
    minute = minute;
}

cout << "Enter a time in a 24 hour format (e.g. 14:30): ";
cin >> hour >> ch >> minute;
while (hour > 24 || minute > 59) {
cout << "That is not a valid time.\n";
cout << "Enter a time in a 24 hour format (e.g. 14:30): ";
cin >> hour >> ch >> minute;
}
}
//================================================
// This function checks for daylight savings time which will be used in the time zone
// conversion later.  It takes the first letter of a yes or no answer and turns that
// into a bool answer.

bool daylightSavingsTime(bool& DST) {
char yesNo;
cout << "Is it daylight savings time now? ";
cin >> yesNo;  // Takes only the first letter of the inputed answer to daylight savings

yesNo = tolower(yesNo);  // Converts letter to uppercase to allow for fewer compairsons

if (yesNo == 'y')
    DST = true;
else 
    DST = false;

return DST;
}
//================================================
// This block of code will convert the previously entered 24 hour time and convert it
// to a 12 hour time format.  It will do this by adding 12 to the hours and using the 
// result to determine if the time is AM or PM.  It will return the time to be stored.

int  convertTime24to12(int hour) {
int hour12 = 0;
int timeCheck = hour + 12;

if (timeCheck >= 25) {
    hour12 = timeCheck - 24;
}
else {
    hour12 = timeCheck - 12;
}
return hour12;
}
//================================================
// This block of code will print out the time in a 24 hour format.

void printTime24(int hour, int minute) {

cout << "The current time (24 hour format) is " << hour << ":" << minute;
}
//================================================
// This block of code will print out the 12 hour format of the time by checking the hour
// variable as a reference.  If it detects that it is in the afternoon (i.e. the hour is
// 12 or greater) then it will print out the time as a PM time, otherwise it will print out
// an AM time.

void printTime12(int hour, int hour12, int minute) {

if (hour > 11)
    cout << "The current time (12 hour format) is " << hour12 << ":" << minute << " PM";
else
    cout << "The current time (12 hour format) is " << hour12 << ":" << minute << " AM";
}
//================================================
// This block of code will take daylight savings time into account and convert the current
// time in Portland to the current time in Tokyo.  It will then print out the current time.
// Check time conversions at https://savvytime.com/converter/jst-to-pst/sep-3-2018/11-30am


void printJapanTime(int hour, int minute, bool DST) {
int japanHour = 0;
int japanHour12 = 0;

if (DST == true) {
    if (hour > 8) {
        japanHour = hour - 8; // from hour - 24 hours + 16 hours for the time conversion.
    }
    else {
        japanHour = hour + 16;
    }
    printTime24(japanHour, minute);
    cout << " in Tokyo." << endl;
    japanHour12 = convertTime24to12(japanHour);
    printTime12(japanHour, japanHour12, minute);
    cout << " in Tokyo." << endl;
}
else if (DST == false) {
    if (hour > 7) {
        japanHour = hour - 7; // from hour - 24 hours + 17 hours for the time conversion.
    }
    else {
        japanHour = hour + 17;
    }
    printTime24(japanHour, minute);
    cout << " in Tokyo." << endl;
    japanHour12 = convertTime24to12(japanHour);
    printTime12(japanHour, japanHour12, minute);
    cout << " in Tokyo." << endl;
}
}
//================================================
// This block of code will determine if the user wants to continue the program or not.
// This will be used in a do while loop, as soon as stop becomes true, we exit the loop.

bool userWantsToContinue(bool& repeat) {
char yesNo;

cout << "Would you like to convert another time? ";
cin >> yesNo;

yesNo = toupper(yesNo);  // Converts letter to uppercase to allow for fewer compairsons

if (yesNo == 'Y') {
    repeat = true;
}
else
    repeat = false;
return repeat;
}
//================================================

Спасибо.

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Я понял, в чем проблема. На самом деле было две проблемы.

Я избавился от затененной переменной повтора, как упоминалось другими пользователями выше. В основной функции я переключил тип цикла на цикл do ... while. Я инициализировал переменную bool как true, чтобы цикл не завершался немедленно, поэтому он выглядит примерно так:

// FUNCTION
// Asks the user if they want to go again, 
// if they say yes the function repeats, if no then the program ends.
bool userWantsToContinue(bool repeat);

int main()
  bool repeat = true;

  do {
     ...
     // Continue for another iteration of the loop?
    repeat = userWantsToContinue(repeat);
    cout << endl << endl;
  }while(repeat != false);  // while repeat is true, keep doing the loop

...

//============================================================================================
// This block of code will determine if the user wants to continue the program or not.
// This will be used in a do while loop, in main() as soon as stop becomes true, we exit the loop.

bool userWantsToContinue(bool repeat) {
    char yesNo;
    bool repeat1 = 0;

    cout << "Would you like to convert another time? ";
    cin >> yesNo;
    cin.ignore(100, '\n');

    yesNo = toupper(yesNo);  // Converts letter to uppercase to allow for fewer compairsons

    if (yesNo == 'Y') 
        repeat1 = true;
    else if (yesNo == 'N')
        repeat1 = false;

    return repeat1;
}
//============================================================================================

Кроме того, всякий раз, когда пользователь вводил простую букву Y или N, программа выполнялась бы так, как должна, однако, если бы они вводили полное слово (т. Е. Да или нет), то цикл завершался бы сразу после того, как программа закончила его. итерация. Я решил эту проблему, очистив буфер с помощью команды cin.ignore(NUMBER OF CHARACTERS TO BE IGNORED, 'CHARACTER THAT AUTOMATICALLY CLEARS OUT THE REST OF THE BUFFER IF ENCOUNTERED');.

Если буфер не был очищен, то он сохраняет неиспользуемые буквы (например, если вы введете yes, программа будет использовать Y и сохранит E и S в буфере для дальнейшего использования). Позже в программе, когда он спрашивает пользователя, хотели бы они продолжить другой цикл, компилятор автоматически вводит следующую букву в буфер (в нашем примере, E из YES). Очистка буфера сразу после использования буквы решает проблему.

Так, например, у меня был блок кода, который спрашивал пользователя, было ли в настоящее время летнее время. Прежде чем у меня был этот блок кода:

bool daylightSavingsTime(bool& DST) {
char yesNo;
cout << "Is it daylight savings time now? ";
cin >> yesNo;  // Takes only the first letter of the inputted answer to daylight savings

yesNo = tolower(yesNo);  // Converts letter to uppercase to allow for fewer compairsons

if (yesNo == 'y')
    DST = true;
else 
    DST = false;

return DST;
}

После добавления cin.ignore(100, '\n'); я очистил лишние неиспользуемые буквы. В этом случае я сказал, чтобы игнорировать следующие 100 символов или продолжить, когда встречается новая строка (\ n).

Так что теперь мой фиксированный код выглядит так:

bool daylightSavingsTime(bool& DST) {
    char yesNo;
    cout << "Is it daylight savings time now? ";
    cin >> yesNo;  // Reads only the first letter of the inputted word to daylight savings time
    cin.ignore(100, '\n');  // clears all of the other characters that weren't used (e.g. 'es' in 'yes')

    yesNo = toupper(yesNo);  // Converts letter to uppercase to allow for fewer compairsons

    if (yesNo == 'Y')  // if the inputted word/letter begins with a Y do set the value of DST to true
        DST = true;
    else  // if the inputted word/letter does not begin with a Y then set the value of DST to false
        DST = false;

    return DST;
}

Кстати, оператор else является причиной преждевременного завершения цикла, когда буфер не был очищен заранее. В нашем примере YES, E был следующим символом в буфере. Поскольку E не был использован сразу, он был сохранен на потом. Позже в коде, когда он спрашивает пользователя, хочет ли он сделать еще один цикл, используется та же логика. Если программа встретит Y, она продолжит работу, если она обнаружит что-либо еще, она остановится. Так как E в нашем примере YES был сохранен, и поскольку E не является Y, программа решила, что пора заканчивать.

0 голосов
/ 09 ноября 2018

Ваша логика цикла в порядке, но, как указал Рукс, переменная repeat затенена.

bool repeat = true;   // as written in your program, this variable never changes value
                      // let's call it repeat_1

while (repeat)        // here you test repeat_1
{
    // ...

    // Continue?
    bool repeat = userWantsToContinue(repeat); // here you are declaring a second 
                                               // variable named repeat, why?
                                               // let's call it repeat_2
                                               // it hides the var repeat declared outside the loop.
    cout << endl;
    if (repeat == false)                       // this tests repeat_2, and eventually exits the loop
        break;                                 // I guess that's a fix you made to make 
                                               // your program work.
}
assert(repeat == false);   // this assertion would invariably fail, since repeat_1
                           // is still true.
                           // note that repeat_2 is out of scope, it doesn't exist anymore.

Простая фиксация

bool repeat = true;          
while (repeat)
{
     //...
     repeat = userWantsToContinue(repeat);  // note this is NOT a declaration,
                                            // there is only one variable called repeat
}
assert(repeat == false);   // this assertion would invariably succeed, since
                           // repeat has to be false to exit the loop.

Повторное использование имен во включенной области является распространенным источником ошибок. Теперь вы знаете, чего вам следует избегать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...