コンソール用ストップウォッチ

たまにはCプログラムでも。ただのストップウォッチには興味ありませんですか、そうですか。

% gcc -Os -o stopwatch stopwatch.c
% stopwatch 5
/ 0:00:03.9 

↑くるくる回る。
sleepコマンドの代わりにすると、待ち時間がわかって良いかも? でもそれだけ。
なお引数なしだとカウントアップします。


ソースは以下。# 工夫も何もないが…
cygwin, Linux, Mac OS XBSDなどで動く気がします。

/* stopwatch.c */
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

//#define USE_SELECT
struct timeval m;
char rc[] = "|/-\\";

#ifdef USE_SELECT
int usleep(unsigned long u)
{
	struct timeval w = {0,u};
	int ret = select(0,0,0,0,&w);
	if (ret < 0)
		perror("select");
	return ret;
}
#endif

int display(struct timeval *v, int s)
{
	printf("%c%3d:%02d:%02d.%01d \r", rc[v->tv_usec/(1000000/s)%4], 
		v->tv_sec/3600, v->tv_sec/60%60, v->tv_sec%60, v->tv_usec/100000);
	fflush(stdout);
}

int countup()
{
	struct timeval v;
	gettimeofday(&v, NULL);
	timersub(&v, &m, &v);
	display(&v, 4);
	printf("\t\t\t\t%7d\r", 100000 - v.tv_usec%100000);
	return 100000 - v.tv_usec%100000;
}

int sw()
{
	struct timeval v;
	gettimeofday(&v, NULL);
	timersub(&m, &v, &v);
	if (v.tv_sec < 0 || v.tv_sec == 0 && v.tv_usec < 10000)
		return -1;
	display(&v, 8);
	printf("\t\t\t\t%7d\r", v.tv_usec%100000);
	return v.tv_usec%100000;
}

int main(int argc, char** argv)
{
	int w;
	gettimeofday(&m, NULL);
	if (argc > 1) {
		m.tv_sec += atoi(argv[1]);
		while ((w = sw()) >= 0)
			usleep(w);
	} else
		while (1)
			usleep(countup());
	printf("\n");
	return 0;
}

usleepなんて関数ない!って怒られる人は #define USE_SELECT すると、selectシステムコールをusleepの代わりとして使います。誤差蓄積防止用に差分値の0.1秒以下の桁を渡しています。
ちなみにtimersub関数BSD由来のマクロで、POSIXにはありません。最近のLinux(というかglibc)では#define _BSD_SOURCE しないと使えなくなっています。