stdio.py


Below is the syntax highlighted version of stdio.py from § Code.


"""
stdio.py

The stdio module supports reading from standard input and writing to
sys.stdout.

Note:  Usually it's a bad idea to mix these three sets of reading
functions:

-- isEmpty(), readInt(), readFloat(), readBool(), readString()

-- hasNextLine(), readLine()

-- readAll(), readAllInts(), readAllFloats(), readAllBools(),
   readAllStrings(), readAllLines()

Usually it's better to use one set exclusively.
"""
    
import sys
import re

#-----------------------------------------------------------------------

# Change sys.stdin so it provides universal newline support. 

if (sys.hexversion < 0x03000000):
    import os
    sys.stdin = os.fdopen(sys.stdin.fileno(), 'rU', 0)
else:    
    sys.stdin = open(sys.stdin.fileno(), 'r', newline=None)
            
#=======================================================================
# Writing functions
#=======================================================================

def writeln(x=''):
    """
    Write x and an end-of-line mark to standard output.
    """
    if sys.hexversion < 0x03000000:
        x = unicode(x)
        x = x.encode('utf-8')
    else:
        x = str(x)
    sys.stdout.write(x)
    sys.stdout.write('\n')
    sys.stdout.flush()

#-----------------------------------------------------------------------

def write(x=''):
    """
    Write x to standard output.
    """
    if (sys.hexversion < 0x03000000):
        x = unicode(x)
        x = x.encode('utf-8')
    else:
        x = str(x)
    sys.stdout.write(x)
    sys.stdout.flush()

#-----------------------------------------------------------------------

def writef(fmt, *args):
    """
    Write each element of args to standard output.  Use the format
    specified by string fmt.
    """
    x = fmt % args
    if sys.hexversion < 0x03000000:
        x = unicode(x)
        x = x.encode('utf-8')
    sys.stdout.write(x)
    sys.stdout.flush()

#=======================================================================
# Reading functions
#=======================================================================

_buffer = ''

#-----------------------------------------------------------------------

def _readRegExp(regExp):
    """
    Discard leading white space characters from standard input. Then read
    from standard input and return a string matching regular expression
    regExp.  Raise an EOFError if no non-whitespace characters remain
    in standard input.  Raise a ValueError if the next characters to
    be read from standard input do not match 'regExp'.
    """
    global _buffer
    if isEmpty():
        raise EOFError()
    compiledRegExp = re.compile(r'^\s*' + regExp)
    match = compiledRegExp.search(_buffer)
    if match is None:
        raise ValueError()
    s = match.group()
    _buffer = _buffer[match.end():]
    return s.lstrip()

#-----------------------------------------------------------------------

def isEmpty():
    """
    Return True if no non-whitespace characters remain in standard
    input. Otherwise return False.
    """
    global _buffer
    while _buffer.strip() == '':
        line = sys.stdin.readline()
        if sys.hexversion < 0x03000000:
            line = line.decode('utf-8')
        if line == '':
            return True
        _buffer += line
    return False

#-----------------------------------------------------------------------

def readInt():
    """
    Discard leading white space characters from standard input. Then
    read from standard input a sequence of characters comprising an
    integer. Convert the sequence of characters to an integer, and
    return the integer.  Raise an EOFError if no non-whitespace
    characters remain in standard input. Raise a ValueError if the
    next characters to be read from standard input cannot comprise
    an integer.
    """
    s = _readRegExp(r'[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)')
    radix = 10
    strLength = len(s)
    if (strLength >= 1) and (s[0:1] == '0'): radix = 8
    if (strLength >= 2) and (s[0:2] == '-0'): radix = 8
    if (strLength >= 2) and (s[0:2] == '0x'): radix = 16
    if (strLength >= 2) and (s[0:2] == '0X'): radix = 16
    if (strLength >= 3) and (s[0:3] == '-0x'): radix = 16
    if (strLength >= 3) and (s[0:3] == '-0X'): radix = 16
    return int(s, radix)

#-----------------------------------------------------------------------

def readAllInts():
    """
    Read all remaining strings from standard input, convert each to
    an int, and return those ints in an array. Raise a ValueError if
    any of the strings cannot be converted to an int.
    """
    strings = readAllStrings()
    ints = []
    for s in strings:
        i = int(s)
        ints.append(i)
    return ints

#-----------------------------------------------------------------------

