for(i=getchar();; i=getchar())
if(i=='x')
break;
else putchar(i);
Answer is : mi
Can someone explain this piece of code ?(MCQ Question)
This question can be solved by eliminating incorrect answer. This fragments prints character and exits loop if the character is an x. So the program would not output an x.
Any output string that doesn't contain x is possible. In your MCQ, possibly mi is the only option with x and all other options contain x somewhere in the string making them incorrect answer.
If input is "mix....", output would be "mi". Below is your loop unrolled.
getchar() -> m -> else -> print m /* First getchar */
getchar() -> i -> else -> print i /* Second getchar */
getchar() -> x -> if -> break /* Second getchar */
for(i=getchar();; i=getchar())
if(i=='x')
break;
else putchar(i);
your Code will keep on running till it encounter 'x' so whatever input you give, it will read character by character as you have used getchar() function..
If character is 'x' then break the loop.
else print character.
like, If the input is
sparx
output will be
spar
The for loop
for(i=getchar();; i=getchar())
and syntax and structure of the for loop is
for ( variable initialization; condition; variable update )
as i = getchar() will read char 'i' it is ok. next there is no condition and final in updating you are again reading a character so it a infinite loop.
Loop will terminate only when it will encounter 'x' as the statement
if(i=='x')
break;
Otherwise it will keep on printing the character.
else putchar(i);
Here is the Demo.
Hope it helps!!
Related
My current ruby commandline app uses STDIN.ready?. This permits me to capture complex keys such as Meta keys, Function keys, shifted-function keys etc.
I am not finding anything similar in Crystal.
While searching I found STDIN.raw &.read_char.
According to the docs, this should return a nil when there is nothing to read. However, I am not getting a nil. It seems to wait for the next key. The ruby code had a $stdin.getc.
My logic basically keeps reading STDIN as long as it is ready and accumulating key codes. The moment ready? returns false, the key is evaluated.
The logic NOW is:
c = STDIN.raw &.read_char
if c == '\e' # escape char
loop do
k = STDIN.raw &.read_char
if k
# accumulate k into a string
else
# evaluate string and return
end
end #loop
end
# rest of code if not escape.
Currently the else condition does not execute, so I am stuck in the if part. I don't know when to stop reading keys.
Previously, in ruby I had the second getc inside a if STDIN.ready?.
Earlier in ruby:
if c == '\e'
loop
if STDIN.ready?
k = STDIN.getc
accumulate in string
else
evaluation string and return code
end
end
end
EDIT: for me the correct answer lies in the link to 2048.cr suggested below in a comment.
This is not an answer, it is just a workaround if no correct answers here.
def handle_second_key(buffer)
loop do
input = STDIN.raw &.read_char
buffer << input if input
if buffer.size == 2
if buffer[0] == '\e' && buffer[1] == 'q'
puts "Right combination #{buffer[0].dump} + #{buffer[1].dump}"
exit
else
puts "Wrong combination: #{buffer[0].dump} + #{buffer[1].dump}"
break
end
end
end
end
buffer = [] of Char
loop do
input = STDIN.raw &.read_char
buffer << input if input
if buffer[0] == '\e'
handle_second_key(buffer)
buffer.clear
else
buffer.clear if buffer.size > 0
end
end
how to keep the space betwen the words?
in the code it deletes them and prints them in column.. so how to print them in row and with the space?
s ='[]'
f = open('q4.txt', "r")
for line in f:
for word in line:
b = word.strip()
c = list(b)
for j in b:
if ord(j) == 32:
print ord(33)
if ord(j) == 97:
print ord(123)
if ord(j) == 65:
print ord(91)
chr_nums = chr(ord(j) - 1)
print chr_nums
f.close()
Short answer: remove the word.strip() command - that's deleting the space. Then put a comma after the print operation to prevent a newline: print chr_nums,
There are several problems with your code aside from what you ask about here:
ord() takes a string (character) not an int, so ord(33) will fail.
for word in line: will be iterating over characters, not words, so word will be a single character and for j in b is unnecessary.
Take a look at the first for loop :
for line in f:
here the variable named 'line' is actually a line from the text file you are reading. So this 'line' variable is actually a string. Now take a look at the second for loop :
for word in line:
Here you are using a for loop on a string variable named as 'line' which we have got from the previous loop. So in the variable named 'word' you are not going to get a word, but single characters one by one. Let me demonstrate this using a simple example :
for word in "how are you?":
print(word)
The output of this code will be as follows :
h
o
w
a
r
e
y
o
u
?
You are getting individual characters from the line and so you don't need to use another for loop like you did 'for j in b:'. I hope this helped you.
I am reading stdin in a loop and do some comparaison with a bunch of "if" to decide what to do according to the input.
Here is a shortened snippet of the code :
CHARACTER (len= :), allocatable :: input
CHARACTER (len=4096) :: inbuffer ! frustrating but... well, fortran :3
DO
! get input
READ(*, '(a)') inbuffer ! because apparently you can't have allocation on read so you can't just read "input". meh.
input = TRIM(inbuffer)
CALL debug_log(input)
IF(input .EQ. 'uci') THEN
CALL debug_log(" printing uci info")
!isready
ELSE IF(input .EQ. 'isready') THEN
CALL debug_log(" isready -> readyok")
WRITE(*, '(a)') "readyok"
!ucinewgame
ELSE IF(input .EQ. 'ucinewgame') THEN
CALL debug_log("not implemented : reset board and start a new game")
!position
ELSE IF(input(1:8) .EQ. 'position') THEN
CALL debug_log("not implemented : set position")
!quit -> exit main loop
ELSE IF(input .EQ. 'quit') THEN
CALL debug_log(" quit command issued, exiting main loop")
EXIT
!non uci command
!nothing yet
!unknown command
ELSE
CALL debug_log(" ignoring invalid command")
END IF
end do
The input will expect command like "position 123 23415 etc..."
If I type "posi" it's say it's an invalid command as expected.
If I type "position" it say it's not implemented as expected too.
However:
If I type "position": I get not implemented
Followed by "posi": it says "not implemented" instead of "invalid command"
My guess is that it read 8 character even if the input is only 4 and since the previous command was "position" it make posi + tion = position
Here is some log to demonstrate:
** opening debug file : 20181111 / 223418.127
223418.127 : Initializing Fortiche engine
223418.129 : Entering main loop
223420.859 : posi
223420.859 : ignoring invalid command
223426.467 : xxxxtion
223426.467 : ignoring invalid command
223430.498 : posi
223430.498 : not implemented : set position
223437.323 : xxxxxxxxx
223437.323 : ignoring invalid command
223439.418 : posi
223439.418 : ignoring invalid command
223443.979 : position
223443.979 : not implemented : set position
223447.122 : quit
223447.122 : quit command issued, exiting main loop
223447.122 : closing, bye
xxxxtion + posi = position
Which is clearly wrong but I can understand how it ended up like this.
Should I use something other than .EQ.?
When I print the input it clearly doesn't print the input + whatever garbage was left behind in memory. But it's doing it when comparing string of possibly different length.
What can I do to solve this problem?
I'm not even started with the hardcore parsing and I already have a problem.
I'm using GNU Fortran on Windows.
Yes, it's UCI stuff as Universal Chess Interface.
EDIT : Full source code : https://github.com/ker2x/fortiche (comment the dirty hack at line 107 & 108 to reproduce the problem)
Substring references need to have starting and ending positions that are within the limits of the string.
You don't defend against a string that has a length less than eight prior to the substring reference input(1:8) .eq. 'position'.
With input shorter than eight characters, your program is non-conforming, anything can then happen, where anything very reasonably includes the behaviour you see.
Runtime debugging options may help to catch this programming error, depending on the capabilities of your compiler.
In the following program, if I use the line for the negated scanset, it works fine if I enter a multi-word line (ending with ENTER or newline), even though the newline is in the negated list.
But if I use the line for the scanset instead and enter the word "aegis" (or any word with consonants for that matter), then junk characters are output. Analogous to the first case, shouldn't at least "ae" be output if I enter this word? Please explain this behavior of scanset and negated scanset for scanf().
#include <stdio.h>
int main ()
{
char str[30];
printf("Enter the string\n");
//scanf("%[^\n]",str);
//scanf("%[aeiou]",str);
printf("%s",str);
}
It is because code errantly does not check the return value of scanf()
printf("Enter the string\n");
scanf("%[^\n]",str);
scanf("%[aeiou]",str); // check result before using `str`
printf("%s",str);
With scanf("%[^\n]",str); and input like "123\n", str get the values of "123" and '\n' remains in stdin. Then with scanf("%[aeiou]",str); and input like "aegis\n", the first line's '\n' blocks saving anything as '\n' is not a vowel, nothing is saved in str and since code did not check the return value of scanf(), does not realized that str may be invalid.
1) Always check the return value of scanf() and family.
if (scanf(some_format, var1, var2, ...) != ExpectedConversionCount) {
Fail();
}
2) scanf("%[^\n]",str); to read a line fails 3 things: No input limit, fails to read anything if the the line consists of only '\n'. Without check the return value, EOF is not detected.
3) Use fgets() instead of scanf() for user input.
My assignment (it is not graded and I get nothing from solving it) is to write a lexer/scanner/tokenizer (however you want to call it). flex is used for this class. The lexer is written for Class Object Oriented Language or COOL.
In this language multi-line comments start and end like this:
(* line 1
line 2
line 3 *)
These comments can be nested. In other words the following is valid:
(* comment1 start (* comment 2 start (* comment 3 *) comemnt 2 end *) comment 1 end *)
Strings in this language are regular quoted strings, just like in C. Here is an example:
"This is a string"
"This is another string"
There is also an extra rule saying that there cannot be an EOF in the comment or in the string. For example the following is invalid:
(* comment <EOF>
"My string <EOF>
I wrote a lexer to handle it. It keeps track for a line count by looking for a \n.
Here is the problem that I'm having:
When lexer encounters an EOF in the comment it increments the line count by 1, however when it encounters an EOF in the string it doesn't do it.
For example when lexer encounters the following code
Line 1: (* this is a comment <EOF>
the following error is displayed:
`#2 ERROR "EOF in comment"
However when it encounters this code:
Line 1: "This is a string <EOF>
the following error is displayed:
`#1 ERROR "String contains EOF character"
I can't understand why this (line number is incremented in one case and is not incremented in the other) is happening. Below are some of the rules that I used to match comments and string. If you need more then just ask, I will post them.
<BLOCK_COMMENT>{
[^\n*)(]+ ; /* Eat the comment in chunks */
")" ; /* Eat a lonely right paren */
"(" ; /* Eat a lonely left paren */
"*" ; /* Eat a lonely star */
\n curr_lineno++; /* increment the line count */
}
/*
Can't have EOF in the middle of a block comment
*/
<BLOCK_COMMENT><<EOF>> {
cool_yylval.error_msg = "EOF in comment";
/*
Need to return to INITIAL, otherwise the program will be stuck
in the infinite loop. This was determined experimentally.
*/
BEGIN(INITIAL);
return ERROR;
}
/* Match <back slash>\n or \n */
<STRING>\\\n|\n {
curr_lineno++;
}
<STRING><<EOF>> {
/* String may not have an EOF character */
cool_yylval.error_msg = "String contains EOF character";
/*
Need to return to INITIAL, otherwise the program will be stuck
in the infinite loop. This was determined experimentally.
*/
BEGIN(INITIAL);
return ERROR;
}
So the question is
Why in the case of a comment the line number is incremented and in the case of a string it stays the same?
Any help is appreciated.
Because the pattern for a comment doesn't require a newline to exist in order to increment the line number, and the pattern for a string does.