How can I do cursor control with ANSI using escape sequences using Turbo C? Here I've provided a code, but it's not yet working in my TurboC.
main()
{
while( getche() != '.' )
printf("\x1B[B");
}
Apart from the possibility that that output may be line buffered (meaning nothing may appear until you send a newline), you should probably also ensure that ANSI.SYS is loaded, since it's the device driver responsible for interpreting those sequences.
But I'm wondering why you're doing this. From memory (admittedly pretty faded memory), Turbo C has calls for doing this sort of thing, gotoXY and clrscr and such.
A way of putting escape character with printf() is:
printf("%c[B", 0x1b);
But usually (I don't know Turbo C), there are libraries for doing terminal related stuff in a portable way.
Related
Apologies if this is unclear, but I'm really not sure how to describe this.
See, my issue is that I'm trying to read from the text for user input using fgets(), however, I also need to know if the user presses a special key like /b (backspace) since ideally I want it to start deleting characters from the line before if the current line is empty, like a text editor, which isn't possible with C.
Anyways, let me know if you need more information, thanks in advance.
EDIT: Thought I'd go ahead and post what I have as of now in case someone comes across this later with the same issue to get a better idea
for (; ;)
{
int i;
int key = getch();
if (key == '/b')
{
printf("Hello World");
}
else
{
buffer[i++] = key; // adding character to text user is writing
}
i++;
}
note that this code doesn't work at the moment because of a linker error and something with the /b, but in essence, this could work.
EDIT 2: Thank you chqrlie for bringing up the right way to refer to special characters. Forgot you had to use the backslash for them.
You can certainly write text editors in C :-) A lot of them are.
However, you can't write them in portable C because the facilities required for interactive character-by-character terminal I/O don't exist in standard C. They don't exist because standard C doesn't assume that there is such a thing as a terminal (lots of embedded CPUs don't have any such thing, for example), and it would go far beyond the mandate of ISO C to try to standardise the disparate communications protocols of the various operating systems which do have terminal-like I/O.
getch is an obsolete interface in the Windows conio.h header, and also one of the interfaces in the Curses library, which is available for many operating systems (including Windows). It has nothing to do with fgets, which is part of standard C, and it cannot be implemented using fgets.
It seems likely that what you are trying to do could best be accomplished using an implementation of Curses. (If you're using Linux, as suggested by your avatar, you would be looking for Ncurses.) You might want to look at the Forms library built on top of Ncurses, which provides higher-level input facilities, like editable text boxes.
Another common input-handling library, GNU readline, might also be useful, but it doesn't handle multiline input forms so it would probably be a lot more work.
I found this the above type of code in a pre-completed portion of a coding question in Hackerrank. I was wondering what \n would do? Does it make any difference?
Read some good C reference website, and perhaps the C11 standard n1570 and probably Modern C.
The documentation of scanf(3) explains what is happening for \n in the format control string. It is handled like a space and matches a sequence of space characters (such as ' ', or '\t', or '\n') in the input stream.
If you explicitly want to parse lines, you would use some parser generator like GNU bison and/or use first fgets(3) or getline(3) and later sscanf(3).
Don't forget to handle error cases. See errno(3). Consider documenting using EBNF notation the valid inputs of your program.
Study for inspiration the source code of existing open source programs, including GNU bash or GNU make. Be aware than in 2020 UTF-8 should be used everywhere (then you might want to use libunistring whose source code you could study and improve, since it is free software).
If you use Linux, consider using gdb(1) or ltrace(1) to understand the behavior of your program. Of course, read the documentation of your C compiler (perhaps GCC) and debugger (perhaps GDB).
Experts I've doubts in gets(),puts() and getch().
Why do we use gets() and puts() when we have scanf() and printf()?
What is the use of getch().
Please explain this in simple language because I'm a beginner.
THank you in advance. :)
gets doesn't exist anymore (except in outdated environnments such as the infamous TurboC), use fgets instead.
fgets reads one line of text from a file including from the terminal (standard output)
puts writes one line of text to the terminal (standard output)
fputs writes one line of text to a file, including the terminal (standard output)
getch reads on character from the standard input (terminal)
printf and friends allow you to print formatted output
scanf and friends allow you to read formatted input.
Why do we use gets() and puts() when we have scanf() and printf()?
We don't use gets(), the function was so poorly designed that it was flagged obsolete 18 years ago and finally completely removed from the C language 6 years ago. If someone taught you to use gets(), you need to find a more updated source of learning. See What are the C functions from the standard library that must / should be avoided?.
puts(str) is only used as a micro-optimization of printf("%s", str). puts() is traditionally ever so slightly faster than printf(), since it doesn't need to parse a format string. Today, this performance benefit is a non-issue.
However, puts() is much safer than printf(). You can write bad code like printf("%s", pointer_to_int) and it might compile without warnings. But puts(pointer_to_int) will never compile without warnings/errors.
Generally, most of stdio.h is dangerous and unsafe because of the poor type safety. It is avoided in professional, production-quality code. For student/hobbyist purposes, printf/scanf are however fine.
What is the use of getch()
getch() was a non-standard extension to C, which allowed programs to read a character from stdin without echoing the typed character to stdout (the screen).
This function was popular back in the days of MS DOS when Borland Turbo C was the dominant compiler. Because Turbo C had it, some other compilers also started supporting it together with the non-standard conio.h library. We're talking early 1990s.
You shouldn't use this function in modern C programming.
(Though it is possible to implement it yourself with various API calls, as in this example for Windows.)
I have to draw a box in C, using ncurses;
First, I have defined some values for simplicity:
#define RB "\e(0\x6a\e(B" (ASCII 188,Right bottom, for example)
I have compiled with gcc, over Ubuntu, with -finput-charset=UTF-8 flag.
But, if I try to print with addstr or printw, I get the hexa code.
What I`m doing wrong?
ncurses defines the values ACS_HLINE, ACS_VLINE, ACS_ULCORNER, ACS_URCORNER, ACS_LLCORNER and ACS_LRCORNER. You can use those constants in addch and friends, which should result in your seeing the expected box characters. (There's lots more ACS characters; you'll find a complete list in man addch.)
ncurses needs to know what it is drawing because it needs to know exactly where the cursor is all the time. Outputting console control sequences is not a good idea; if ncurses knows how to handle the sequence, it has its own abstraction for the feature and you should use that abstraction. The ACS ("alternate character set") defines are one of those abstractions.
A few issues:
if your program writes something like "\e(0\x6a\e(B" using addstr, then ncurses (any curses implementation) will translate the individual characters to printable form as described in the addch manual page.
ncurses supports line-drawing for commonly-used pseudo-graphics using symbols (such as ACS_HLINE) which are predefined characters with the A_ALTCHARSET attribute combined. You can read about those in the Line Graphics section of the addch manual page.
the code 0x6a is ASCII j, which (given a VT100-style mapping) would be the lower left corner. The curses symbol for that is ACS_LRCORNER.
you cannot write the line-drawing characters with addstr; instead addch, addchstr are useful. There are also functions oriented to line-drawing (see box and friends).
running in Ubuntu, your locale encoding is probably UTF-8. To make your program work properly, it should initialize the locale as described in the Initialization section of the ncurses manual page. In particular:
setlocale(LC_ALL, "");
Also, your program should link against the ncursesw library (-lncursesw) to use UTF-8, rather than just ncurses (-lncurses).
when compiling on Ubuntu, to use the proper header definitions, you should define _GNU_SOURCE.
BTW, maybe I'm probably arriving somewhat late to the party but I'll give you some insight that might or not shed some light and skills for your "box drawing" needs.
As of 2020 I'm involved in a funny project on my own mixing Swift + Ncurses (under OSX for now, but thinking about mixing it with linux). Apparently it works flawlessly.
The thing is, as I'm using Swift, internally it all reduces to "importing .h and .c" files from some Darwin.ncurses library the MacOS Xcode/runtime offers.
That means (I hope) my newly acquired skills might be useful for you because apparently we're using the very same .h and .c files for our ncurses needs. (or at least they should be really similar)
Said that:
As of now, I "ignored" ACS_corner chars (I can't find them under swift/Xcode/Darwin.ncurses runtime !!!) in favour of pure UTF "corner chars", which also exist in the unicode pointspace, look:
https://en.wikipedia.org/wiki/Box-drawing_character
What does it mean? Whenever I want to use some drawing box chars around I just copy&paste pure UTF-8 chars into my strings, and I send these very strings onto addstr.
Why does it work? Because as someone also answered above, before initializing ncurses with initscr(), I just claimed "I want a proper locale support" in the form of a setlocale(LC_ALL, ""); line.
What did I achieve? Apparently pure magic. And very comfortable one, as I just copy paste box chars inside my normal strings. At least under Darwin.ncurses/OSX Mojave I'm getting, not only "bounding box chars", but also full UTF8 support.
Try the "setlocale(LC_ALL, ""); initscr();" approach and tell us if "drawing boxes" works also for you under a pure C environment just using UTF8 bounding box chars.
Greetings and happy ncursing!
For the sake of education, and programming practice, I'd like to write a simple library that can handle raw keyboard input, and output to the terminal in 'real time'.
I'd like to stick with ansi C as much as possible, I just have no idea where to start something like this. I've done several google searches, and 99% of the results use libraries, or are for C++.
I'd really like to get it working in windows, then port it to OSX when I have the time.
Sticking with Standard C as much as possible is a good idea, but you are not going to get very far with your adopted task using just Standard C. The mechanisms to obtain characters from the terminal one at a time are inherently platform specific. For POSIX systems (MacOS X), look at the <termios.h> header. Older systems use a vast variety of headers and system calls to achieve similar effects. You'll have to decide whether you are going to do any special character handling, remembering that things like 'line kill' can appear at the end of the line and zap all the characters entered so far.
For Windows, you'll need to delve into the WIN32 API - there is going to be essentially no commonality in the code between Unix and Windows, at least where you put the 'terminal' into character-by-character mode. Once you've got a mechanism to read single characters, you can manage common code - probably.
Also, you'll need to worry about the differences between characters and the keys pressed. For example, to enter 'ï' on MacOS X, you type option-u and i. That's three key presses.
To set an open stream to be non-buffered using ANSI C, you can do this:
#include <stdio.h>
if (setvbuf(fd, NULL, _IONBF, 0) == 0)
printf("Set stream to unbuffered mode\n");
(Reference: C89 4.9.5.6)
However, after that you're on your own. :-)
This is not possible using only standard ISO C. However, you can try using the following:
#include <stdio.h>
void setbuf(FILE * restrict stream, char * restrict buf);
and related functions.
Your best bet though is to use the ncurses library.