How to display a moving array in the output console? - c

What's the better way than what I have done below:
system("cls") does the job but clearing the screen will later on mess with whatever that I want to display, the other negative side effect is the annoying blinks.
#include <stdio.h>
#include <stdlib.h>
int a[5]={1,0,1,1,0};
int b[5]={0,0,1,1,1};
int main()
{
srand(time(NULL));
while(1){
//display the arrays
for(int i=0; i<=4; i++){
printf("%d ",a[i]);
}
printf("\n");
for(int i=0; i<=4; i++){
printf("%d ",b[i]);
}
//shift every cell by 1
for (int i = 4 ; i >= 0; i--) {
a[i] = a[i - 1];
b[i] = b[i - 1];
}
sleep(1);
system("cls");
//keep generating 0s and 1s for the 1st cell of arrays
a[0] = rand() %2;
b[0] = rand() %2;
}
}

Without platform/terminal specific code that is not possible as there is no platform independent way to place the cursor or clear the screen.
The best you can do that is largely platform independent is return to the start of the current line, or back-space on the current line. That is to say you can only move the cursor backward on the current cursor line:
What you can do is:
Replace printf("\n"); with printf("\t");
Replace system("cls") ; with:
printf("\r");
fflush(stdout) ;
The output will be on one line with a TAB separation, and the line will be overwritten on each iteration.
1 1 1 0 1 1 0 1 0 0
Failing that you can either:
Use a platform independent console library such as ncurses,
On windows use the native Windows Console API.
Where supported use ANSI escape sequences.
The last option is simplest and while for a long time was not supported in Windows, Windows 10 now supports ANSI ESC sequences, so there are few reasons not to use that for this simple screen handling.
For example ESC[0;0H moves the cursor to the top-left. In this case you would simply replace the "cls" with:
printf( "\x1b[0;0H" ) ;
Note that in this case you also need either a newline or fflush(stdout) before the sleep() to ensure the second line is output before the clear screen:
printf("\n"); // Force output flush
sleep(1);
printf( "\x1b[0;0H" ) ; // Home cursor
If you have other content on the screen before this and you don't want to redraw everything, you could move the cursor by:
printf("\n"); // Force output flush
sleep(1);
printf( "\x1b[2A" ) ; // Cursor Up two lines

Related

ncurses displays characters horizontally instead of vertically

I am writing a simple game in console using ncurses on linux and I have a very odd problem and I cannot find out what's wrong in my code the problem is that when I run my program my screen should look like this
which it does but after my draw() function runs more than 10 times i get something like this
here is my code:
#include <stdio.h>
#include <ncurses.h>
#include <stdlib.h>
#define END endwin();return 0
#define LN 5
#define RN 100
int display [LN][RN] = {
// 1 2 3 4 5 6 7 8 9 q w e r t y u
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},//1
{0,0,'#',0,0,0,0,0,0,0,0,0,0,0,0},//2
{0,0,'#',0,0,0,0,0,0,0,0,0,0,0,0},//3
{0,0,'#',0,0,0,0,0,0,0,0,0,0,0,0},//4
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} //5
};
void setup(){//cr
initscr();
cbreak();
nodelay(stdscr,TRUE);
keypad(stdscr, TRUE);
noecho();
curs_set(0);
for(int i = 0 ; i < RN ; i++){
display[LN - 1][i] = 1;
}
return;
}
void draw(){
system("clear");
for(int i = 0; i < LN ; i++){
for(int j = 0; j < RN ; j++){
if(display[i][j] == 1){
addch(ACS_HLINE);
}
else if(display[i][j] == 0){
addch(' ');
}
else printw("%c",display[i][j]);
}
addch('\n');
}
refresh();
system("sleep 0.3");
return;
}
and I'm using arch
[n]curses keeps an internal map of what the screen is supposed to look like. It uses that map to do efficient updates when you call refresh(). This only works if the library is exclusively in control of the output to the terminal.
When you do terminal output through some other method, like system("clear"), the library no longer has an accurate map of the state of the terminal. The next update sends the escape sequences and printable strings necessary to go from state A to state B, but the terminal is actually in state C, and you end up with something crazy.
There is a curses erase() function which clears the screen, which you should use instead. It's equivalent to using a bunch of addch calls to write blanks in every position.
There's also a clear() function, which does an erase() and a clearok(TRUE), which tells the library to throw away its internal map and redraw the whole screen. This can be used to recover from the situation when something bad has happened, corrupting the screen. So, ironically, you could have gotten away with system("clear") if you'd done a clear() afterward.

Strange output when using system("clear") command in C program

