I'm trying to solve a Krypto Problem on https://www.spoj.pl in Python, which involves console input.
My Problem is, that the Input String has multiple Lines but is needed as one single String in the Programm.
If I just use raw_input() and paste (for testing) the text in the console, Python threats it like I pressed enter after every Line -> I need to call raw_input() multiple times in a loop.
The Problem is, that I cannot modify the Input String in any way, it doesn't have any Symbol thats marks the End and I don't know how many Lines there are.
So what do I do?
Upon reaching end of stream on input, raw_input will return an empty string. So if you really need to accumulate entire input (which you probably should be avoiding given SPOJ constraints), then do:
buffer = ''
while True:
line = raw_input()
if not line: break
buffer += line
# process input
Since the end-of-line on Windows is marked as '\r\n' or '\n' on Unix system it is straight forward to replace those strings using
your_input.replace('\r\n', '')
Since raw_input() is designed to read a single line, you may have trouble this way.
A simple solution would be to put the input string in a text file and parse from there.
Assuming you have input.txt you can take values as
f = open(r'input.txt','rU')
for line in f:
print line,
Using the best answer here, you will still have an EOF error that should be handled. So, I just added exception handling here
buffer = ''
while True:
try:
line = raw_input()
except EOFError:
break
if not line:
break
buffer += line
Related
I have a long list of numbers that I would like to input into my code through a raw_input. It includes numbers that are spaced out through SPACES and ENTER/RETURN. The list looks like this . When I try to use the function raw_input, and copy paste the long list of numbers, my variable only retains the first row of numbers. This is my code so far:
def main(*arg):
for i in arg:
print arg
if __name__ == "__main__": main(raw_input("The large array of numbers"))
How can I make my code continue to read the rest of the numbers?
Or if that's not possible, can I make my code acknowledge the ENTER in any way?
P.s. While this is a project euler problem I don't want code that answers the project euler question, or a suggestion to hard code the numbers in. Just suggestions for inputting the numbers into my code.
If I understood your question correctly, I think this code should work (assuming it's in python 2.7):
sentinel = '' # ends when this string is seen
rawinputtext = ''
for line in iter(raw_input, sentinel):
rawinputtext += line + '\n' #or delete \n if you want it all in a single line
print rawinputtext
(code taken from: Raw input across multiple lines in Python )
PS: or even better, you can do the same in just one line!
rawinputtext = '\n'.join(iter(raw_input, '') #replace '\n' for '' if you want the input in one single line
(code taken from: Input a multiline string in python )
I think what you are actually looking for is to directly read from stdin via sys.stdin. But you need to accept the fact that there should be a mechanism to stop accepting any data from stdin, which in this case is feasible by passing an EOF character. An EOF character is passed via the key combination [CNTRL]+d
>>> data=''.join(sys.stdin)
Hello
World
as
a
single stream
>>> print data
Hello
World
as
a
single stream
I have a function that executes the following (among other things):
userinput = stdin.readline()
betAmount = int(userinput)
Is supposed to take input integer from stdin as a string and convert it to an integer.
When I call the function, however, it returns a single newline character (it doesn't even wait for me to input anything).
Earlier in the program I get some input in the form of:
stdin.read(1)
to capture a single character.
Could this have something to do with it? Am I somehow writing a newline character to the next line of stdin?
How can I fix this?
stdin.read(1) reads one character from stdin. If there was more than one character to be read at that point (e.g. the newline that followed the one character that was read in) then that character or characters will still be in the buffer waiting for the next read() or readline().
As an example, given rd.py:
from sys import stdin
x = stdin.read(1)
userinput = stdin.readline()
betAmount = int(userinput)
print ("x=",x)
print ("userinput=",userinput)
print ("betAmount=",betAmount)
... if I run this script as follows (I've typed in the 234):
C:\>python rd.py
234
x= 2
userinput= 34
betAmount= 34
... so the 2 is being picked up first, leaving the 34 and the trailing newline character to be picked up by the readline().
I'd suggest fixing the problem by using readline() rather than read() under most circumstances.
Simon's answer and Volcano's together explain what you're doing wrong, and Simon explains how you can fix it by redesigning your interface.
But if you really need to read 1 character, and then later read 1 line, you can do that. It's not trivial, and it's different on Windows vs. everything else.
There are actually three cases: a Unix tty, a Windows DOS prompt, or a regular file (redirected file/pipe) on either platform. And you have to handle them differently.
First, to check if stdin is a tty (both Windows and Unix varieties), you just call sys.stdin.isatty(). That part is cross-platform.
For the non-tty case, it's easy. It may actually just work. If it doesn't, you can just read from the unbuffered object underneath sys.stdin. In Python 3, this just means sys.stdin.buffer.raw.read(1) and sys.stdin.buffer.raw.readline(). However, this will get you encoded bytes, rather than strings, so you will need to call .decode(sys.stdin.decoding) on the results; you can wrap that all up in a function.
For the tty case on Windows, however, input will still be line buffered even on the raw buffer. The only way around this is to use the Console I/O functions instead of normal file I/O. So, instead of stdin.read(1), you do msvcrt.getwch().
For the tty case on Unix, you have to set the terminal to raw mode instead of the usual line-discipline mode. Once you do that, you can use the same sys.stdin.buffer.read(1), etc., and it will just work. If you're willing to do that permanently (until the end of your script), it's easy, with the tty.setraw function. If you want to return to line-discipline mode later, you'll need to use the termios module. This looks scary, but if you just stash the results of termios.tcgetattr(sys.stdin.fileno()) before calling setraw, then do termios.tcsetattr(sys.stdin.fileno(), TCSAFLUSH, stash), you don't have to learn what all those fiddly bits mean.
On both platforms, mixing console I/O and raw terminal mode is painful. You definitely can't use the sys.stdin buffer if you've ever done any console/raw reading; you can only use sys.stdin.buffer.raw. You could always replace readline by reading character by character until you get a newline… but if the user tries to edit his entry by using backspace, arrows, emacs-style command keys, etc., you're going to get all those as raw keypresses, which you don't want to deal with.
stdin.read(1)
will not return when you press one character - it will wait for '\n'. The problem is that the second character is buffered in standard input, and the moment you call another input - it will return immediately because it gets its input from buffer.
If you need just one character and you don't want to keep things in the buffer, you can simply read a whole line and drop everything that isn't needed.
Replace:
stdin.read(1)
with
stdin.readline().strip()[:1]
This will read a line, remove spaces and newlines and just keep the first character.
Try this ...
import sys
buffer = []
while True:
userinput = sys.stdin.readline().rstrip('\n')
if userinput == 'quit':
break
else:
buffer.append(userinput)
import sys
userinput = sys.stdin.readline()
betAmount = int(userinput)
print betAmount
This works on my system. I checked int('23\n') would result in 23.
I have an id in invalid_change variable which I am trying to delete from the input file "list.txt" and create a file results.txt as below..can anyone provide inputs on how can this be fixed?I have a sample input and expected output below..
'''
INPUT(list.txt:-
350882 348521 350166
346917 352470
360049
EXPECTEDOUTPUT(results.txt):-
350882 348521 350166
346917
360049
'''
invalid_list=['352470','12345']
f_write = open('results.txt', 'wb')
with open('list.txt','r') as f :
for line in f :
#delete the whole line if any invalid gerrit is presnet
gerrit_list = line.strip().split(' ')
ifvalid = True
for gerrit in gerrit_list:
try: # check if invalid gerrit is present
invalid_gerrit.index(invalid_change)
ifvalid = False
break
except:
pass
if ifvalid:
f_write.write(line)
f_write.close()
The problem is that when you reach this line:
346917 352470
the ifvalid variable is set to False and thus this specific line (even if adjusted) is not being written to the output file.
Possible solutions:
Modify string eg. using regular expressions. They will do replacing.
Do not skip writing "invalid" line to a file, just prepare it without the ID you want to remove (as in solution no. 1).
Let us know, if you have any questions.
Other problems in your code are:
diaper anti-pattern (you catch all the exceptions, including NameError, while you should only catch ValueError, or rather performing test including in keyword) - this is the reason you do not see errors related to lack of invalid_change and invalid_gerrit variables,
instead of opening and closing f_write, you could use it also in with statement you are already using, if you have Python 2.7+ or 3.1+,
str.split() splits by default by whitespaces, and removes empty strings from result, so instead of writing line.strip().split(' ') you could just write line.split(),
Each item in gerrit_list is an individual number. You don't need to find whether the invalid change is contained within the number. In fact, that can cause bugs. You can just directly iterate through the items in gerrit_list and throw away the ones that match invalid_list:
for line in f:
gerrit_list = line.split()
valid_gerrits = [gerrit for gerrit in gerrit_list if gerrit not in invalid_list]
if valid_gerrits:
newline = ' '.join(valid_gerrits) + '\n'
f_write.write(newline)
I'm trying to get the behaviour of typical IM clients that use Return to send a text and Shift + Return to insert a linebreak. Is there a way to achieve that with minimal effort in Python, using e.g. readline and raw_input?
Ok, I heard it can be accomplished also with the readline, in a way.
You can import readline and set in configuration your desired key (Shift+Enter) to a macro that put some special char to the end of the line and newline. Then you can call raw_input in a loop.
Like this:
import readline
# I am using Ctrl+K to insert line break
# (dont know what symbol is for shift+enter)
readline.parse_and_bind('C-k: "#\n"')
text = []
line = "#"
while line and line[-1]=='#':
line = raw_input("> ")
if line.endswith("#"):
text.append(line[:-1])
else:
text.append(line)
# all lines are in "text" list variable
print "\n".join(text)
I doubt you'd be able to do that just using the readline module as it will not capture the individual keys pressed and rather just processes the character responses from your input driver.
You could do it with PyHook though and if the Shift key is pressed along with the Enter key to inject a new-line into your readline stream.
I think that with minimal effort you can use urwid library for Python. Unfortunately, this does not satisfy your requirement to use readline/raw_input.
Update: Please see also this answer for other solution.
import readline
# I am using Ctrl+x to insert line break
# (dont know the symbols and bindings for meta-key or shift-key,
# let alone 4 shift+enter)
def startup_hook():
readline.insert_text('» ') # \033[32m»\033[0m
def prmpt():
try:
readline.parse_and_bind('tab: complete')
readline.parse_and_bind('set editing-mode vi')
readline.parse_and_bind('C-x: "\x16\n"') # \x16 is C-v which writes
readline.set_startup_hook(startup_hook) # the \n without returning
except Exception as e: # thus no need 4 appending
print (e) # '#' 2 write multilines
return # simply use ctrl-x or other some other bind
while True: # instead of shift + enter
try:
line = raw_input()
print '%s' % line
except EOFError:
print 'EOF signaled, exiting...'
break
# It can probably be improved more to use meta+key or maybe even shift enter
# Anyways sry 4 any errors I probably may have made.. first time answering
Write a program that outputs the first number within a file specified by the user. It should behave like:
Enter a file name: l11-1.txt
The first number is 20.
You will need to use the file object method .read(1) to read 1 character at a time, and a string object method to check if it is a number. If there is no number, the expected behaviour is:
Enter a file name: l11-2.txt
There is no number in l11-2.txt.
Why is reading 1 character at a time a better algorithm than calling .read() once and then processing the resulting string using a loop?
I have the files and it does correspond to the answers above but im not sure how to make it output properly.
The code i have so far is below:
filenm = raw_input("Enter a file name: ")
datain=file(filenm,"r")
try:
c=datain.read(1)
result = []
while int(c) >= 0:
result.append(c)
c = datain.read(1)
except:
pass
if len(result) > 0:
print "The first number is",(" ".join(result))+" . "
else:
print "There is no number in" , filenm + "."
so far this opens the file and reads it but the output is always no number even if there is one. Can anyone help me ?
OK, you've been given some instructions:
read a string input from the user
open the file given by that string
.read(1) a character at a time until you get the first number or EOF
print the number
You've got the first and second parts here (although you should use open instead of file to open a file), what next? The first thing to do is to work out your algorithm: what do you want the computer to do?
Your last line starts looping over the lines in the file, which sounds like not what your teacher wants -- they want you to read a single character. File objects have a .read() method that lets you specify how many bytes to read, so:
c = datain.read(1)
will read a single character into a string. You can then call .isdigit() on that to determine if it's a digit or not:
c.isdigit()
It sounds like you're supposed to keep reading a digit until you run out, and then concatenate them all together; if the first thing you read isn't a digit (c.isdigit() is False) you should just error out
Your datain variable is a file object. Use its .read(1) method to read 1 character at a time. Take a look at the string methods and find one that will tell you if a string is a number.
Why is reading 1 character at a time a better algorithm than calling .read() once and then processing the resulting string using a loop?
Define "better".
In this case, it's "better" because it makes you think.
In some cases, it's "better" because it can save reading an entire line when reading the first few bytes is enough.
In some cases, it's "better" because the entire line may not be sitting around in the input buffer.
You could use regex like (searching for an integer or a float):
import re
with open(filename, 'r') as fd:
match = re.match('([-]?\d+(\.\d+|))', fd.read())
if match:
print 'My first number is', match.groups()[0]
This with with anything like: "Hello 111." => will output 111.