人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

【はてな五番勝負!】キーワード:C言語なら、オレに聞け!

おれは32才、10年間プログラムを一生懸命作ってきた。
C言語しか知らないがC言語なら誰にも負けない...
・キーワードに関連して、なんでも質問してくれ。
・あなたの質問に全力で答えるが、C-FAQ載ってる質問をすると全力で煽るかも知れない。
・回答に納得したらスターを付けろ。

この質問はhttp://q.hatena.ne.jp/1202314128への応募だ。

1202355906
●拡大する

●質問者: dev_zer0
●カテゴリ:コンピュータ ネタ・ジョーク
✍キーワード:C言語 FAQ あなた はてな五番勝負! キーワード
○ 状態 :終了
└ 回答数 : 6/6件

▽最新の回答へ

1 ● BLOG15
●20ポイント

プログラミングのことは全く何も知らない素人です。C言語には、C++というのとC♯という言語もあると思います。

wikipediaの説明を見てみましたが、専門用語だらけでこれらの違いが全くわかりません。この3つの言語の違いを素人にもわかるように、専門用語を使わずやさしく私に教えて下さい。

◎質問者からの返答

あなたは日本語という自然言語で質問されていますが、

日本語しか話せない人に英語やフランス語の違いを分かりやすく説明できると思いますか?

多分、日本語しか知らない質問された人間は、適当なことを言うか、

自分の中の語彙を総動員して煙に巻くに違いありません。


ハッキリ言ってしまいますが、3歳程度の子供に対して日本語と英語の文法や単語の違いを

専門用語を使わずに子供に理解させようとする行為をあなたは私に要求しています。

もし、あなたが気軽に行ったその質問の答えが知りたいのならば

C、C++、C#のプログラム言語を知って、理解してください。

そうすれば自ずと答えは導き出されます。


私は(設定上)Cしか知りませんが、Cの良書としてプログラミング言語C(通称K&R)

をお勧めします。まず、これを読んでCを知るという努力をしてください。


以上


2 ● miharaseihyou
●35ポイント

それでは、C言語の「性別」を二択で答えていただきましょう。

男らしいですか? それとも女っぽいでしょうか?

男性向き or 女性向き ?

50文字以下でお答えください。

◎質問者からの返答

私は男であり、Cは女、そしてプログラミングの結果できたプログラムは私の子供ですが何か?

(43文字)


3 ● ffmpeg
●10ポイント

プログラミングはソフトを作ってなんぼのもん。クイズごっこなんていうてる時点でクズ


http://www

◎質問者からの返答

オマエモナー

# 煽りたいだけならコメントで好きなだけやってくれ


4 ● pyopyopyo
●100ポイント ベストアンサー

以下のコードを解読して,解説してください.

long h[4];t(){h[3]-=h[3]/3000;setitimer(0,h,0);}c,d,l,v[]={(int)t,0,2},w,s,I,K
=0,i=276,j,k,q[276],Q[276],*n=q,*m,x=17,f[]={7,-13,-12,1,8,-11,-12,-1,9,-1,1,
12,3,-13,-12,-1,12,-1,11,1,15,-1,13,1,18,-1,1,2,0,-12,-1,11,1,-12,1,13,10,-12,
1,12,11,-12,-1,1,2,-12,-1,12,13,-12,12,13,14,-11,-1,1,4,-13,-12,12,16,-11,-12,
12,17,-13,1,-1,5,-12,12,11,6,-12,12,24};u(){for(i=11;++i<264;)if((k=q[i])-Q[i]
){Q[i]=k;if(i-++I||i%12<1)printf("\033[%d;%dH",(I=i)/12,i%12*2+28);printf(
"\033[%dm "+(K-k?0:5),k);K=k;}Q[263]=c=getchar();}G(b){for(i=4;i--;)if(q[i?b+
n[i]:b])return 0;return 1;}g(b){for(i=4;i--;q[i?x+n[i]:x]=b);}main(C,V,a)char*
*V,*a;{h[3]=1000000/(l=C>1?atoi(V[1]):2);for(a=C>2?V[2]:"jkl pq";i;i--)*n++=i<
25||i%12<2?7:0;srand(getpid());system("stty cbreak -echo stop u");sigvec(14,v,
0);t();puts("\033[H\033[J");for(n=f+rand()%7*4;;g(7),u(),g(0)){if(c<0){if(G(x+
12))x+=12;else{g(7);++w;for(j=0;j<252;j=12*(j/12+1))for(;q[++j];)if(j%12==10){
for(;j%12;q[j--]=0);u();for(;--j;q[j+12]=q[j]);u();}n=f+rand()%7*4;G(x=17)||(c
=a[5]);}}if(c==*a)G(--x)||++x;if(c==a[1])n=f+4**(m=n),G(x)||(n=m);if(c==a[2])G
(++x)||--x;if(c==a[3])for(;G(x+12);++w)x+=12;if(c==a[4]||c==a[5]){s=sigblock(
8192);printf("\033[H\033[J\033[0m%d\n",w);if(c==a[5])break;for(j=264;j--;Q[j]=
0);while(getchar()-a[4]);puts("\033[H\033[J\033[7m");sigsetmask(s);}}d=popen(
"stty -cbreak echo stop \023;sort -mnr -o HI - HI;cat HI","w");fprintf(d,
"%4d from level %1d by %s\n",w,l,getlogin());pclose(d);}
◎質問者からの返答

