How could I achieve gotoxy() in gcc - c

I am using gcc in ubuntu.so, I compile and execute in terminal. But In a online programming contest, they require the output as shown in diagram.
For that, if I use TURBOC I can get it using conio.h using gotoxy() to get spiral format of output. But in Ubuntu , How could I achieve this?

Assuming because it is a contest and they don't want dependencies like ncurses you could try to do it in memory.
Set up 2 dimensional array of char - lines and columns - say 24x80. Write your own version of gotoxy() which assigns values into the proper cells. When done plotting, print out the array of lines.

Use the ncurses library.
Here's an example, adapted from http://www.paulgriffiths.net/program/c/srcs/curhellosrc.html
#include <stdlib.h>
#include <stdio.h>
#include <curses.h>
int main(void) {
WINDOW * mainwin;
/* Initialize ncurses */
if ( (mainwin = initscr()) == NULL ) {
fprintf(stderr, "Error initialising ncurses.\n");
exit(EXIT_FAILURE);
}
move(10, 15);
addch('X');
refresh();
getch();
delwin(mainwin);
endwin();
refresh();
return EXIT_SUCCESS;
}
Further information is available here: http://invisible-island.net/ncurses/ncurses-intro.html#stdscr

Aside of ANSI escape sequences you might wish to investigate ncurses:
http://www.gnu.org/s/ncurses/
It all ultimately depends upon the capabilities of the terminal running the program, not the actual host, language, or library. Consider what happens redirecting program output to a file or to a printer.
conio.h API is more to do with a fixed console, with Unix like systems you usual deal with terminals which can be more varied such as resizable X-Terminals.

Determine how many lines of output you need. Allocate an array of "char *" with one entry per line of output needed. When you place a number use "realloc()" to increase the size of the line and fill from the old end to the new end with spaces (if necessary); then put your number at the right place in that line (in memory).
After you've build an array of string in memory; do a for loop that prints each line (and frees the memory you allocated).
You don't need "gotoxy()" or anything to control cursor position.

Since it isn't here yet, I just wanted to say about an example using ANSI escape sequences as Steve-o mentioned.
void gotoxy(int x, int y)
{
printf("%c[%d;%df", 0x1B, y, x);
}
I got it from here.
0x1B is hexadecimal for 27 in decimal and is the ASCII for ESC. The escape sequences start with it
%m;%nf moves the cursor to row n, column m.
The ANSI escape sequences are used "to control the formatting, color, and other output options on video text terminals"

Related

top and bottom half block character in ncurses

I'm building a ncurses program in c and i want to get the upper and lower half block characters (U+2580 and U+2584 for example) (▀) for graphics on small terminals (i normally use double space and inverted double space). I've tried a lot of different ways, but none of them worked. I also tried urxvt st and xterm with absolutely no success. For example:
#include <locale.h>
#include <ncurses.h>
int main (int argc, char *argv[]) {
setlocale(LC_ALL, "");
initscr();
add_wch(L"\u2584");
refresh();
getch();
endwin();
}
Also, i would be very interested if there is any other way of displaying graphics in a terminal, like some tiny dots i've seen.
EDIT: Also, when i paste the character to the terminal it shows it fine but when i use printf it shows nothing. why is that?
The statement
add_wch(L"\u2584");
won't work for any terminal because the parameter is the wrong datatype. add_wch expects a cchar_t datatype, while you have provided a string of wchar_t (you'll get better results with waddwstr).

pre-fill stdin in C

