I would like to display the seconds elapsed after the start of program:
volatile time_t start_time = time(NULL);
volatile time_t target_seconds = 60*60*17;
volatile time_t time_passed = 0;
while(1)
{
time_passed = time(NULL)-start_time;
printf("\rTime elapsed=%lu/%lu(seconds)", time_passed, target_seconds);
}
Output:
Time elapsed=1/61200(second)
But it will keep updating the display no matter what value time_passed is.
Now I only want to update the displaying time elapsed when the actual time is incremented.
So I changed the program in this way:
volatile time_t start_time = time(NULL);
volatile time_t target_seconds = 60*60*17;
volatile time_t time_passed = 0;
while(1){
if ((time(NULL)-start_time) != time_passed)
{
time_passed = time(NULL)-start_time;
printf("\rTime elapsed=%lu/%lu(seconds)", time_passed, target_seconds);
}
}
Now it displays nothing.
Can anyone explain why and how to solve it.
Your code is fine.
But depending on your platform the output buffer is flushed only when a \n is printed.
Therefore you should add fflush(stdout); right after the printf.
if ((time(NULL)-start_time) != time_passed)
{
time_passed = time(NULL)-start_time;
printf("\rTime elapsed=%lu/%lu(seconds)", time_passed, target_seconds);
fflush(stdout);
}
BTW: if you wait long enough, you'll end up seeing some output because eventually the output buffer will be full and then everything will be displayed at once, which of course doesn't make much sense here.
The reason why you see immediately output with the first version of your code is that your're printing contiuously and therefore the output buffer will be full very quickly, and it will be flushed contiuously hence you see output.
The volatile keyword is not required here, it's absolutely unnecessary but it doesn't harm either.
Apart from calling fflush after every printf it's also possible to turn off buffering on stdout. use either setbuf or setvbuf
#include <stdio.h>
setbuf(stdout, NULL);
setvbuf(stdout, NULL, _IONBF, 0);
Now every character will get printed
Related
I'm struggling to make a timer in c that counts minutes and seconds. I'm trying to test it by printing the time to the console but it doesn't seem to show anything. Does anything look wrong in my code?
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define TRUE 1
int main( void )
{
int min = 0;
int sec = 0;
while (TRUE)
{
sec++;
Sleep(1000);
printf("%2d:%2d", min, sec);
if (sec == 59)
{
min++;
sec = 0;
}
}
return 0;
}
For performance reason, printf is buffered. That is, it won't display until the buffer is full. First thing to try is to add a new-line character to the end:
printf("%2d:%2d\n", min, sec);
If that doesn't work, you can force the output buffer to flush by calling fflush(stdout);
I would just check the system time rather than keeping track of seconds/minutes. This is because, your Sleep may not be exactly 1000ms, so over time your counter will not be accurate.
Since you're using Windows, here's a slightly modified version of your code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
int main()
{
for (;;)
{
time_t now = time(NULL);
struct tm* ptm = localtime(&now);
printf("%02d:%02d\n", ptm->tm_min, ptm->tm_sec);
Sleep(1000);
}
return 0;
}
I hope that helps.
As you ask, there are several things wrong in your code, I'll tell you as I read it. See below.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define TRUE 1
int main( void )
{
int min = 0;
int sec = 0;
while (TRUE)
{
sec++;
Sleep(1000);
There's a problem with Sleep(). The thing is that you ask the kernel to pause your program for 1000 milliseconds, but that means that the kernel will awake your program 1 second after your call it to pause. This doesn't take into account the fact that the kernel will put in the schedule queue your process and it will, in general never take the cpu immediately, but after some delay. Then, even if you get the cpu immediately, your code will need some time to execute, making the total loop longer than 1000 ms. And your clock will be slow. It is better to get the system time and show it on the screen, or to take a timestamp when you start... and then show the difference in time from the start time to the timestamp you get at each display. The system time is maintained by an interrupt, that happens at regular intervals (by means of a precise clock oscillator) so you'll get a good clock time that way, instead of your slow clock (how slow it is will depend on things like how many other processes you are running on the system)
printf("%2d:%2d", min, sec);
This has already been stated in other answers, but let me explain how it works so you can understand how buffering works. A buffer is a large block of memory (normally it is 512 bytes) that is filled by printf() so it only calls write() when it has filled a complete buffer of data. This allows stdio to save system calls to do the actual writing and so, be more efficient when transferring large amounts of data.
On interactive applications, this is not applicable, as no output would be done if you don't force the buffers to fflush() before any input is done, so when the output is a tty device (something that stdio can know from the file descriptor associated to standard output) then it switches to line mode buffering, and that means that printf() will flush out the buffer when: 1) it is filled up, or 2) when a newline \n character is found in the output. So, one way to solve your problem is to put a \n at the end of the string, or to call fflush(stdout); after calling printf().
if (sec == 59)
as you increment your seconds before comparing, you have to check against 60 and not 59, as you compare with 60 to convert it to 0 after you have already incremented the seconds.
{
min++;
You should have to do the same with the minutes, when minutes get to 60. As you have not included this code, I assume you are not considering an hours chrono.
sec = 0;
}
}
return 0;
}
A complete solution for what I mean can be:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <windows.h>
int main()
{
long start_timestamp;
long display_timestamp;
start_timestamp = time(NULL);
for(;;) { /* this is the same as while(TRUE) */
display_timestamp = time(NULL);
int elapsed = display_timestamp - start_timestamp;
int min = elapsed / 60;
int sec = elapsed % 60;
/* the \r in next printf will make to print a single carry
* return in the same line, so the time updates on top of
* itself */
printf("\r%02d:%02d", min, sec); fflush(stdout);
Sleep(100); /* as you print the time elapsed, you don't
* mind if you shorten the time between
* displays. */
}
}
Does anything look wrong in my code?
Several things look wrong. The first is stdout line buffering - see eduffy's answer for that.
The second problem is that you're doing sec++; sleep(1000);, which means that sec will be incremented once every 1000 seconds or more.
The third problem is that if(sec == 59; is wrong and needs to be if(sec == 60). Otherwise you'll have 59 seconds per minute.
The fourth problem is that sleep(1) will sleep for at least 1 second, but may sleep for 2 seconds, or 10 seconds, or 1234 seconds. To guard against this you want something more like this:
expiry = now() + delay;
while(true) {
sleep(expiry - now() ):
expiry += delay;
}
The basic idea being that if one sleep takes too long then the next sleep will sleep less; and it'll end up being "correct on average".
The last problem is that sleep() doesn't really have enough precision. For 1 second delays you want to be able to sleep for fractions of a second (e.g. like maybe 9/10ths of a second). Depending on which compiler for which OS, there's probably something better you can use (e.g. maybe nanosleep()). Sadly there may be nothing that's actually good (e.g. some sort of "nanosleep_until(expiry_time)" that prevents jitter caused by IRQs and/or task switches that occur after you determine now but before you call something like "nanosleep()").
I want to print the seconds elapsed in real time since the program began. First the output is "0". After one second, the "0" is replaced by "1", and so on. Here is the code I wrote initially.
#include<stdio.h>
#include<time.h>
void main ()
{
long int time;
printf("Hello, let us measure the time!\n");
time=clock();
printf("%ld", 0);
while(time/CLOCKS_PER_SEC<7)
{
time=clock();
if(time%CLOCKS_PER_SEC==0)
{
printf("\r");
printf("%ld", time/CLOCKS_PER_SEC);
}
}
}
This gave an output "7" at the end of 7 seconds only.
If I make the following replacements, the code works fine.
printf("%ld", 0);
by
printf("%ld\n", 0);
and
printf("\r");
printf("%ld", time/CLOCKS_PER_SEC);
by
printf("\33[A"); //vt100 char, moves cursor up
printf("\33[2K"); //vt100 char, erases current line
printf("%ld\n", time/CLOCKS_PER_SEC);
The problem seems that the output wont be sent until the current line is completely determined. What is happening here?
I am using gcc compiler on Ubuntu.
The output stream that you are writing to with printf() will buffer until the newline is received. Since you aren't sending a newline then you get no flush until your application exits or the buffer fills up.
You can flush the output buffer yourself after each printf(), as hyde said in the comment above using fflush(stdout).
Or you can disable buffering by using setbuf( stdout, NULL );
I am trying to run the following code :
#include <sys/time.h>
#include <stdio.h>
int main()
{
unsigned int ms, oldms = 0,dif;
struct timeval tv;
while(1)
{
gettimeofday(&tv, NULL);
ms=tv.tv_sec;
//printf("%d\n",ms-oldms );
dif=ms-oldms;
if(dif>3)
{
printf("3 seconds up");
oldms=ms;
}
}
}
I am expecting it to print "3 seconds up" after every 3 seconds, but it doesn't display that message.
I tried to debug it using gdb but nothing seems wrong and still no output.
While trying to debug, I added a printf statement and magically the output can be seen.
If I run the program after removing the //printf("%d\n",ms-oldms ); statement , there is no output again.I am not sure what's happening and whether its dependant on anything.
$gcc --version
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Output buffering is the reason.
stdout is line buffered by default when attached to a terminal device. You can flush this out using fflush(stdout); or using \n in printf() i.e. printf("3 seconds up\n");.
or disabling it with setbuf(stdout, 0);
I/O is slow in general. So implementations use a fixed size buffer and printf once it gets full.
In practice, calling fflush(stdout); too often can affect performance.
the posted code has a couple of problems
the variable oldms is not being set to any specific value before the elapsed time is being checked
without either a call to fflush(stdout); or a trailing newline ('\n') in the format string, nothing will be output (for a very long time, until the system stdout buffer is filled)
for readability, the axiom only one statement per line and (at most) one variable declaration per statement is applied to the code
the following code compiles cleanly and performs the desired operation
#include <sys/time.h>
#include <stdio.h>
int main()
{
unsigned int ms;
unsigned int oldms = 0;
unsigned int dif;
struct timeval tv;
gettimeofday(&tv, NULL);
oldms = tv.tv_sec;
while(1)
{
gettimeofday(&tv, NULL);
ms=tv.tv_sec;
//printf("%d\n",ms-oldms );
dif=ms-oldms;
if(dif>3)
{
printf("3 seconds up\n");
oldms=ms;
}
}
} // end function: main
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void delay(double sec)
{
clock_t start = clock();
while ((clock() - start) / CLOCKS_PER_SEC < sec)
;
}
int main()
{
for (int i = 0; i < 100000; i++) {
printf("%d ", i);
delay(1);
}
return 0;
}
I wrote a delay function and tested it with this code, but I didn't see any number in standard output.
Then I changed the printf() call like this :
printf("%d \n", i);
Interestingly, it worked. I also tried without delay function like this:
for (int i = 0; i < 100000; i++)
printf("%d ", i);
It also worked. What am I missing here? Why can't I see any number when I run the first code? Thanks for helps :)
Because the output is buffered. Most terminals will buffer the standard-output until either a newline (\n) is encountered, or fflush(stdout) is called.
Your loop that includes the call to delay should eventually print the numbers, but when the program is finished.
Add fflush(stdout); after the printf-call to make the numbers appear immediately without newlines in between.
Well, there are two reasons. First, printf() doesn't always flush its output, so you may actually get past the printf statement and still not see anything on your terminal. The text is buffered. Putting in a \n may have caused it to flush its output, so that's why that worked.
The second problem is that you are not passing any value to your delay() function. So it's probably using some random value, and hanging.
I'd also like to point out that clock() returns CPU time, not "wall clock" time, so it may actually take longer than you think.
Delay functions are tricky, that's why there are lots of system calls to do them. See sleep().
I'm working on a class project in which I must write a command line shell with the following requirements:
The shell must able to read buffered input
Buffer should be 64 characters
Error conditions should be handled
Exceeded buffer size
Interruptions (when a signal arrives) – see the man page for read()
Invalid input (unparsable characters, blank lines, etc)
Any other error that may be encountered.
Shell must have a history of at least 20 items, and the history must not be of a static size. When the history buffer is full, the oldest item is removed and the newest item added.
Programs should be able to run in the foreground or background. (using &)
Ctrl-D will exit the shell
Ctrl-C will print the complete history
The Command ‘history’ will also print the complete history. Newest items will be at the bottom of the list.
All other signals will be trapped and displayed to the user in the shell
Program will use the read() command to read in input, unless the arrow keys are supported
I have opted to implement arrow keys for history cycling, so I'm using ncurses for input, rather than read(). I think I'm doing all right using strtok() to parse input, and fork() and execvp() to run the processes, but I'm not doing all right implementing ncurses correctly. All I've gotten it to do so far is init a new screen, display the prompt, then segfault upon any key press. Not good.
I reckon the problem must be in my design. I'm not wrapping my head around ncurses too well. What sort of data structures should I be using for this project? How should I handle the ncurses setup, teardown, and everything in between? What's the deal with windows and screens, and should I have a single globally accessible window/screen that I work with? Also, I've been trying to use a char* for the input buffer, and a char** for the command history, but I have no experience in C, so despite reading up on malloc, calloc, and realloc, I'm not sure of the best way to store commands in the buffer and the history. Any tips on managing these char arrays?
tl;dr: How do I use ncurses correctly to make a command line shell, and how do I handle the command memory management with C?
I realize this is a pretty hefty question. :(
edit: I have already seen http://www.gnu.org/software/libc/manual/html_node/Implementing-a-Shell.html and http://www.linuxinfor.com/english/NCURSES-Programming/ but the ncurses documentation has actually too much overhead. I just want to use its ability to recognize arrow keys.
Here's some sample code which:
Performs dynamic memory allocation.
Reads from the console in non-blocking mode.
Uses VT100 codes to print a frame buffer to the console.
It compiles on Linux using GCC without warnings or errors. It's far from bug free, but it should give you some ideas of what's possible. Compile and run it, pressing [up] and [down] will print messages, typing characters and hitting [enter] will "execute" the command.
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/** VT100 command to clear the screen. Use puts(VT100_CLEAR_SCREEN) to clear
* the screen. */
#define VT100_CLEAR_SCREEN "\033[2J"
/** VT100 command to reset the cursor to the top left hand corner of the
* screen. */
#define VT100_CURSOR_TO_ORIGIN "\033[H"
struct frame_s
{
int x;
int y;
char *data;
};
static int draw_frame(struct frame_s *frame)
{
int row;
char *data;
int attrib;
puts(VT100_CLEAR_SCREEN);
puts(VT100_CURSOR_TO_ORIGIN);
for (row = 0, data = frame->data; row < frame->y; row++, data += frame->x)
{
/* 0 for normal, 1 for bold, 7 for reverse. */
attrib = 0;
/* The VT100 commands to move the cursor, set the attribute, and the
* actual frame line. */
fprintf(stdout, "\033[%d;%dH\033[0m\033[%dm%.*s", row + 1, 0, attrib, frame->x, data);
fflush(stdout);
}
return (0);
}
int main(void)
{
const struct timespec timeout = { .tv_sec = 1, .tv_nsec = 0 };
struct frame_s frame;
struct termios tty_old;
struct termios tty_new;
unsigned char line[128];
unsigned int count = 0;
int ret;
struct pollfd fds[1];
sigset_t sigmask;
struct tm *tp;
time_t current_time;
/* Set up a little frame. */
frame.x = 80;
frame.y = 5;
frame.data = malloc(frame.x * frame.y);
if (frame.data == NULL)
{
fprintf(stderr, "No memory\n");
exit (1);
}
memset(frame.data, ' ', frame.x * frame.y);
/* Get the terminal state. */
tcgetattr(STDIN_FILENO, &tty_old);
tty_new = tty_old;
/* Turn off "cooked" mode (line buffering) and set minimum characters
* to zero (i.e. non-blocking). */
tty_new.c_lflag &= ~ICANON;
tty_new.c_cc[VMIN] = 0;
/* Set the terminal attributes. */
tcsetattr(STDIN_FILENO, TCSANOW, &tty_new);
/* Un-mask all signals while in ppoll() so any signal will cause
* ppoll() to return prematurely. */
sigemptyset(&sigmask);
fds[0].events = POLLIN;
fds[0].fd = STDIN_FILENO;
/* Loop forever waiting for key presses. Update the output on every key
* press and every 1.0s (when ppoll() times out). */
do
{
fds[0].revents = 0;
ret = ppoll(fds, sizeof(fds) / sizeof(struct pollfd), &timeout, &sigmask);
if (fds[0].revents & POLLIN)
{
ret = read(STDIN_FILENO, &line[count], sizeof(line) - count);
if (ret > 0)
{
line[count + ret] = '\0';
if (strcmp(&line[count], "\033[A") == 0)
{
snprintf(frame.data, frame.x, "up");
count = 0;
}
else if (strcmp(&line[count], "\033[B") == 0)
{
snprintf(frame.data, frame.x, "down");
count = 0;
}
else if (line[count] == 127) // backspace
{
if (count != 0) { count -= ret;}
}
else if (line[count] == '\n')
{
snprintf(frame.data, frame.x, "entered: %s", line);
count = 0;
}
else
{
count += ret;
}
}
}
/* Print the current time to the output buffer. */
current_time = time(NULL);
tp = localtime(¤t_time);
strftime(&frame.data[1 * frame.x], frame.x, "%Y/%m/%d %H:%M:%S", tp);
/* Print the command line. */
line[count] = '\0';
snprintf(&frame.data[(frame.y - 1) * frame.x], frame.x, "$ %s", line);
draw_frame(&frame);
}
while (1);
/* Restore terminal and free resources. */
tcsetattr(STDIN_FILENO, TCSANOW, &tty_old);
free(frame.data);
return (0);
}
If your input buffer is defined to be 64 characters, then I would recommend using a char array instead of a char*. Something like char input_buffer[65]; should serve your purposes (add an extra character for the trailing '\0').
As far as command history goes, you can use a two-dimensional array for that. Something like char command_history[20][65]; should let you store 20 old commands of 64 characters each.
Allocating these buffers statically should make things a bit easier for you, as you won't have to worry about malloc and friends.
It's hard to give you too much specific advice without seeing your code. I have a feeling that you are making the same type of mistakes that are typical to people first learning C. Can you post the part of your code that is giving you problems so that we can learn more about what you are doing?
Update after posted provided code:
One problem I'm seeing is that the function takeInput doesn't have a return statement. When you use input = takeInput(); inside your main function, the value of input isn't being set to what you think it is. It's probably not a valid pointer, which is causing your line that says input[j] to segfault.
Your usage of cmdHistory also needs revisiting. You allocate it with cmdHistory = (char**)calloc(21,sizeof(int));, which gives you enough space to store 21 integers. In the function printHistory, you pass elements of cmdHistory to printw as if they were strings (they're only integers). This is most definitely not doing what you want it to do. Instead, your allocation logic for cmdHistory needs to look more like your de-allocation logic (except backwards). Allocate an array of char**, then iterate through the array, assigning each pointer to a newly-allocated buffer. Just like you have one free statement for each element in the array plus a free for the array as a whole, you should have one malloc for each element plus one malloc for the array as a whole.
Even if you can't use a statically-allocated stack, try writing your program using one anyway. This will let you work the kinks out of your key detection logic, etc without having to worry about the dynamic memory part of the program. Once the rest of it is working, go back in and swap out the static memory for dynamic memory allocation. That way, you're only having to debug a little bit at a time.
Have you looked at the Readline library? It's ideal for use in your project.
http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html