何かのゲームらしいことは理解できたが、それ以外は分からん

適当なコメントは入れてみたが意味が分からん

/**
 * 変数h[4]の本来の構造
 * struct itimerval {
 * struct timeval {
 *long tv_sec;
 *long tv_usec;
 *} interval;
 *struct timeval {
 *long tv_sec;
 *long tv_usec;
 *} timeval;
 *};
 */
long h[4];

/**
 * タイマ設定
 */
int t(void) {
// h[3]とはtimeval.tv_secである
h[3] -= h[3] / 3000;
setitimer (0, h, 0);
}

int c;// getchar()の結果とa[0]?a[5]が入ることがある
int d;// FILE * だろうが!popen()の戻りは!
int l;// レベル、これが高いと、割り込む間隔が短くなる

/**
 * 変数v[]の本来の構造
 * struct sigvec {
 *void (*sv_handler)();
 *int sv_mask;
 *intsv_flags;
 * };
 */
int v[] = {
(int)t,
0,
2
};

int w;// 得点じゃね?ひたすらインクリメントされてるだけ
int s;// シグナルのブロック、解除用
int I;// 良くわからない、iと関係ありそう
int K= 0;// 良くわからない、kと関係ありそう
int i = 276;// カウンタ、色々な箇所で使われている
int j;// カウンタその2、12の倍数でトリッキーな挙動をする
int k;// 何かの判定で使われているらしい
int q[276];// ここが肝
int Q[276];// ここが肝
int *n = q;// このnの使われ方が一番の謎
int *m;// まぁ、mもnと同じぐらい謎だけどさ
int x = 17;// これは17に初期化しとかないとマズイらしい

/**
 * 怪しいテーブル
 * 使っている箇所
 * n = f + rand () % 7 * 4
 * n = f + 4 ** (m = n), G (x) || (n = m);
 * とにかく、nの挙動に注意
 */
int f[] =
{
7, -13, -12, 1, 8, -11, -12, -1, 9, -1, 1, 12, 3, -13, -12, -1, 12, -1, 11,
1, 15, -1, 13, 1, 18, -1, 1, 2, 0, -12, -1, 11, 1, -12, 1, 13, 10, -12,
1, 12, 11, -12, -1, 1, 2, -12, -1, 12, 13, -12, 12, 13, 14, -11, -1, 1,
4, -13, -12, 12, 16, -11, -12, 12, 17, -13, 1, -1, 5, -12, 12, 11, 6,
-12, 12, 24
};

/**
 * 何かをprintfしたいらしい
 * in :q
 * out:Q, I
 * 多分、ローカル変数でも良いもの
 * i, k
 */
int u(void)
{
// 11以降から最後までQを舐める
for (i = 11; ++i < 264;) {
// q[i] - Q[i]が\0以外の場合
if ((k = q[i]) - Q[i]) {
Q[i] = k;// Q[i] = q[i]
// 12って何?後回し
if (i - ++I || i % 12 < 1)
printf("\033[%d;%dH", (I = i) / 12, i % 12 * 2 + 28);
printf("\033[%dm " + (K - k ? 0 : 5), k);
K = k;
 }
}
// Qの最後(\0除く)に文字保存
Q[263] = c = getchar();
}