I have the following code
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#define dimensions 5
int RandomNumInRange(int M, int N)
{
return M + rand() / (RAND_MAX / (N - M + 1) + 1);
}
char ** CreateWorld(int dim)
{
int i,j;
char **world = malloc(dim *sizeof(char*));
for(i=0;i<dim;i++)
world[i]=malloc(dim*sizeof(char));
for(i=0;i<dim;i++)
for(j=0;j<dim;j++)
world[i][j]=42;
return world;
}
void CreateCastle(char **world)
{
//assuming world is big enough
//to hold a match of 2
int randRow,randCol;
//1 to dimension -2 so we can spawn a 3x3 castle
randRow = RandomNumInRange(1,dimensions-2);
randCol = RandomNumInRange(1,dimensions-2);
printf("position: %d %d\n", randRow, randCol);
world[randRow][randCol]='c';
//fill the rest so castle is 3x3
//assuming there is enough space for that
world[randRow-1][randCol-1]=35;
world[randRow-1][randCol]=35;
world[randRow-1][randCol+1]=35;
world[randRow][randCol-1]=35;
world[randRow][randCol+1]=35;
world[randRow+1][randCol-1]=35;
world[randRow+1][randCol]=35;
world[randRow+1][randCol+1]=35;
}
void DisplayWorld(char** world)
{
int i,j;
for(i=0;i<dimensions;i++)
{
for(j=0;j<dimensions;j++)
{
printf("%c",world[i][j]);
}
printf("\n");
}
}
int main(void){
system("clear");
int i,j;
srand (time(NULL));
char **world = CreateWorld(dimensions);
DisplayWorld(world);
CreateCastle(world);
printf("Castle Positions:\n");
DisplayWorld(world);
//free allocated memory
free(world);
//3 star strats
char ***world1 = malloc(3 *sizeof(char**));
for(i=0;i<3;i++)
world1[i]=malloc(3*sizeof(char*));
for(i=0;i<3;i++)
for(j=0;j<3;j++)
world1[i][j]="\u254B";
for(i=0;i<3;i++){
for(j=0;j<3;j++)
printf("%s",world1[i][j]);
puts("");
}
free(world1);
//end
return 0 ;
}
If I use the system("clear") command, I get a line consisting of "[3;J"
followed by an expected output. If I run the program again, I get the same gibberish, then many blank newlines, then the expected output. If I put the system("clear") command in comments then both the "[3;J" and the blank newlines don't show and the output is expected.
Edit: it seems the error is not in the code, but rather in the way the terminal on my system is (not) set. Thank you all for your input, I definitely have a lot of interesting stuff to read and learn now.
The codes being sent by your clear command from don't seem to be compatible with the Gnome terminal emulator, which I believe is what you would be using.
The normal control codes to clear a console are CSI H CSI J. (CSI is the Control Sequence Initializer: an escape character \033 followed by a [). CSI H sends the cursor to the home position, and CSI J clears from the cursor position to the end of the screen. You could also use CSI 2 J which clears the entire screen.
On Linux consoles and some terminal emulators, you can use CSI 3 J to clear both the entire screen and the scrollback. I would consider it unfriendly to do this (and the clear command installed on my system doesn't.)
CSI sequences can typically contain semicolons to separate numeric arguments. However, the J command doesn't accept more than one numeric argument and the semicolon seems to cause Gnome terminal to fail to recognize the control sequence. In any event, I don't believe Gnome terminal supports CSI 3 J.
The clear command normally uses the terminfo database to find the correct control sequences for the terminal. It identifies the terminal by using the value of the TERM environment variable, which suggests that you have to wrong value for that variable. Try setting export TERM=xterm and see if you get different results. If that works, you'll have to figure out where Linux Mint configures environment variables and fix it.
On the whole, you shouldn't need to use system("clear") to clear your screen; it's entirely too much overhead for such a simple task. You would be better off using tputs from the ncurses package. However, that also uses the terminfo database, so you will have to fix your TERM setting in any case.

RNG Character Printing Function - More than one line of RNG characters per page? : C

So, I wrote a function (and an RNG function, which the aforementioned function calls) to print a random number of asterisks to the console window, until it hits 90 spaces. The asterisks represent the movement of a car, and the 90 spaces is the length of the track. The code I've included below prints a random number of asterisks until it hits 90 spaces, assuming the fnvMoveSpaces() function is called in main and the user presses a key to resume the loop after each system("PAUSE") until 90 spaces is hit.
My question is, looking at the provided code, how would I get four separate lines of totally independent RNG character printing on the same page of the console window? It needs to look like a legitimate race, on the same screen.
What I've tried:
1) Separate functions for each line, called in main:
Won't work, as they don't happen at the same time. Results in four different pages. I.e. the user has to press a key to get through system("PAUSE") until it hits 90 spaces, then the next function does the same, then the next, and the next. Also, if the loop/function call is outside of the fnvMoveSpaces() main loop, they don't print to the same page.
2) Putting four of the same for loops in the fnvMoveSpaces() function:
This prints four lines to the same screen, but they all move the same increment, because they are pulling from the same RNG value.
Basically, the RNG values for each line need to be totally independent of one another. Would having a different seed value for each line be the answer? I have no idea...
/* - - DEFINED - - */
// Constants of RNG for spaces moved
#define TRACK_LENGTH 90
#define MAX_MOVE_SPACES 10
#define MIN_MOVE_SPACES 1
// Assume fnvMoveSpaces call in main
// Function to create random number for car movement
int fniRandGenMove()
{
// Declare
int randInt;
// Initialize random seed
srand(time(NULL));
// Formula for RNG (1-10) based on global-defined numbers
randInt = (rand() % (MAX_MOVE_SPACES - MIN_MOVE_SPACES + 1) + MIN_MOVE_SPACES);
return (randInt);
}
void fnvMoveSpaces()
{
// Declare
int i;
int iMoveSum;
// Outer for loop to maintain the sum of asterisks
for(iMoveSum = 0; iMoveSum <= TRACK_LENGTH; iMoveSum += fniRandGenMove())
{
// Inner for loop to print asterisks
for(i = 0; i < iMoveSum; i++)
{
putchar('*');
}
// Newline for next line of asterisks
printf("\n");
/*
I'm assuming three more for loops... I tried a bunch of
combinations of things, even making new iMoveSums
(2, 3 and 4) and doing for loops.
But, no luck.
I should also not that making four separate functions for each
line of asterisks will not work, unless there is a way to call all
four at once in main. Separate functions results in separate screens
in the console window. In addition, if the four 'putchar' blocks
are not in the same loop as a whole, the first one will print, hit
90 spaces, then the second, etc... They aren't on the same screen.
*/
// System pause to wait for user
system("PAUSE");
// Clear screen
system("CLS");
}
}
Just to clarify, the current output of this in the console window is this:
**.....*
(Writing in a form of enumeration; no periods actually output.)
Until 90 spaces are hit, then the program closes. Also keep in mind that it prints in random increments each time the user presses a key after system("PAUSE"), until 90. So, not all the asterisks print at once.
What I want it to output is something like this:
*...**
*.........**
**........................*
**..............*
With each line randomly generating its own independent movement increment, until 90 spaces are hit.
Hope that helps.
Thanks,
Bagger
Okay, I got it worked out. Keep in mind that at some point in the near future, I intend to replace the structures with some file I/O. Also, fniRandGenMove is the same as in the question, just move the seed to main, so it only seeds once.
But it works perfectly... the 'cars' race across the console window! It's actually really neat.
void fnvMoveSpaces(int iAutoManual)
{
// Declare
int i, j;
// Declare structures
struct Car stCars[4];
stCars[0].iPosition = 0;
stCars[1].iPosition = 0;
stCars[2].iPosition = 0;
stCars[3].iPosition = 0;
stCars[0].iCarNumber = 1;
stCars[1].iCarNumber = 2;
stCars[2].iCarNumber = 3;
stCars[3].iCarNumber = 4;
struct Car furthestCar;
furthestCar.iPosition = 0;
furthestCar.iCarNumber = 0;
do
{
for(i = 0; i < 4; i++)
{
if(stCars[i].iPosition <= TRACK_LENGTH)
{
stCars[i].iPosition += fniRandGenMove();
}
printf("Car %d\n\t", stCars[i].iCarNumber);
for(j = 0; j < stCars[i].iPosition; j++)
{
printf("*");
}
if (stCars[i].iPosition > furthestCar.iPosition)
{
furthestCar.iPosition = stCars[i].iPosition;
furthestCar.iCarNumber = stCars[i].iCarNumber;
}
printf("\n");
}
system("PAUSE");
system("CLS");
} while(furthestCar.iPosition < TRACK_LENGTH);
printf("The winning car is #%d.\n", furthestCar.iCarNumber);
}