def readFloat():
    """
    Discard leading white space characters from standard input. Then
    read from standard input a sequence of characters comprising a
    float. Convert the sequence of characters to a float, and return the
    float.  Raise an EOFError if no non-whitespace characters remain
    in standard input. Raise a ValueError if the next characters to be
    read from standard input cannot comprise a float.
    """
    s = _readRegExp(r'[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?')
    return float(s)

#-----------------------------------------------------------------------

def readAllFloats():
    """
    Read all remaining strings from standard input, convert each to
    a float, and return those floats in an array. Raise a ValueError if
    any of the strings cannot be converted to a float.
    """
    strings = readAllStrings()
    floats = []
    for s in strings:
        f = float(s)
        floats.append(f)
    return floats

#-----------------------------------------------------------------------

def readBool():
    """
    Discard leading white space characters from standard input. Then
    read from standard input a sequence of characters comprising a bool.
    Convert the sequence of characters to a bool, and return the
    bool.  Raise an EOFError if no non-whitespace characters remain
    in standard input. Raise a ValueError if the next characters to be
    read from standard input cannot comprise a bool.

    These character sequences can comprise a bool:
    -- True
    -- False
    -- 1 (means true)
    -- 0 (means false)
    """
    s = _readRegExp(r'(True)|(False)|1|0')
    if (s == 'True') or (s == '1'):
        return True
    return False

#-----------------------------------------------------------------------

def readAllBools():
    """
    Read all remaining strings from standard input, convert each to
    a bool, and return those bools in an array. Raise a ValueError if
    any of the strings cannot be converted to a bool.
    """
    strings = readAllStrings()
    bools = []
    for s in strings:
        b = bool(s)
        bools.append(b)
    return bools

#-----------------------------------------------------------------------

def readString():
    """
    Discard leading white space characters from standard input. Then
    read from standard input a sequence of characters comprising a
    string, and return the string. Raise an EOFError if no
    non-whitespace characters remain in standard input.
    """
    s = _readRegExp(r'\S+')
    return s

#-----------------------------------------------------------------------

def readAllStrings():
    """
    Read all remaining strings from standard input, and return them in
    an array.
    """
    strings = []
    while not isEmpty():
        s = readString()
        strings.append(s)
    return strings

#-----------------------------------------------------------------------

def hasNextLine():
    """
    Return True if standard input has a next line. Otherwise return
    False.
    """
    global _buffer
    if _buffer != '':
        return True
    else:
        _buffer = sys.stdin.readline()
        if sys.hexversion < 0x03000000:
            _buffer = _buffer.decode('utf-8')
        if _buffer == '':
            return False
        return True

#-----------------------------------------------------------------------

def readLine():
    """
    Read and return as a string the next line of standard input.
    Raise an EOFError is there is no next line.
    """
    global _buffer
    if not hasNextLine():
        raise EOFError()
    s = _buffer
    _buffer = ''
    return s.rstrip('\n')

#-----------------------------------------------------------------------

def readAllLines():
    """
    Read all remaining lines from standard input, and return them as
    strings in an array.
    """
    lines = []
    while hasNextLine():
        line = readLine()
        lines.append(line)
    return lines

#-----------------------------------------------------------------------

def readAll():
    """
    Read and return as a string all remaining lines of standard input.
    """
    global _buffer
    s = _buffer
    _buffer = ''
    for line in sys.stdin:
        if sys.hexversion < 0x03000000:
            line = line.decode('utf-8')
        s += line
    return s

#=======================================================================
# For Testing
#=======================================================================

def _testWrite():
    writeln()
    writeln('string')
    writeln(123456)
    writeln(123.456)
    writeln(True)
    write()
    write('string')
    write(123456)
    write(123.456)
    write(True)
    writeln()
    writef('<%s> <%8d> <%14.8f>\n', 'string', 123456, 123.456)
    writef('formatstring\n')

#-----------------------------------------------------------------------

def _main():
    """
    For testing. The command-line argument should be the name of the
    function that should be called.
    """

    map = {
        'readInt':    readInt,    'readAllInts':    readAllInts,
        'readFloat':  readFloat,  'readAllFloats':  readAllFloats,
        'readBool':   readBool,   'readAllBools':   readAllBools,
        'readString': readString, 'readAllStrings': readAllStrings,
        'readLine':   readLine,   'readAllLines' :  readAllLines,
        'readAll':    readAll }

    testId = sys.argv[1]

    if testId == 'write':
        _testWrite()
    else:
        writeln(map[testId]())

if __name__ == '__main__':
    _main()


Copyright © 2000–2015, Robert Sedgewick, Kevin Wayne, and Robert Dondero.
Last updated: Fri Oct 20 20:45:16 EDT 2017.