Хотите написать консольную программу Objective-C для 4-х температурного преобразователя - PullRequest
4 голосов
/ 10 августа 2010

Как некоторые из вас, возможно, видели, как я экспериментировал с программой, конвертирующей из Фаренгейта в Цельсий и наоборот в Objective-C, основанной на вводе и выводе консоли.Я просто делаю это, чтобы лучше выучить язык, и я думаю, что это хороший способ продемонстрировать некоторые вещи, с которыми я сталкивался.

Так что, в любом случае, я собираюсь включить и Кельвин, иРанкин подходит к моей программе, хорошее предложение, которое я хотел бы рассмотреть, предложенное dreamlax.

Теперь, до этого момента, моя программа функционировала относительно хорошо для преобразования между градусами Фаренгейта и Цельсия, но если янужно конвертировать между этими 4 разными шкалами, мне нужно будет по-другому работать с этим, на мой взгляд.

Во-первых, мне нужно предоставить конечному пользователю возможность выбора начальной температуры.температура, из которой они хотят конвертировать.

Чтобы сделать это, мне нужно попросить их с помощью инструкции NSLog или printf, инструктирующей их сделать это.

Теперь я бы предпочелони набирают по Фаренгейту, Цельсию, Кельвину или Ранкину, основываясь на том, какой из них они хотели бы, а не 0-3.Теперь я не думаю, что scanf способен, но если я ошибаюсь, я хотел бы знать, имеет ли он эту функциональность, или это другой метод, которым я могу воспользоваться, чтобы добавить это в свою программу.

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

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

string baseTemp
string targetTemp

NSLog(@"Please type Fahrenheit, Celsius, Kelvin or Rankine to select your base temperature");
scanf or some other method here("string format specifier here" &baseTemp);
NSLog(@"Please type Fahrenheit, Celsius, Kelvin or Rankine to select your target temperature");
scanf or some other method here("string format specifier here" &targetTemp);

Теперь мне нужно лицо, принимающее решение, чтобы решить, есть ли Fahrenheit == baseTemp и Celsius == targetTemp, а затем настройте определенную формулу соответственно.

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

Извините за, вероятно, довольно неловкий код, я пытаюсь использовать то, что яузнал до сих пор здесь.

Любые предложения, настройки, идеи и все, что между ними, высоко ценится!

Спасибо !!

ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ: ОБНОВЛЕНИЕ:

Код для программных файлов class.h, class.m и main.m содержит окончательный код, по крайней мере для этого проекта, который Dreamlax очень помог мне, чтобы мы оба достигли своей цели,Еще раз спасибо Dreamlax !!

class.h:

#import <Cocoa/Cocoa.h>


@interface Temperature : NSObject

{
    double kelvin;
}

//Instance methods to convert argument to kevin
-(void) setFahrenheitValue: (double) f;
-(void) setCelsiusValue: (double) c;
-(void) setKelvinValue: (double) k;
-(void) setRankineValue: (double) r;

//Instance methods for extracting the kelvin value using any scale
-(double) fahrenheitValue;
-(double) celsiusValue;
-(double) kelvinValue;
-(double) rankineValue;

@end

class.m:

#import "class.h"

@implementation Temperature;

-(void) setFahrenheitValue: (double) f
{
    kelvin = ((f + 459.67)*(5.0/9.0));
}

-(void) setCelsiusValue: (double) c
{
    kelvin = (c + 273.15);
}

-(void) setKelvinValue: (double) k
{
    kelvin = k;
}

-(void) setRankineValue: (double) r
{
    kelvin = (r*(5.0/9.0));
}



-(double) fahrenheitValue
{
    return ((kelvin*(9.0/5.0)) - 459.67);
}

-(double) celsiusValue
{
    return (kelvin - 273.15);
}

-(double) kelvinValue
{
    return (kelvin);
}

-(double) rankineValue
{
    return (kelvin * (9.0/5.0));
}

@end

main.m:

#import <Cocoa/Cocoa.h>
#import "class.h"

int main(int argc, char *argv[])
{
    int result;
    int prompt;
    double sourceTemp;

    printf("Please choose a source temperature scale:\n[1] Fahrenheit\n[2] Celsius\n[3] Kelvin\n[4] Rankine\n\n");

    result = scanf("%i", &prompt);

    if (result != 1)
        printf("I couldn't understand your input, I need only one number!");

    else if (result == EOF)
        printf("I apologize, I encountered an error when trying to read your input.");

    else if (result == 1)
    {
    printf("\nNow, please enter the temperature you would like to convert:\n\n");

    scanf("%lf", &sourceTemp);

    Temperature *converter = [[Temperature alloc] init];

    switch (prompt) 
    {
        case 1:
            //end-user chooses Fahrenheit
            [converter setFahrenheitValue:sourceTemp];
            break;

        case 2:
            //end-user chooses Celsius
            [converter setCelsiusValue:sourceTemp];
            break;

        case 3:
            //end-user chooses Kelvin
            [converter setKelvinValue:sourceTemp];
            break;

        case 4:
            //end-user chooses Rankine
            [converter setRankineValue:sourceTemp];
            break;
    }

    printf("\nNow, please choose a target temperature scale:\n[1] Fahrenheit\n[2] Celsius\n[3] Kelvin\n[4] Rankine\n\n");

    scanf("%i", &prompt);

    switch (prompt) 
    {
        case 1:
            //end-user chooses Fahrenheit
            printf("%lf degrees Fahrenheit\n", [converter fahrenheitValue]);
            break;

        case 2:
            //end-user chooses Celsius
            printf("%lf degrees Celsius\n", [converter celsiusValue]);
            break;

        case 3:
            //end-user chooses Kelvin
            printf("%lf degrees Kelvin\n", [converter kelvinValue]);
            break;

        case 4:
            //end-user chooses Rankine
            printf("%lf degrees Rankine\n", [converter rankineValue]);
            break;
    }

    }

}

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

