raynstard
起動オプションの解析
(Nested
Flatten)
えーと。何人かの方から指摘されていますが
-sは-dの間違いです。
また、-dのオプションは省略可能なオプションでした。
ということで書式を訂正すると
書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]
です。
それと起動例も
1. cmdopt -o AAA
2. cmdopt -o AAA BBB CCC
3. cmdopt -oq AAA
4. cmdopt -o -q AAA
5. cmdopt -o -d1 AAA
6. cmdopt -o -d 1 AAA
7. cmdopt -q -d2 -o AAA
となります。
フォロー遅くなってしまって申し訳ないです。
期末恒例のお祭りが発生しちゃって^^;;
指摘ありがとうございました。
sh版作っていて-oオプションのチェックが抜けていたことに気づくorz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | --- doukaku205.c 2008-09-10 22:23:39.953125000 +0900
+++ doukaku205.c.new 2008-09-10 22:43:58.656250000 +0900
@@ -61,6 +61,14 @@
info.argv0 = argv[0];
info.argv = &argv[optind];
info.num = argc - optind;
+
+ /* 必須チェック */
+ if( info.output != true )
+ {
+ printf("必須オプションがたりない\n");
+ printf("書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]\n");
+ return 1;
+ }
if( info.num < 1 )
{
printf("文字列がない\n");
|
もう一つPOSIX-shのものを投稿 evalって便利ですよね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #!/usr/bin/sh
OPT_o='OFF'
OPT_q='OFF'
OPT_d='0'
OPTERR=0
while getopts ":oqd:" name
do
case $name in
[oq])
eval "OPT_$name='ON'"
;;
d)
OPT_d=$OPTARG
echo "$OPTARG" | grep -e '[012]' >/dev/null 2>&1
if [ $? -ne 0 ] ; then
echo '変な値: ' "[$OPT_d]"
echo '書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]'
exit 1
fi
;;
[:?])
echo '変なオプション: ' "[$name]"
echo '書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]'
exit 1
;;
esac
done
shift $(($OPTIND-1))
if [ $# -eq 0 ]; then
echo '文字列がない'
echo '書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]'
exit 1
fi
if [ $OPT_o = "OFF" ]; then
echo '-oがない'
echo '書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]'
exit 1
fi
echo '[オプション情報]'
echo 'o(output):' "$OPT_o"
echo 'q(quote):' "$OPT_q"
echo 'd(debug):' "$OPT_d"
echo ''
echo '[パラメータ情報]'
echo '指定数:' "$(($#-1))"
C=0
while [ $C -lt $# ];
do
let C=C+1
echo "$C:$1"
shift
done
#EOF
|
とりあえず getopt()を利用したものです。 コンパイラによってはgetopt()が unistd.hにはいっているかもしれません。 僕はいつも起動情報を保持する構造体を作って保持しています。 has~()という関数作ってしまえばあんまり関係ないですけど。。 // gcc -Wall -std=c99 doukaku205.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <getopt.h>
#define OPTION_OUTPUT 'o'
#define OPTION_QUOTE 'q'
#define OPTION_DEBUG 'd'
static char options[] = { ':',
OPTION_OUTPUT
, OPTION_QUOTE
, OPTION_DEBUG, ':'
, '\0' };
struct tagParamInfo
{
bool output;
bool quote;
int debug;
int num;
char *argv0;
char **argv;
} info = { false, false, 0, 0, NULL, NULL};
int main(int argc, char *argv[])
{
int opt;
/* デフォル値 設定 */
/* オプション解析 */
opterr = 0;
while( (opt = getopt(argc, argv, options)) != EOF )
{
switch( opt )
{
case OPTION_OUTPUT:
info.output = true;
break;
case OPTION_QUOTE:
info.quote = true;
break;
case OPTION_DEBUG:
info.debug = strtol(optarg, NULL,10);
if( 0 <= info.debug && info.debug <= 2 )
{
break;
}
case '?':
case ':':
default:
printf("変なオプション[%c]\n", opt);
printf("書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]\n");
return 1;
}
}
/* パラメータ設定 */
info.argv0 = argv[0];
info.argv = &argv[optind];
info.num = argc - optind;
if( info.num < 1 )
{
printf("文字列がない\n");
printf("書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]\n");
return 1;
}
/* 解析結果の出力 */
printf("[オプション情報]\n");
printf("%-10s:%3s\n", "o(output)", ((info.output==true)?"ON":"OFF"));
printf("%-10s:%3s\n", "q(quote)", ((info.quote==true)?"ON":"OFF"));
printf("%-10s:%3d\n", "d(debug)", info.debug);
printf("\n");
printf("[パラメータ情報]\n");
printf("%-10s:%3d\n", "指定数", info.num);
for( int n=0; n<info.num; n++)
{
printf("%2d:%s\n", n, info.argv[n]);
}
return 0;
}
|
文字列型日時ののN秒後時間取得
(Nested
Flatten)
あれ?バージョン同じだぞ?とおもって再度やってみたら動きました。 秒の指定を間違えていたみたいです。 失礼しました。
Perlにまでパーサっがあったのですね。。。 僕が妥協した時はPOSIXを使ったべた書きでした。 # ほとんどCとかわりません(笑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/env perl
use strict;
use POSIX qw/strftime mktime/;
sub DateEx($$)
{
my $outDate = '';
my @t = ($_[0] =~ m/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/);
$t[0] -= 1900; $t[1] -= 1; @t = reverse @t;
$t[0] += $_[1];
mktime( @t );
return strftime("%Y%m%d%H%M%S", @t);
}
print DateEx("20080827235925",40) . "\n";
__END__
#EOF
|
てもとのdateコマンドでは動きませんでした。 バージョンていくつでしょう? $ date --version date (GNU coreutils) 5.96 Copyright (C) 2006 Free Software Foundation, Inc. This is free software. You may redistribute copies of it under the terms of the GNU General Public License <http://www.gnu.org/licenses/gpl.html>. There is NO WARRANTY, to the extent permitted by law. Written by David MacKenzie.
ども、raynstardです。 うーん、どっちにになるのでしょう?(笑 このお題の目的は、文字列という日付とは関係ない入力データで 日付の計算をすることです。 そもそもの発端は、シェルで自分自身を 再スケジュールしようとしたらシェルじゃできねぇってことで 計算部分をperlの呼び出しで妥協してしまったことです。 最近の言語には、大抵パーサがあるのですね。 盲点でしたorz
最近は普通にパーサがある時代になったのですね。 ごめんなさい盲点でした^^;; ということで、「仕様.3」については、 入力の書式は限定しないこととし、出力の書式を限定するようにしてください。
LL Golf Hole 8 - 横向きのピラミッドを作る
(Nested
Flatten)
ネストしない形を投下~
sin()でいけるかと思ったら単位が小さすぎて形にならなかったので絶対値を利用しました。
ちなみに、「abs(n-i)」を「abs(n-(i%lines))」とすると
lines はどこまでも増やせます(笑
# 波打ちます
n==4固定で76B
一般化(n<17)すると99Bくらい
n;i;main(){char o[16];scanf("%d",&n);memset(o,'*',n);while(++i<n*2)printf("%.*s\n",n-abs(n-i),o);}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *o = "****";
int n=4,i=1;
int lines = n * 2;
while( i<lines )
{
printf("%.*s\n",n-abs(n-i),o);
i++;
}
return 0;
}
|
LL Golf Hole 7 - バイト数を読みやすくする
(Nested
Flatten)
後続の#7358 では問題無くなっていますが 僕のロジックでは%cを利用してはいけません。 %cはバイナリ出力に使いので出力結果をバイナリで確認してみるとわかります。 echo '100' ./a.out | od -x あとちなみに、こう。氏のロジックだと iをデータセグメントに持って行ってデフォルトの型に期待しちゃうことで僕よりも短くなります。 といっても98Bなので似たようなものですけど。 文字列と扱うためのキャストが;; # たぶん、C99です。
1 | i;main(){float d;for(scanf("%f",&d);d>1023;i++)d/=1024;printf("%.1f%.1sB\n",d,&("\0kMGTPE"[i]));}
|
よく考えてみたらどうせ1024でわってしまう上に小数第一位までしか表示しないので
倍精度で値を保持する必要ありませんでしたね。
指数にしてしまうので単精度で十分と思われ。
祝☆99B
多少お題と違うみたいですけど、とりあえず満足です(ぁ
ちなみに、内部が指数表記なので
30桁とかとんでもない桁数でも動きますが
もちろんオーババッファフローします^^;
main(){char*t="\0kMGTPE";float d;for(scanf("%f",&d);d>1023;t++)d/=1024;printf("%.1f%.1sB\n",d,t);}
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h>
int main(int argc, char *argc[])
{
char*t="\0kMGTPE";
float d;
for(scanf("%f",&d);d>1023;t++)
{
d/=1024;
}
printf("%.1f%.1sB\n",d,t);
return 0;
}
|
1ってなんだorz
scanf("%1lf",&d);
↓
scanf("%lf",&d);
申し訳ないです。気をつけます。。。
まいど、raynstardです。
単位を文字列として出力してしまえば100バイトまでは減らせそうなのだけど
その先にある壁が越えられないorz
// gcc doukaku202.c
ちなみに、コードをそのまま短くすると↓の通り(104B)
main(){char*t="\0kMGTPE";double d;scanf("%1lf",&d);for(;d>1023;t++){d/=1024;}printf("%.1lf%.1sB\n",d,t);}
1 2 3 4 5 6 7 8 9 10 11 12 | int main(int argc, char *argv[])
{
char*t="\0kMGTPE??";
double d;
scanf("%1lf",&d);
for(;d>1023;t++)
{
d/=1024;
}
printf("%.1lf%.1sB\n",d,t);
return 0;
}
|
LL Golf Hole 5 - 最上位の桁を数え上げる
(Nested
Flatten)
修正みすってるorz
char s[9]={0x30},*t=s;
↓
char s[9]={0x31},*t=s;
C++に対抗意識を燃やしてみたけどかてなかったorz
うーん、atoi()をstrcmp()にすればもう少し短くなる気がするんだけどうまく動かない。。
strcmp()って短い文字列は小さいと判断されると思ったのだけど気のせいかなー?
// gcc -Wall doukaku200.c
ちなみに圧縮すると↓のような感じ(113バイト?)
char s[9]={48},*t=s;
main(int ac, char* av[]){for(;atoi(s)<atoi(av[1]);(*s)++)
{puts(s);if(*s==59)*s=*(++t)=48;}}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <stdio.h>
#include <stdlib.h>
char s[9]={0x30},*t=s;
int main(int ac, char* av[])
{
for(;atoi(s)<=atoi(av[1]);(*s)++)
{
puts(s);
if(*s==0x39)
{
t++;
*s = *t = 0x30;
}
}
return 0;
}
/* EOF */
|
tailの実装
(Nested
Flatten)
たしかにお題を出す人にも、もうすこし丁寧に出題してほしい感じがしますね。 たぶんですが、 意訳すると以下のような感じになるのではないでしょうか? 1. 指定されたファイルの最後尾から N行表示すること 2. ファイルの更新を監視して、指定のファイルが更新された場合に、 更新分のうち、最後尾からN行を表示すること 「2.」更新分なので前回表示続きからという点が注意事項だと思います。 # 「-f」 を実装しなさいというあたり、 以前あったファイルの更新を監視するお題の 派生と考えられるのかな?
LL Golf Hole 3 - 13日の金曜日を数え上げる
(Nested
Flatten)
Cだとmktime(3C)を使うと便利です。 まぁ、ほんとにmktime()が本領発揮するのは日時へ変換したときなのですけど^^;; // gcc -Wall -std=c99 doukaku197.c -o doukaku197
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <stdio.h>
#include <time.h>
static const char *weekdayname[] = {"Sun","Mon","Tue","Wed","Thi","Fri","Sat"};
int main(int argc, char *argv[])
{
static const int YEAR_END = (2013 - 1900) + 1;
struct tm t = {0};
time_t now = 0;
int count = 0;
now = time(NULL);
localtime_r(&now, &t);
t.tm_mday = 13; // 13日固定
/* 2014年までの13日の金曜日を検索する */
count = 0;
while( t.tm_year < YEAR_END )
{
// 13日の金曜日を探す
if( t.tm_wday == 5 )
{
// 13日の金曜日なら表示してカウントアップ
printf("%d/%02d/%02d (%s)\n"
, t.tm_year+1900, t.tm_mon+1, t.tm_mday
, weekdayname[ t.tm_wday ]);
count ++;
}
t.tm_mon ++;
mktime( &t ); // 日時の再計算(正規化)
}
printf("COUNT:[%d]\n", count);
return 0;
}
/* EOF */
|
環境変数の取得
(Nested
Flatten)
next >>
ども、raynstardです。 環境には依存しないと思いますが、 入力データを壊してしまうので基本的に直接strtok()は、 まずいいんじゃないでしょうか? # forkとかexec*したときとか このコードなら問題ないからやっているだけかもしれませんが。。。 ちょっと気になりました。



raynstard
#7991()
[
C
]
Rating0/0=0.00
Rating0/0=0.00-0+
[ reply ]