How to stop showing input items in C

Took some element for the matrix, just want to show the output matrix, hiding the matrix elements separately. Could you help please. I have tried as bellow:
#include<stdio.h>
int main() {
int mat[100][100];
int row, column, i, j;
printf("enter how many row and column you want:\n \n");
scanf("%d", &row);
scanf("%d", &column);
printf("enter the matrix:");
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++) {
scanf("%d", &mat[i][j]);
}
printf("\n");
}
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++) {
printf("%d \t", mat[i][j]);
}
printf("\n");
}
}
Actually it's not compiler dependant, but platform dependant.
The thing you are looking for is called Termcap for "Terminal capability".
It basically allow you to configure your terminal but it's not necessary simple as you need to understand a bit how a terminal works.
This link should interest you if you are working on linux.
http://man7.org/linux/man-pages/man3/termios.3.html
I'm not sure on this point but I think there's a library that allow you to have the same code for linux/windows.
Sorry not to be more precise it's been a long time since I didn't play with that.
use the tcgetattr() function on the serial/usb port used by your terminal to get the current setup of the terminal driver.
use the tcsetattr() function to update the serial/usb port used by your terminal to turn off the echo feature of the terminal driver.
use the escape sequences to move the cursor around on the terminal, change colors, etc.
Be sure to save the original settings returned from the call to tcgetattr() so you can easily restore the terminal driver to its' original settings.
Read the man page for tcgetattr(3) and tcsetattr(3) for all the details of those commands. The details can be found online at: http://man7.org/linux/man-pages/man3/termios.3.html
Read the man page for console_codes(4). The details can be found online at: http://man7.org/linux/man-pages/man4/console_codes.4.html