Предположим, что конечный пользователь выбрал Фаренгейт в качестве своего /ее температура источника, желая преобразовать 212 градусов в его / ее целевую шкалу температуры Цельсия.Преобразования должны равняться 100 градусам Цельсия, но я думаю, что программа будет лучше отображать результат следующим образом:

212 градусов Фаренгейт равно 100 градусов по Цельсию.

Теперь я сделал значения, которые нужно заменить на переменные, выделенные жирным шрифтом.У меня есть значения 212 и 100, которые легко решаются, потому что 100 был там, во-первых, и 212 можно легко исправить, заменив его строковым форматером переменной sourceTemp.

Теперь строка Фаренгейтанемного по-другому.

Я попытался установить что-то новое в нашем исходном переключателе, например, так:

switch (prompt) 
{
    case 1:
        //end-user chooses Fahrenheit
        [converter setFahrenheitValue:sourceTemp];
        sourceTempText = 1;
        break;

    case 2:
        //end-user chooses Celsius
        [converter setCelsiusValue:sourceTemp];
        sourceTempText = 2;
        break;

    case 3:
        //end-user chooses Kelvin
        [converter setKelvinValue:sourceTemp];
        sourceTempText = 3;
        break;

    case 4:
        //end-user chooses Rankine
        [converter setRankineValue:sourceTemp];
        sourceTempText = 4;
        break;
}

ОК, поэтому я добавил в каждый другой случай, устанавливая новую переменную с именем sourceTempTextлибо 1-4, то же значение, которое конечный пользователь выбрал, чтобы выбрать его / ее температуру источника.

Теперь вот как я пытался отобразить окончательное приглашение для конечного пользователя с помощью последнего переключателя:

switch (prompt2) 
{
    case 1:
        //end-user chooses Fahrenheit
        printf("%lf degrees sourceTempText is %lf degrees Fahrenheit\n", sourceTemp, [converter fahrenheitValue]);
        break;

    case 2:
        //end-user chooses Celsius
        printf("%lf degrees sourceTempText is %lf degrees Celsius\n", sourceTemp, [converter celsiusValue]);
        break;

    case 3:
        //end-user chooses Kelvin
        printf("%lf degrees sourceTempText is %lf degrees Kelvin\n", sourceTemp, [converter kelvinValue]);
        break;

    case 4:
        //end-user chooses Rankine
        printf("%lf degrees sourceTempText is %lf degrees Rankine\n", sourceTemp, [converter rankineValue]);
        break;
}

Сейчас я не уверен, смогу ли я вставить sourceTempText в строку, как здесь, вместо этого, возможно, мне придется использовать форматировщик строки, но я не уверен.Это должно быть легко исправить, я просто хотел выбросить это здесь!:)

Надеюсь, следующий проект будет ... GUI GUI GUI!XD

1 Ответ

4 голосов
/ 10 августа 2010

Что касается вашего класса, один подход, который я кратко затронул в вашем предыдущем вопросе, мог бы быть:

  1. Он должен хранить значение, используя только одну температурную шкалу.Имейте в виду, что Ранкин для Фаренгейта то же, что Кельвин для Цельсия.Я имею в виду, что Ранкин - просто Фаренгейт, но с другим смещением, а Кельвин - просто Цельсий, но с другим смещением (Ранкин и Кельвин оба считают, что 0 ° абсолютный ноль ),С научной точки зрения, Кельвин был бы хорошим выбором базовой шкалы, поскольку это международный стандарт для измерений температуры (США, Бирма и Либерия - единственные страны, которые не приняли систему СИ).Есть некоторые плюсы и минусы использования только одной температурной шкалы:

    • Будет потеря точности, потому что вы конвертируете дважды (один раз для преобразования исходной шкалы в Кельвин, а затем другойпреобразование для преобразования в желаемый масштаб пользователя)

    • Однако реализация вашего класса будет проще, поскольку существует только одна переменная.

  2. Вам нужен только один экземпляр вашего класса Converter.Когда вы читаете ввод из командной строки, вы сообщаете экземпляру класса Converter значение измерения, а также масштаб, который выбрал пользователь.Например, интерфейс преобразователя может принимать следующие методы:

    @interface Temperature : NSObject
    {
        double kelvin;
    }
    - (void) setCelsiusValue:(double) c; // kelvin = (c + 273.15)
    - (void) setKelvinValue:(double) k; // kelvin = k
    - (void) setFahrenheitValue:(double) f; // kelvin = (f + 459.67) × 5⁄9
    - (void) setRankineValue:(double) r; // kelvin = (f × 5/9)
    @end
    

    Все эти методы должны преобразовывать аргумент в шкалу Кельвина.

  3. Ваш класс должен такжереализовать способы извлечения значения с использованием любого масштаба.Для этой цели могут быть приняты следующие методы:

    @interface Temperature : NSObject
    {
        double kelvin;
    }
    // include methods from above
    - (double) celsiusValue; // return kelvin - 273.15
    - (double) kelvinValue; // return kelvin
    - (double) fahrenheitValue; // return kelvin × 9⁄5 − 459.67
    - (double) rankineValue; // return kelvin × 9/5
    @end
    

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