/**
 * 何かを見つけて、
 * 見つかったら0, 見つからなかったら1を返す
 * in :n, q
 * out:なし
 * 多分、ローカル変数でも良いもの
 * i
 */
int G(int b)
{
// 4回繰り返し
for (i = 4; i--;) {
// 何かを見つけている
//i != 0の場合、q[b + n[i]]が0以外なら0を返す
//i == 0の場合、q[b]が0以外なら0を返す
if (q[i ? b + n[i] : b])
return 0;
}
// 見つからなかったら1を返す
return 1;
}

/**
 * bをqのどこかに代入
 * in :n, q
 * out:q
 * 多分、ローカル変数でも良いもの
 * i
 */
int g(int b)
{
// 4回繰り返し
// i == 0 の場合、q[x] = b(ループ最後だけ、特殊)
// i != 0 の場合、q[x + n[i]] = b
for (i = 4; i--; q[i ? x + n[i] : x] = b)
;
}

/**
 * main、*aは環境変数だったっけ?
 */
//main (C, V, a)
// char **V, *a;
int main(int C, char **V, char *a)
{
// タイマの設定、引数が無い場合デフォルト値2
// 引数が存在する場合、その値にする
// なお、数値以外が設定されると0割しないか?
h[3] = 1000000 / (l = C > 1 ? atoi (V[1]) : 2);
// キーバインドの設定、デフォルトでは
// a[0] = 'j', a[1] = 'k', a[2] = 'l', a[3] = ' ',
// a[4] = 'p', a[5] = 'q'
for (a = C > 2 ? V[2] : "jkl pq"; i; i--)
*n++ = i < 25 || i % 12 < 2 ? 7 : 0;
srand(getpid());
system("stty cbreak -echo stop u");
// SIGBUSをトラップし、t()を再度実行させる
sigvec(14, v, 0);
t();
puts("\033[H\033[J");

// 無限ループし、g(7), u(), g(0)を呼び続ける
// よく分からない用途であるnの初期化
for (n = f + rand () % 7 * 4;; g(7), u(), g(0)) {
if (c < 0)
{
// また12が出てきた、12って何だ?
if (G(x + 12)) {
x += 12;
} else {
g(7);
++w;
// j = 12 * (j / 12 + 1)ではjは12の倍数を取る
for (j = 0; j < 252; j = 12 * (j / 12 + 1)) {
// whileで良くね?
for (; q[++j];) {
if (j % 12 == 10) {
for (; j % 12; q[j--] = 0)
;
u();
for (; --j; q[j + 12] = q[j])
;
u ();
}
// nの再初期化
n = f + rand () % 7 * 4;
// xを17に初期化(), cには何を代入している?
G (x = 17) || (c = a[5]);
}
}
}
}
// jがキー入力された場合
if (c == *a)
// Gが0を返すと、++xは実行しない
G(--x) || ++x;
// kがキー入力された場合
if (c == a[1])
// n = f[4 * *n]? わけ分からん
n = f + 4 * *(m = n), G (x) || (n = m);
// lがキー入力された場合
if (c == a[2])
G(++x) || --x;
// スペースがキー入力された場合
if (c == a[3])
for (; G(x + 12); ++w)
x += 12;
// p, qがキー入力された場合
if (c == a[4] || c == a[5]) {
// この最中はシグナル割り込みされると困るらしい
s = sigblock(8192);
printf ("\033[H\033[J\033[0m%d\n", w);
// qなら終了
if (c == a[5])
break;
// Qの初期化。memset使えよ!
for (j = 264; j--; Q[j] = 0)
;
// pが押されるまでループ
while (getchar() - a[4])
;
puts ("\033[H\033[J\033[7m");
// シグナル割り込み解除
sigsetmask(s);
}
}
// HIというファイルを操作しているらしい(多分、ハイスコアと言う意味)
d = popen("stty -cbreak echo stop \023;sort -mnr -o HI - HI;cat HI", "w");
// もしかして、得点、レベル、名前を表示してるのか?
fprintf(d, "%4d from level %1d by %s\n", w, l, getlogin());
pclose(d);
}

