tags:

views:

80

answers:

2

Hey everyone, I am writing a simple console application in Objective-C but I have heard that this coding may be loosely applied to some C as well, so I wanted to make that clear.

I am having a slight problem however, when I run from the Debugger in Xcode, for some reason, my program does not wait for user input, it just rolls right on through, displaying the strings and converting a number automatically.

Is there a case for this?

Did I not specify something correct in my if else statement?

Here is my code:

//Simple program to convert Fahrenheit to Celsius and Celsius to Fahrenheit

#import <stdio.h>

@interface Converter: NSObject
{
//Instance variable which stores converting formula for objects
double formula;
}

//Declare instance method for setting instance variable
-(double) convert: (double) expression;

//Declare instance method for getting instance variable
-(double) formula;

@end


@implementation Converter;

//Define instance method to set the argument (expression) equal to the instance variable
-(double) convert: (double) expression
{
formula = expression;
}

//Define instance method for returning instance variable, formula
-(double) formula
{
return formula;
}

@end

int main (int argc, char *argv[])
{

//Point two new objects, one for the Fahrenheit conversions and the other for the Celsius conversions, to the Converter class
Converter *fahrenheitConversion = [[Converter alloc] init];
Converter *celsiusConversion = [[Converter alloc] init];

//Declare two double variables holding the user-inputted data, and one integer variable for the if else statement   
double fahrenheit, celsius;
int prompt;

NSLog(@"Please press 0 to convert Celsius to Fahrenheit, or 1 to convert Fahrenheit to Celsius\n ");
scanf("%i", &prompt);
if(prompt == 0) {
    NSLog(@"Please enter a temperature in Celsius to be converted into Fahrenheit!:\n");
    scanf("%lf", &celsius);
    [fahrenheitConversion convert: ((celsius*(9/5)) + 32)];
    NSLog(@"%lf degrees Celsius is %lf Fahrenheit", celsius, [fahrenheitConversion formula]);
}

else {
    NSLog(@"Please enter a temperature in Fahrenheit to be converted into Celsius!:\n");
    [celsiusConversion convert: ((fahrenheit - 32)*(5/9))];
    NSLog(@"%lf degrees Fahrenheit is %lf Celsius", fahrenheit, [celsiusConversion formula]);
}

return 0;
}

UPDATE:

It looks as though the reason the console in the Xcode debugger did not wait for my input was because I had it set as an iPhone application, not a Mac OS X Cocoa, I can't even remember why I did that. What I really should do is just make a project with no template, so it doesn't expect anything..

I'm still really appreciative and open to suggestions like dreamlax, and I'm trying to implement your code suggestion, it's a little harder than expected though, because I'm still very new.

A: 

You should use "%d" in format for scanf instead of "%i":

scanf("%d", &prompt);
Eimantas
Actually, with the way I had this setup, isn't it correct to use %i in my case, because I instantiated the prompt variable as an integer, as it won't deal with floating points or double precision data types, just because the user was instructed to type in either 0 or 1 into the console. This also didn't appear to affect my problem upon running either.. Thanks though.
BOSS
+1  A: 

When you call scanf, always check the return value. It will return however many items were successfully scanned. In your application, you only provide one argument, so if scanf was successful, then it should return 1. It can return two other values:

  1. If there was an error reading input, or if the input ended before successfully scanning all format descriptions, scanf may return EOF.
  2. If there was no input that matched the format description provided, scanf may return 0 (this may happen if the user provided an alphabetic character instead of a number, or if the user just pressed enter without typing anything, etc.)

You should check the result of each scanf call and handle it appropriately.

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

if (result == EOF || result == 0)
{
    NSLog (@"There was an error reading your choice.");
    exit(1);
}
else
{
    // result should be 1 here, continue onwards doing work
}

There could be a number of reasons why scanf may not return 1 while running through a debugger, here's a few that I can think of:

  1. stdin is closed for some reason, so reading from stdin will always fail.
  2. There could be some data being piped into your application's stdin stream. I'm not sure where this could come from.

Some further advice

It may be better if you store the temperature in your class using only a single scale. For example:

@interface Temperature : NSObject
{
    double celsius; // only store one temperature
}

- (id) initWithFahrenheit:(double) f;
- (id) initWithCelsius:(double) c;

- (double) fahrenheitValue;
- (double) celsiusValue;
@end

@implementation Temperature
 - (id) initWithFahrenheit:(double) f
{
    self = [super init];
    if (!self) return nil;
    celsius = (f - 32)*(5/9);
    return self;
}

- (id) initWithCelsius:(double) c
{
    self = [super init];
    if (!self) return nil;
    celsius = c;
    return self;
}

- (double) fahrenheitValue
{
    return (celsius*(9/5)) + 32);
}

 - (double) celsiusValue
{
    return celsius;
}

@end

Then, if you have a value in fahrenheight, you can do:

 Temperature *myTemp = [[Temperature alloc] initWithFahrenheit:f];
 double celsius = [myTemp celsiusValue];

See if you can implement other temperature scales too, such as Kelvin, and Rankine!

dreamlax
Good idea about other scales, never heard of Rankine though.. OK, cool, what about your line where result == 0 is included in the same line as EOF. Why is that? Also, why did you set it equal to result, and not prompt? Is that just a standard naming technique?
BOSS
Also, in your suggested code, is it basically just taking one Celsius value and having the extendibility to be converted into anything else from celsius? That makes more sense when I add Kelvin and Rankine. I guess it would be really cool to select you "base" temperature, and then be able to convert that temperature into any of the others.
BOSS
@BOSS: `scanf` *returns* the number of items successfully scanned, I called the variable `result` but if it were more verbosely named it could be called `scannedItems` or `numberOfSuccessfullyScannedItems` to be uber-verbose. I check for both `EOF` and `0` in one go because both of these would indicate that it did not successfully scan a number into the `prompt` variable. You are correct about having just one Celsius value and have each of the other temperature scales convert from the Celsius value.
dreamlax