СЧто касается взаимодействия с пользователем, обычно NSLog используется только для регистрации информации о вашем приложении во время выполнения (например, для проверки значения объекта или для определения точки выполнения в вашем приложении).Для того, чтобы задавать вопросы, обычно более распространенным является использование printf.

. Вы можете распечатать меню следующим образом:

Please choose a source temperature scale:
[1] Celsius
[2] Kelvin
[3] Fahrenheit
[4] Rankine

Затем распечатать другое меню для целевой шкалы температуры, изатем попросите пользователя для измерения температуры источника.Как правило, вы не должны просить пользователя ввести полное слово, потому что его легче набрать, чем простое число.Также есть специальная программная конструкция, называемая switch.Он имеет некоторые оговорки, но хорошо работает с несколькими вариантами ответов на вопросы.После того, как вы прочитали ввод пользователя с помощью scanf, вы можете сделать это:

int prompt;
double sourceTemp;
// use scanf to read values into prompt and sourceTemp variables

Temperature *converter = [[Temperature alloc] init];
switch(prompt)
{
    case 1: // the user chose celsius
        [converter setCelsiusValue:sourceTemp];
        break; // if you don't break, it will execute all other cases

    case 2: // user chose kelvin
        [converter setKelvinValue:sourceTemp];
        break;

    case 3:
        [converter setFahrenheitValue:sourceTemp];
        break;

    case 4:
        [converter setRankineValue:sourceTemp];
        break;
}

// prompt the user again here to determine the target temperature scale
// use the same menu again and read the user's input into the prompt variable

case (prompt)
{
    case 1: // user wants to convert to celsius
         printf("%f degrees C\n", [converter celsiusValue]);
         break;

    case 2: // user wants kelvin
         printf("%f degrees K\n", [converter kelvinValue]);
         break;

    case 3:
         printf("%f degrees F\n", [converter fahrenheitValue]);
         break;

    case 4:
         printf("%f degrees R\n", [converter rankineValue]);
         break;
}

Что касается scanf, он выполняет две вещи.Во-первых, он сканирует входные данные в предоставленные переменные, а во-вторых, возвращает количество успешно отсканированных элементов.Например:

int result;
int first;
int second;

printf("Please type two numbers: ");
result = scanf("%d %d", &first, &second);

Если scanf успешно прочитал два числа, то result должно быть равно 2. Если оно равно 2, то вы можете быть уверены, что first и second содержатхорошие данные, вы можете быть уверены, что scanf успешно отсканировал ввод.Точно так же, если вы только попросите scanf прочитать одно число, то, если result равно 1, тогда оно успешно прочитает это одно число.

Если result равно 1, то это означает, что оно толькоотсканировал один номер, а затем столкнулся с проблемой.Например, если пользователь набрал «100 abc», scanf сможет прочитать только один номер, но мы попросили два.В этом случае он вернет 1, чтобы сообщить нам, что он сканировал только одно целое число.

Если result равен 0, то это означает, что scanf не смог отсканировать что-либо это соответствует тому, что мы просили (например, если пользователь ввел «abc abc»).

Наконец, result будет EOF (конец файла), если не было данных для чтения.

Итак, важно проверить возвращаемое значение вызовов scanf, чтобы убедиться, что пользователь ввел что-то допустимое. Если результат равен 0, вы знаете, что пользователь ввел что-то недопустимое, а если результат равен EOF, тогда возникла проблема с чтением каких-либо данных. Итак, мы могли бы иметь эту настройку:

int result;
int first;
int second;

printf("Please type two numbers: ");
result = scanf("%d %d", &first, &second);

if (result == 0)
    printf("I couldn't understand what you gave me, I need numbers!\n");
else if (result == 1)
    printf("I was only able to read one number!\n");
else if (result == EOF)
    printf("Whoops, there was some problem trying to read your input\n");
else if (result == 2) // scanf was able to read two numbers
    printf("Great! The sum of those two numbers is: %d\n", first + second);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...