My program is supposed to let the user edit a line of a file. The user edits the line and sends it back by pressing enter. Therefore I would like to print the current line which is about to be edited, but kind of print it on stdin instead of stdout.
The only problem I don't know how to solve is how I can prefill the stdin. I've already tried this:
char cprefill[] = {"You may edit this line"};
char cbuffer[100];
fprintf(stdin, cprefill);
fgets(cbuffer, 100, stdin);
This seems to be the simplest solution, but is probably too simple to work. The fprintf doesn't print anything to stdin. What is the correct way?
Edit:
This is how it is supposed to look like. Please mind the cursor which can be moved.
The C language has no notion of terminal nor of line edition, so it cannot be done in a portable way. You can either rely on a library like [n]curses to get an almost portable solution, or if you only need that on one single OS use low level OS primitives.
For exemple on Windows, you could feed the input buffer by simulating key strokes into the appropriate window (for example by sending WM_CHAR messages) just before reading, but that would be highly non portable - and in the end is no longer a C but a Windows solution...
First you need the libreadline developer package. (You might also need the libreadline if it's not already available on your system)
On Debian / Ubuntu that's apt install libreadline-dev (plus libreadline6 if you need the binaries also - 6 might be different on your platform)
Then you can add an history to readline, like this
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
...
char cprefill[] = {"You may edit this line"};
add_history(cprefill);
char *buf = readline("Line: ");
printf("Edited line is %s\n", buf);
// free the line allocated by readline
free(buf);
User is prompted "Line: ", and has to do UP ARROW to get and edit the history, i.e. the cprefill line.
Note that you have to compile/link with -lreadline
readline prints the prompt given as argument, then waits for user interaction, allowing line edition, and arrows to load lines stored in the history.
The char * returned by readline has then to be freed (since that function allocates a buffer with malloc()).
You could use GNU Readline. It calls the function that rl_startup_hook points to when starting, where we use rl_insert_text to put our text in the line buffer.
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
int prefill(void)
{
rl_insert_text("You may edit this line");
return 0;
}
int main(void)
{
char *cbuffer;
puts("Please edit the following line");
rl_startup_hook = prefill;
if ((cbuffer = readline(NULL)) == NULL) /* if the user sends EOF, readline will return NULL */
return 1;
printf("You entered: %s\n", cbuffer);
free(cbuffer);
return 0;
}
For more information, see the GNU Readline manual.

Get in which terminal column I'm writing

In my C program I would like to know where my cursor is located in terminal. For example, another program could have written something before mine and I would like to know how much space is left before the last column of the terminal, or I could not know the terminal reaction to some special sequences (like colors: I could write it but they are not showed).
Any suggestion?
Edit: it would be better avoiding over complicated solutions like ncurses (ncurses doesn't know where's the cursor directly: it computes its position).
Edit 2: I found a way to do it, but it works only in non-graphical terminals: https://www.linuxquestions.org/questions/programming-9/get-cursor-position-in-c-947833/
Edit 3: Nice code and it works well, but it uses /dev/vcsaN (same problem of Edit 2): http://dell9.ma.utexas.edu/cgi-bin/man-cgi?vcs+4
Ncurses is a big and powerful library for creating terminal-based text interfaces.
tputs is a simple low-level universal function for manipulating terminal capabilities.
Either one could serve your needs.
You could try using ncurses' getyx().
This solution is not optimal because it refers to /dev/vcsa*. Hope this could help someone else.
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
int fd;
char *device = "/dev/vcsa2";
struct {unsigned char lines, cols, x, y;} scrn;
fd = open(device, O_RDWR);
if (fd < 0) {
perror(device);
exit(EXIT_FAILURE);
}
(void) read(fd, &scrn, 4);
printf("%d %d\n", scrn.x, scrn.y);
exit(EXIT_SUCCESS);
}
Generally you are supposed to remember where you've left the cursor.
However, most terminals do respond to DSR; Device Status Request. By sending
CSI 6 n
you'll receive a CPR; cursor position report, in the form of
CSI Pl;Pc R
where Pl and Pc give the cursor line and column number, indexed from 1.

how to print to console graphically in C on unix

So I'm familiar with printf and the like, but I need to update a single line on the screen without having multiple lines scrolling. I have found libraries to do this in windows (conio.h) but not in unix. I need to be able to run this in cygwin, but any unix examples would be welcome.
I found the following stackoverflow article , but I don't think it quite closes the question for my needs.
Thanks for your help
It depends on whether you're trying to do a text-mode full-screen application (in which case ncurses is probably what you want) or just want to update a single line in-place (e.g., you want to update an "X percent done" indicator from 1 to 100, with all the output appearing on the same line so when X percent done is printed, it prints "over" the previous X-1 percent done indicator). In the latter case, you can write code that's relatively portable, and considerably simpler as well. For example, something like this:
#include <windows.h> // Used only for "Sleep" in our simulated work load
#include <stdio.h>
void do_work() {
// Simulated work load. Just waste some time:
Sleep(100);
}
int main() {
for (int i=0; i<100; i++) {
char buffer[82];
sprintf(buffer, "%d percent done", i+1);
printf("\r%-79s", buffer);
do_work();
}
return 0;
}
You want Ncurses for this. It's a library which allows you to edit any character on the screen.

How to overwrite stdout in C

