This question already has an answer here:
How to read one character at a time from user input — at each keystroke (without waiting for the user to press the return key)?
(1 answer)
Closed 2 months ago.
I'm trying to read from the standard input by using input_byte stdin
Something like this:
let rec loop () =
Format.eprintf "in the loop#.";
(match input_byte stdin with
| 0x0D -> print_newline ()
| b -> Format.eprintf "saw %i#." b);
loop ()
let () =
loop ()
If I type aaa I expect to see
in the loop
a
in the loop
saw 97
a
in the loop
saw 97
a
in the loop
saw 97
But instead nothing happens until I hit enter and this is what I have:
in the loop
aaa
saw 97
in the loop
saw 97
in the loop
saw 97
in the loop
saw 10
in the loop
Is there a way to read characters from a channel with a reader that doesn't wait for a flush?
Generally speaking the terminal driver of your system doesn't send characters at each keystroke. As you're seeing, it waits to send a whole line. This is more efficient and it also lets you correct errors before sending.
There are system-dependent ways to change this buffering behavior (and also echoing behavior, which you might also want to change). If you're on some kind of Unix system (anything but Windows essentially) you can use Unix.tcsetattr to change the handling of characters by the terminal driver.
Here is a previous question and answer that shows how to read one character at a time: How to read a character in OCaml without a return key?
Related
I'm starting out with Haskell and was looking into I/O mechanims. I read up on the interact function which takes a function of type String -> String as parameter. I tried to write a simple program that takes to numbers from stdin and creates a list and prints it line by line.
import Data.List
readIn = sort . map read . words
writeOut = unlines . map show
rangeList [n,m] = [n .. m]
main = interact (writeOut . rangeList . readIn)
For some reason it wont print the numbers. Could you help me out?
interact requires you to input an end-of-file (EOF) to stdin with Ctrl+D (or Ctrl+Z on Windows); when I type that combination, the output appears as required. This is necessary because, as the documentation for interact states, ‘the entire input from the standard input device is passed to [interact] as its argument’; due to this, you need to explicitly signal the place where stdin ends.
(By the way, I’m not even sure how you got your program to compile; GHC gives me lots of ‘ambiguous type’ errors when I try. I had to add type signatures to get it working, at which point I found the solution above to work.)
Hi guys i have the following question:
string s;
std::cout << "give me a string" << std::endl;
while (std::cin >> s){
std::cout << "give me a string" << std::endl;
}
cin.clear();
if s was an integer then i know that if i typed a char then the while would break. If it was an integer and typed a double the same would happened. But what about strings ?? Somewhere I read that in windows (as I am writting at netbeans in windows) you have to press ctrl+z and then it stops as it is taken as a false string. But when i do this , the process freezes and nothing happens.
You need to send the EOF signal, which in Netbeans is Ctrl + D.
However, hitting Enter twice will result in the condition of your loop to resolve in false, causing the loop to stop. That's excpected: How is "std::cin>>value" evaluated in a while loop?
If that doesn't work, use Ctrl + z and a newline character, which is the EOF signal in Windows, as stated here. Ctrl + D is for Linux though, but it works in your case.
The EOF signal closes the input stream, thus breaking the loop.
Moreover, in Netbeans (if the above doesn't work) it seems that you need to run your application from the command prompt to achieve this. Another attempt would be to "press Ctrl + z after pressing Enter", as stated here.
The loop will stop when the input stream is closed.
If you run the program from a shell, then the input stream may be open indefinitely. Exactly how you would close the stream in a terminal, depends on what terminal you are using.
In UNIX, the stream is closed when you send empty input. ctrl + d is the standard key combination for sending (flushing) the input to the stream (^d is the ASCII control code EOT, end of transmission). Pressing enter also sends the input, but it also inserts the end of line character, so it is not possible to use it to send empty input.
ctrl + z is similar in windows, but it has different behaviour (wikipedia):
The EOT character in Unix is different from the Control-Z in DOS. The DOS Control-Z byte is actually sent and/or placed in files to indicate where the text ends. In contrast the Control-D causes the Unix terminal driver to signal the EOF condition, which is not a character, while the byte has no special meaning if actually read or written from a file or terminal.
I'm trying to make a useful system to automatically increase numbers in selected text. For example, when I working in Zbrush on the project named "Example_character012" I have a folder with 23 files from "Example_character012_prj_01.zpr" to "Example_character012_prj_23.zpr". When I need to save next iteration I'm pressing "ctrl+s" and then regular saving screen opens in the last working directory with preselected filename text, in this scenario it would be "Example_character012_prj_23.zpr". I need to copy this text, select the last number(23) increase it by one, and past it all the text back to the text-field. In this case it would be "Example_character012_prj_24.zpr".
This kind of script would be really useful in all kinds of scenario, mainly with saving in different programs.
I tried to made it myself and come up with this:
^!Numpad1::
Sleep 100
Send ^c
Sleep 10
RegExMatch(clipboard,"(\d+)(?!.*\d)",Number)
NewNumber:=Number1+1
OldNumber:=NewNumber-1
Clipboard:=RegExReplace(clipboard, OldNumber, NewNumber)
Sleep 10
Send ^v
Sleep 10
Send +{Home}
Return
^!Numpad0::
Sleep 100
Send ^c
Sleep 10
RegExMatch(clipboard,"(\d+)(?!.*\d)",Number)
NewNumber:=Number1-1
OldNumber:=NewNumber+1
Clipboard:=RegExReplace(clipboard, OldNumber, NewNumber)
Sleep 10
Send ^v
Sleep 10
Send +{Home}
Return
Ctrl+alt+Num1 for increase and Ctrl+alt+Num0 for decrease.
It's work fine with in the simplest scenario, but have significant problems I can't solve myself:
It only works in english keyboard-layout. When I use it in russian layout - it puts "cv" instead of pasting(If I paste manually afterwards it put the correct text)
Sometimes it increases not only the last number "Example_character012_prj_01.zpr" changing to "Example_character022_prj_02.zpr" instead of "Example_character012_prj_02.zpr"
Zeros working incorrectly "Example_prj_09.zpr" changing to "Example_prj_010.zpr" instead of "Example_prj_10.zpr"
After pasting it selects the whole line instead of only what just have been pasted
If it's possible, it would be great to make it work without affecting clipboard at all.
Sometimes some keys like "ctrl" just get stuck until being clicked manually for some reason.
Edit:
Got some help at Autohotkey forums, current version of script below. Only questions 4 and 5 left.
^!Numpad1::
^!Numpad0::
Sleep 50
Send {Ctrl up}^{Ins}
Sleep 10
RegExMatch(Clipboard, "^(.*)(?=_)_(\d+)(\....)$", Match)
Len := StrLen(Match2)
if InStr(A_ThisHotkey, 1)
Match2++
else
Match2--
if (StrLen(Match2) < Len)
Match2 := Format("{:0" Len "}", Match2)
Clipboard := Match1 "_" Match2 Match3
Sleep 10
Send +{Ins}
Sleep 10
Send +{Home}
Return
The reason your CTRL key is misbehaving is maybe because:
If you have a hotkey like
^F12::
Send {a}
What actually happens when you hit CTRL+F12 is that AHK releases CTRL, sends a, then re-hits CTRL.
This can get more complicated, eg in your scenario.
Try prefixing your Send commands with {Blind} eg Send {Blind}^v to suppress this behavior.
This may or may not work (ie if the hotkey is shift+ctrl+something but the hotkey sends ctrl+v, then what would actually get sent is ctrl+shift+v) but if it does still work, it may make CTRL start behaving itself more.
Referring to two questions:
Incorrect output from C++ Primer 1.4.4
Confused by control flow execution in C++ Primer example
My question is answered in both of those posts, but I want to delve further.
First, I know this is only the beginning, but let's say I make a fully functional program that runs in a designed window. By that level, will I already know how to implement a EOF? I can't expect someone running my program to know that they need to hit Control-Z.
Is there a way to implement a specific code that functions so that it does not need me to type in an unrecognized value?
Also one guy in those questions somewhat answered the importance of EOF, but how come the program doesn't even post the final cnt - 1?
Let's say I do the numbers 10 10 10 20 20 20. Without EOF, this will only show the "10 repeats 3 times." How come the program doesn't at least type in the count "10 repeats 3 times and 20 repeats 2 times" minus the final one with white space?
lets say I make a fully functional program that runs in a designed window. By that level, will I already know how to implement a eof? I can't expect someone running my program to know that they need to hit ctrl + z.
You could either tell the user explicitly to do a specific action to end input or the design of the window itself could tell the user the information implicitly. For instance, a dialog box could ask the user to enter input and click an OK button when done.
Is there a way to implement a specific code that functions so that it does not need me to type in an unrecognized value?
It seems like you would rather use a newline character to terminate your input. An example of this usage could be std::getline. Instead of writing
while (std::cin >> val)
you could instead use
std::string line;
if (std::getline(std::cin,line))
and assume that your user's input only consists of one line of values. There are plenty of other ways to similarly achieve this task depending on how you want to constrain the user's input.
Let's say I do the numbers 10 10 10 20 20 20. WIthout eof this will only show the "10 repeats 3 times." How come the program doesn't at least type in the count "10 repeats 3 times and 20 repeats 2 times" minus the final one with white space?
Without the eof your program is still executing the while (std::cin >> val) loop since std::cin >> val has not yet received invalid input.
Since the line
std::cout << currVal << " occurs " << cnt << " times" << std::endl;
occurs after that while loop finishes execution, you don't (yet) see any information about the three 20's in the input.
When you are reading a sequence of inputs you'll need some indication when your down. That could be a sentinel value ("enter 999 to stop reading"; you'd need to detect that while reading), an invalid input ("enter X to stop reading"; when reading an int the value X is illegal and causes the stream to got into failure mode, i.e., have std::ios_base::failbit set), or the more conventional "there isn't anything more to read". For a file, the last conditions is straight forward. When reading data from the console you'll either need to teach people how to terminate the input or you'll need to use a different approach.
If you want to intercept any keypressed and react on them directly you may do so, too. You could, e.g., use ncurses and control your input via that. You could also set the concole to non-buffering (on POSIX systems using tcgetattr() and tcsetattr() to clear the ICANON flag) and deal directly with all key presses to decide whether you want to continue reading or not.
Although I'm certainly up to doing fancy I/O stuff I normally don't bother: users will understand the "end of input" character and just deal with it. That is, my input normally looks something like this:
while (in >> whatever_needs_to_be_read) { ... }
... or, if the input is genuinely line oriented
for (std::string line; std::getline(in, line); ) { ... }
The function doing this input will then be called with a suitable std::istream which may be std::cin although I have typically some way to also read from a file (in addition to the shell-privided input redirection).
BTW, despite some indications in the questions referenced, "EOF" is not a character being read. It is a character entered, though (normally). ... and it is quite conventional to "know" the end of input character (on POSIX systems a ctrl-D and on Windows a ctrl-Z). You can use other indicators, e.g., the "interrupt" (ctrl-C) but that takes more work and doesn't integrate nicely with stream. To use the interrupt chacter you'd need to setup a signal handler for SIGINT and deal with that. One slightly annoying part of doing so is that if you get it wrong you'll need to find a different way to kill the program (e.g. on POSIX using ctrl-Z to put the process to sleep and kill it via a harsher signal).
I have my 2nd assignment for C++ class which includes Markov chains. The assignment is simple but I'm not able to figure out what is the best implementation when reading chars from files.
I have a file around 300k. One of the rules for the assignment is to use Map and Vector classes. In Map (key is only string) and values will be the Vectors. When I'm reading from the file, I need to start collecting key pairs.
Example:
File1.txt
1234567890
1234567890
If Select Markov k=3, I should have in my Map:
key vector
123 -> 4
456 -> 7
789 -> 0
0/n1 -> 2
234 -> 5
567 -> 8
890 -> /n
/n -> NULL
The professor's suggestion is to read char by char, so my algorithm is the following
while (readchar != EOF){
tempstring += readchar
increment index
if index == Markovlevel {
get nextchar if =!EOF
insert nextchar value in vector
insert tempstring to Map and assign vector
unget char
}
}
I omit some other details. My main question is that if I have 318,000 characters, I will be doing the conditional every time which slows down my computer a lot (brand new MAC pro). A sample program from the professor executes this file in around 5 seconds.
I'm not able to figure out what's the best method to read fixed length words from a text file in C++.
Thanks!
Repeated file reading will slow down the program.
Read the file in blocks, of say size 1024, put into a buffer. Then process this buffer as you require for the assignment. Repeat for the next block till you are done with the file.
Have you actually timed the program? 318,000 conditionals should be a piece of cake for your brand new MAC pro. That should take only microseconds.
Premature optimization is the root of all evil. Make your program work first, optimization comes second.