Informative "if" statement in "for" loop

Normally when I have a big for loop I put messages to inform me in which part of the process my program is, for example:
for(i = 0; i < large_n; i++) {
if( i % (large_n)/1000 == 0) {
printf("We are at %ld \n", i);
}
// Do some other stuff
}
I was wondering if this hurts too much the performance (a priori) and if it is the case if there is a smarter alternative.Thanks in advance.
Maybe you can split the large loop in order to check the condition sometimes only, but I don't know if this will really save time, that depends more on your "other stuff".
int T = ...; // times to check the condition, make sure large_n % T == 0
for(int t = 0; t < T; ++t)
{
for(int i = large_n/T * t; i < large_n/T * (t+1); ++i)
{
// other stuff
}
printf("We are at %ld \n", large_n/T * (t+1));
}
Regardless of what is in your loop, I wouldn't be leaving statements like printf in unless it's essential to the application/user, nor would I use what are effectively redundant if statements, for the same reason.
Both of these are examples of trace level debugging. They're totally valid and in some cases very useful, but generally not ultimately so in the end application. In this respect, a usual thing to do is to only include them in the build when you actually want to use the information they provide. In this case, you might do something like this:
#define DEBUG
for(i = 0; i < large_n; i++)
{
#ifdef DEBUG
if( i % (large_n)/1000 == 0)
{
printf("We are at %ld \n", i);
}
#endif
}
Regarding the performance cost of including these debug outputs all the time, it will totally depend on the system you're running, the efficiency of whatever "printing" statement you're using to output the data, the check/s you're performing and, of course, how often you're trying to perform output.
Your mod test probably doesn't hurt performance but if you want a very quick test and you're prepared for multiples of two then consider a mathematical and test:
if ( ( i & 0xFF ) == 0 ) {
/* this gets printed every 256 iterations */
...
}
or
if ( ( i & 0xFFFF ) == 0 ) {
/* this gets printed every 65536 iterations */
...
}
By placing a print statement inside of the for loop, you are sacrificing some performance.
Because the program needs to do a system call to write output to the screen every time the message is printed, it takes CPU time away from the program itself.
You can see the difference in performance between these two loops:
int i;
printf("Start Loop A\n");
for(i = 0; i < 100000; i++) {
printf("%d ", i);
}
printf("Done with Loop A\n");
printf("Start Loop B\n");
for(i = 0; i < 100000; i++) {
// Do Nothing
}
printf("Done with Loop B\n");
I would include timing code, but I am in the middle of work and can update it later over lunch.
If the difference isn't noticeable, you can increase 100000 to a larger number (although too large a number would cause the first loop to take WAY too long to complete).
Whoops, forgot to finish my answer.
To cut down on the number of system calls your program needs to make, you could check a condition first, and only print if that condition is true.
For example, if you were counting up as in my example code, you could only print out every 100th number by using %:
int i;
for(i = 0; i < 100000; i++) {
if(i%100 == 0)
printf("%d", i);
}
That will reduce the number of syscalls from ~100000 to ~1000, which in turn would increase the performance of the loop.
The problem is IO operation printf takes a much time than processor calculates. you can reduce the time if you can add them all and print finally.
Notation:
Tp = total time spent executing the progress statements.
Tn = total time spent doing the other normal stuff.
>> = Much greater than
If performance is your main criteria, you want Tn >> Tp. This strongly suggests that the code should be profiled so that you can pick appropriate values. The routine 'printf()' is considered a slow routine (much slower than %) and is a blocking routine (that is, the thread that calls it may pend waiting for a resource used by it).
Personally, I like to abstract away the progress indicator. It can be a logging mechanism,
a printf, a progress box, .... Heck, it may be updating a structure that is read by another thread/task/process.
id = progressRegister (<some predefined type of progress update mechanism>);
for(i = 0; i < large_n; i++) {
progressUpdate (id, <string>, i, large_n);
// Do some other stuff
}
progressUnregister(id);
Yes, there is some overhead in calling the routine 'progressUpdate()' on each iteration, but again, as long as Tn >> Tp, it usually is not that important.
Hope this helps.

Resources