0

I have an assignment for my first year programming class in which one of the parts is to convert a string to an integer or float value. However, if the string is not convertible it should pass a value of None to the variable. My professor indicated that we are not allowed to use try/except for whatever reason and the only way I can think of doing this is using the isdigit() method, however, this will not work for negative values which are required as the value is being used for a temperature.

temp = input('What is the temperature value? Enter a numeric value: ')

try: 
   temp = float(input('What is the temperature value? Enter a numeric value: '))
except ValueError:
   temp = None

This is the only way I can think of doing this, however, another student in my class did it using the is digit() in one of the previous functions we are supposed to define

def convert_to_kelvin(temperature, units):
    unit = units.lower()
    if type(temperature) != float and type(temperature) != int and temperature.isdigit() == False:
   return None

Using this, the autograder that the professor uses marks it as correct and it also marks my try/except correct as well. But my classmate code gives none for negative values and mine does not. The professor said that try/except is not allowed.

Ammar Ahmed
  • 344
  • 3
  • 11
  • 1
    Remove the negative sign, process, and add the sign back? So if the first character of `s` is `'-'`, do `isdigit(s[1:])`, if it's not, just use `isdigit(s)` - does that meet your requirements? – Collin Heist Oct 28 '20 at 21:21
  • Sorry, I'm pretty new to programming. How would I remove the negative sign and add it back? – Ammar Ahmed Oct 28 '20 at 21:37
  • Does your code need to behave exactly as `int()` and `float()` do? – AMC Oct 28 '20 at 23:06
  • Does this answer your question? [How can I check if a string represents an int, without using try/except?](https://stackoverflow.com/questions/1265665/how-can-i-check-if-a-string-represents-an-int-without-using-try-except) – AMC Oct 28 '20 at 23:15

2 Answers2

0

so here is my try and I dont know whether it really works for all cases but as far as I tested it does:

allowed_chars = '1234567890.-'

temp = input('Input temp: ')

def check():
    not_int = False
    for chars in temp:
        if chars not in allowed_chars or temp[-1] == '.' or temp[-1] == '-':
            not_int = True
        else:
            not_int = False
    return temp if not not_int else None

print(check())

now you have to understand what it does on your own as you may have to explain it to your proffessor

Matiiss
  • 5,970
  • 2
  • 12
  • 29
0

One way to determine this would be to attempt to do the conversion to see if it can be done successfully. Not being able to use exceptions makes the task surprising difficult to get right because it requires using of a lot of flag variable internally. That said, here's something I think covers a most, if not all, the possibilities.

That's a weakness of this approach, because there's a huge number of invalid possible inputs vs only a relatively small number of valid ones.

from string import digits  # '0123456789'


def parse_numeric(string):
    """ Parse a string into an integer or float if possible and return it,
        otherwise return None.
    """
    if not string:  # Empty string?
        return None
    decimal_point = None
    neg = False
    if string.startswith('-'): # minus sign?
        string = string[1:]  # Remove it.
        neg = True

    res = 0
    for ch in string:
        if ch == '.':  # Decimal point?
            if decimal_point is not None:
                return None  # Invalid, one already seen.
            else:
                decimal_point = 0  # Initialize.
                continue

        if ch not in digits:
            return None  # Invalid.
        if decimal_point is not None:
            decimal_point += 1
        res = res*10 + ord(ch) - ord('0')

    if decimal_point is not None:
        res = res / 10**decimal_point
    return res if not neg else -res


if __name__ == '__main__':

    testcases = ('1', '12', '123', '123.', '123.4', '123.45',
                 '-1', '-12', '-123', '-123.', '-123.4', '-123.45',
                 '1-', '-1-2', '123-4.5', 'foobar', '-woot')

    for temp in testcases:
        print(f'input: {temp!r:>10}, result: {parse_numeric(temp)}')

Output:

input:        '1', result: 1
input:       '12', result: 12
input:      '123', result: 123
input:     '123.', result: 123.0
input:    '123.4', result: 123.4
input:   '123.45', result: 123.45
input:       '-1', result: -1
input:      '-12', result: -12
input:     '-123', result: -123
input:    '-123.', result: -123.0
input:   '-123.4', result: -123.4
input:  '-123.45', result: -123.45
input:       '1-', result: None
input:     '-1-2', result: None
input:  '123-4.5', result: None
input:   'foobar', result: None
input:    '-woot', result: None
martineau
  • 119,623
  • 25
  • 170
  • 301