In most modern shells, you can hit the up and down arrows and it will put, at the prompt, previous commands that you have executed. My question is, how does this work?!
It seems to me that the shell is somehow manipulating stdout to overwrite what it has already written?
I notice that programs like wget do this as well. Does anybody have any idea how they do it?
It's not manipulating stdout -- it's overwriting the characters which have already been displayed by the terminal.
Try this:
#include <stdio.h>
#include <unistd.h>
static char bar[] = "======================================="
"======================================>";
int main() {
int i;
for (i = 77; i >= 0; i--) {
printf("[%s]\r", &bar[i]);
fflush(stdout);
sleep(1);
}
printf("\n");
return 0;
}
That's pretty close to wget's output, right? \r is a carriage-return, which the terminal interprets as "move the cursor back to the start of the current line".
Your shell, if it's bash, uses the GNU Readline library, which provides much more general functionality, including detecting terminal types, history management, programmable key bindings, etc.
One more thing -- when in doubt, the source for your wget, your shell, etc. are all available.
To overwrite the current standard output line (or parts of it) use \r (or \b.) The special character \r (carriage return) will return the caret to the beginning of the line, allowing you to overwrite it. The special character \b will bring the caret back one position only, allowing you to overwrite the last character, e.g.
#include <stdio.h>
#include <unistd.h>
int i;
const char progress[] = "|/-\\";
for (i = 0; i < 100; i += 10) {
printf("Processing: %3d%%\r",i); /* \r returns the caret to the line start */
fflush(stdout);
sleep(1);
}
printf("\n"); /* goes to the next line */
fflush(stdout);
printf("Processing: ");
for (i = 0; i < 100; i += 10) {
printf("%c\b", progress[(i/10)%sizeof(progress)]); /* \b goes one back */
fflush(stdout);
sleep(1);
}
printf("\n"); /* goes to the next line */
fflush(stdout);
Use fflush(stdout); because standard output is usually buffered and the information may not otherwise be immediately printed on the output or terminal
In addition to \r and \b, take a look at ncurses for some advanced control over what's on the console screen. (Including columns, moving around arbitrarily, etc).
A program running in a text terminal / console can manipulate the text displayed in its console in various ways (make text bold, move cursor, clear screen etc.). This is accomplished by printing special character sequences, called "escape sequences" (because they usually start with Escape, ASCII 27).
If stdout goes to a terminal which understands these escape sequences, the display of the terminal will change accordingly.
If you redirect stdout to a file, the escape sequences will appear in the file (which is usually not what you want).
There is no complete standard for escape sequences, but most terminals use the sequences introduced by VT100, with many extensions. This is what most terminals under Unix/Linux (xterm, rxvt, konsole) and others like PuTTY understand.
In practice, you would not directly hardcode escape sequences into your software (though you could), but use a library to print them, such as ncurses or GNU readline mentioned above. This allows compatibility with different terminal types.
It's done with the readline library... I'm not sure how it works behind the scenes but I don't think it has anything to do with stdout or streams. I suspect readline uses some sort of cryptic (to me, at least) terminal commands - that is, it cooperates with the terminal program that actually displays your shell session. I don't know that you can get readline-like behavior just by printing output.
(Think about this: stdout can be redirected to a file, but the up/down-arrow keys trick doesn't work on files.)
You can use carriage return to simulate this.
#include <stdio.h>
int main(int argc, char* argv[])
{
while(1)
{
printf("***********");
fflush(stdout);
sleep(1);
printf("\r");
printf("...........");
sleep(1);
}
return 0;
}
The program does this by printing special characters that the terminal interprets in a special way. The most simple version of this is (on most linux/unix terminals) to print '\r' (carriage return) to the normal stdout which resets the cursor position to the first character in the current line. So the thing you write next will overwrite the line you wrote previously. This can be used for simple progress indicators, for example.
int i = 0;
while (something) {
i++;
printf("\rprocessing line %i...", i);
...
}
But there are more complicated escape characters sequences that are interpreted in various ways. All kinds of things can be done with this, like positioning the cursor at a specific position on the screen or setting the text color. If or how these character sequences are interpreted depends on your terminal, but a common class supported by most terminals are ansi escape sequences. So if you want red text, try:
printf("Text in \033[1;31mred\033[0m\n");
The simplest way is to print to stdout the carriage return character ('\r').
The cursor will be moved to the start of the line, allowing you to overwrite its contents.

Resources