5 ● shirasaki
●30ポイント

真面目に知りたいことを質問します。複数の質問が不可であるならば、どれか1つ選んで回答お願いします。

1.while()ではなく、do while()を使ったほうがよいと思われるケースを理由とともに教えてください。

できれば、2つ以上お願いします。

2.C99には可変配列があるようですが、これについてどう思われますか。

私は使えないと思うのですが、もし使えると考えるならば、どういったケースで使いますか。

3.どういったプログラムをCで組むべきでしょうか。逆に、どういったプログラムをCで組んではいけないと考えますか。

他言語との比較ではなく、Cのみで語ってください。

◎質問者からの返答

1.do while()を使ったほうがよいと思われるケース

基本は1回以上処理を行うときにdo-while, 0回以上の場合はwhileを使えばいいんじゃね?

思いつく例としては

例1:コンソールからの入力の妥当性チェック

#include <stdio.h>
int main(void)
{
char buf[256];
int i = 0;
do {
printf("input>");
fgets(buf, sizeof buf, stdin);
i = atoi(buf);
} while(i <= 0);
printf("i = %d\n", i);
return 0;
}

例2:コーディング規約でgotoが禁止されてしまった場合のエラー処理

#include <stdio.h>

/* ファイルコピー */
int main(int argc, char **argv)
{
FILE *src = NULL;
FILE *dst = NULL;
int c = 0;
/* パラメータチェックは本論ではないので省略 */
do {
src = fopen(argv[1], "rb");
if (src == NULL)
break;
dst = fopen(argv[2], "wb");
if (dst == NULL)
break;
do {
if ((c = fgetc(src)) == EOF)
break;
if ((c = fputc(c, dst)) == EOF)
break;
} while (c != EOF);
if(ferror(dst) || ferror(src))
fprintf(stderr, "エラーが発生\n");
} while (0);
/* OPENしてたらCLOSE */
if(dst != NULL) fclose(dst);
if(src != NULL) fclose(src);
return 0;
}

例3:マクロ内で変数を使いたいとき

#define swap(type, a, b) \
 do { type tmp; tmp = a; b = a; a = tmp; } while[0]


2.可変長配列の私見

可変長配列なんて中でallocaが呼ばれてるだけでしょ?

http://www.linux.or.jp/JM/html/LDP_man-pages/man3/alloca.3.html

gcc拡張でよく使われているし、allocaが規格として認められたと思えばいいと思う。

# 個人的にC99規格は好きではないけれど...

使うケースとしては例えばコード変換とかで

int conv(const char *src, size_t siz, char *dst)
{
char tmp[siz];

とできると便利だとは思う。


3-a.Cで組むべきプログラムとは

移植性と速度を両立させたい場合、2008年現在ではC以外の選択肢は少ない

よって、移植性と速度を両立させなければならないプログラム、ライブラリを

作らなければならなくなった場合、Cかbetter CなC++にならざる得ないだろう


3-b.Cで組んではいけないプログラムとは

Cで組んではいけないプログラムなどこの世界には存在しない。好きにしろ

ただ、文字列処理はCでは面倒だし、バグの温床になるのでCで組むのは止めておけとは忠告する。

初心者が良く扱うscanf()はバッファ溢れをさせないためにはえらい注意が必要だし、

strtok()はスレッドセーフでないし、gets()はC89,C99では非推奨だ。

# C99ではgets()は非推奨とかいう生ぬるい措置ではなく、ライブラリから外せと問い詰めたい



最後に「あえて」他言語と比較しよう

Cはレジスタを意識させること無く、アセンブラ並みの性能を引き出したことに成功した言語だ

# register宣言は?という突っ込みは却下する

そして、最近の言語はメモリ管理を意識することなくプログラミングができることを可能にしている

プログラマは低級な資源の管理に気を取られること無く、問題の本質に集中することができる

これは、わたしも歓迎する

Cはプログラマは間違ったことをしないという誤った前提の上に確立された言語である

誤った設計の言語だが、我々は残念ながら「まだ」それを手放せない


1-5件表示/6件
4.前の5件|次5件6.
関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