C言語なら俺に聞け 148

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん (アウアウカー Sacf-slpW)
垢版 |
2018/09/19(水) 17:56:50.83ID:XSTNMnDwa
C言語の話題のみ取り扱います C++の話題はC++スレへ
質問には最低限の情報(ソース/コンパイラ/OS)を付ける
数行で収まらないソースは以下を適当に使ってURLを晒す
https://paiza.io/
https://ideone.com/
http://codepad.org/

C11
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf

C99
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
http://kikakurui.com/x3/X3010-2003-01.html

C FAQ 日本語訳
http://www.kouno.jp/home/c_faq/

JPCERT C コーディングスタンダード
https://www.jpcert.or.jp/sc-rules/

※前スレ
C言語なら俺に聞け 147
http://mevius.5ch.net/test/read.cgi/tech/1534430162/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:----: EXT was configured
2018/09/19(水) 18:46:51.43ID:5wa+YDhW0
JPCERTに書いてある
> DCL12-C. 抽象データ型は opaque な型を使って実装する
これ、言葉遣いが JIS に準拠してないね
- opaque な型
+ 不完全型
2018/09/19(水) 18:51:06.87ID:SdGhFMnDa
おぱきゅー
2018/09/19(水) 18:52:22.93ID:sSjeJI6sd
おぺいきゅー
2018/09/19(水) 20:53:36.31ID:6LbAKjXm0
あのね opaque を「おぱきゅー」と読むとね、
中がどうなっているか見えないって感じがヒシヒシ伝わるんだよ。
6デフォルトの名無しさん (アウアウカー Saeb-slpW)
垢版 |
2018/09/19(水) 21:01:51.92ID:zcXFtBV7a
opaque音頭
2018/09/19(水) 21:10:39.04ID:kKUGVzPQ0
ドラハッパー?
2018/09/19(水) 21:40:07.01ID:aiIpKBDGM
>>5
寧ろ向こう側が透けて見えて意味を取り違えそうな…
9デフォルトの名無しさん (アウアウカー Saeb-slpW)
垢版 |
2018/09/19(水) 21:46:14.52ID:zcXFtBV7a
透けるトン
10デフォルトの名無しさん (ワッチョイ 9780-9b2l)
垢版 |
2018/09/19(水) 22:44:21.77ID:xLP4ypV20
おおきいおっぱいを占領する
11デフォルトの名無しさん (アウアウカー Sae9-kke4)
垢版 |
2018/09/20(木) 12:33:56.62ID:irJ5n1n9a
おっぱいがキューイングされてる状態だろ
12デフォルトの名無しさん (アウアウカー Sae9-rLjT)
垢版 |
2018/09/20(木) 12:46:40.86ID:rEtRtbV+a
キューは口を尖らせて発音
2018/09/20(木) 13:32:01.11ID:6Uvn6M6wH
俺氏、マジレスするタイミングを完全に失う
2018/09/20(木) 14:06:56.92ID:4xeYkQf2a
不可視を不完全と呼ぶのはちょっと良くないと思うわ
まあ視点が違うんだけども
2018/09/20(木) 15:50:43.96ID:kJMlDz7M0
ピンプル的な意味で「見えない」なら合ってんじゃん
2018/09/20(木) 19:19:48.48ID:fVTsYrUH0
みんなmusl libcとか使ってたりする?
プロジェクトの内容だけみると けっこう良さげなんだけど
あまり日本語の情報を聞かないし 実際はglibcとかが大半なのかな。
2018/09/21(金) 11:19:07.18ID:7KdLYb7A0
CはGNUが9割
2018/09/21(金) 17:35:46.83ID:r4ObfaEn0
c言語本格入門のリスト構造(単方向リスト)が理解できず困っています。
書籍には図を書けば理解できるとあり、ソースにprintf関数をところどころに入れて、ポインタの動きを追いかけていたのですが、余計こんがらがってしまいます。
他のサイトや他者の質問が掲載された掲示板なども参考にしましたが、さっぱりわかりません。
図を描いても理解には繋がりません。
プログラムは250行くらいあり、掲載出来る様なサイトがあれば誘導お願いします。

ポインタの*ptr_now、*ptr_before、*ptr_new の動きと役割が理解できれば、前に進めると思うのですが、知恵を貸して下さい。
2018/09/21(金) 17:44:45.17ID:TewjjbP30
>>18
サイトは>>1にあるのを使えばいいよ
2018/09/21(金) 17:46:57.36ID:DzWt0PfVa
nowが今いる所でbeforeがさっきいた所でnewが新たに作る所?
2018/09/21(金) 18:05:52.26ID:r4ObfaEn0
>>18
now と before は作業用領域で、newは名前とかを格納しています。
2018/09/21(金) 18:39:31.34ID:FeY49FdEM
>>18
とある位置に新しいデータを挿入するサンプルコードなんじゃないか?

newが新たに挿入しようとするデータのアドレス、
nowが挿入先の直後のデータのアドレス、
beforeが挿入先の直前のデータのアドレス。
(単方向リストへのデータ挿入は新しいデータを挿入する位置の前後のデータのアドレスが必要のため)


ところでnowってスケジュールリストか何かなのか
2018/09/21(金) 18:44:04.65ID:M1mNaNG00
>>18
努力しているようだが、色々おかしい。

> ソースにprintf関数をところどころに入れて、ポインタの動きを追いかけていたのですが
ポインタの『動き』ではなく、ポインタの『中身』を追いかけろ。
ポインタは自然言語で言う「ポイントする(指し示す)もの」でしかないから、
正しい物を示しているかどうかだけであって、
それはポインタ自体ではなく、『中身』を見ないと判定出来ない。

> 単方向リスト
> *ptr_now、*ptr_before、*ptr_new
単方向リストならポインタは一つだけだし、
> now と before は作業用領域で、newは名前とかを格納しています。
名前の付け方が絶望的におかしい。
多分君の理解が間違っているだけだと思うが、
もしその理解が正しくて、ガチでこんな名前を付けているソースなら、
その本は今すぐ捨てるべきだ。
これはソースを上げれば誰かが見てくれるだろう。
(多分>>22が当たりだろう)

当たり前だが、
1. まず、0,1,2,3... とリストに入れて、それを表示(リストアップ)出来る関数を作れ。
2. 次に、その関数を用いて、挿入等したとき、期待通りにリストアップ出来るか確認しろ。
3. それでバグっているようなら、その後でいちいちIDE等で止めてポインタの値を確認するんだよ。
多分お前はデバッグの仕方もおかしい。

ただまあ正直なところ、このレベルの初心者ならリストなんてどうせ使わないし、
スキップしても構わんぞ。いちいち全部やらなくてもいい。
そんなことより、ゲームを作りたいのならそのゲームを作る方向目指してコーディングしろ。
そのうち、ポインタ等の意味も分かってきて、今回の問題なんて自然に解決出来るようになる。
2018/09/21(金) 19:29:46.56ID:820RD++bM
いちいちそんなに長文で噛み付くようなことか?
2018/09/21(金) 19:50:07.83ID:M1mNaNG00
>>22
ちなみに細かいようだが、

> (単方向リストへのデータ挿入は新しいデータを挿入する位置の前後のデータのアドレスが必要のため)
実際の所、単方向リストなら

struct List {
T value; // または T* ptr;
T* next;
};

だから、ループは now と next だけで構成しないと筋が悪いんだけどね。
ソート済みリストでデリミタがヌルポなら、

while (now->next && value <= next->value) now = next; // 同値なら挿入順

で now を確定させ、now と next の間に挿入する。
nowは「今」、newが「新」として、beforeは余計だね。
何かの説明をする為なのだろうけど、余計におかしくなってる。
(挿入するのは『nowとnext』の間であって、『beforeとnow』の間ではない)
2018/09/21(金) 19:54:01.86ID:7TX+3hKV0
そもそもポインタ自体分かってない説
2018/09/21(金) 19:58:44.97ID:M1mNaNG00
>>24
駄目な事を駄目だとはっきり言っただけだ。
怒られたことのないゆとりには噛みついているようにしか見えないのかもしれないが、
このレベルの駄目っぷりを駄目出ししてもらえない方が問題だろ。

これが許容出来ないのなら、コテハン制の他サイトに行けよ。
どんなアホな投稿でも優しく教えてくれるだろうさ。
ただそれが本人の為になるかどうかはまた別だが、ゆとりにはお似合いだ。

右も左も分かってない馬鹿なんだから普通にIDE使えよ。
printfデバッグなんて(IDEが有料だった昔はさておき)
今のそのレベルの初心者がやるもんじゃない。


まあしかし、お前がそういうのならお前が導いて見せろ。
出来もしないのに文句だけ言うのもゆとりの特徴だとも思うがね。
2018/09/21(金) 20:02:21.86ID:M1mNaNG00
てゆーかマジな話、250行って何だよ?
27のリストなら精々50行だろ。
色々根本的におかしい。
本ではなく、18が根本的に間違ってるんだと思うが。
2018/09/21(金) 20:16:03.47ID:7TX+3hKV0
>>21
名前ってまさか構造体の名前じゃないよね・・?
2018/09/21(金) 21:44:03.41ID:JP8I8TZy0
>>18
その250行と、printf() を入れてみたけれどもうまくいかなかった、という printf() の挿入場所をこちらに貼ってください
https://ideone.com
話はそれから
31デフォルトの名無しさん (アウアウカー Sae9-rLjT)
垢版 |
2018/09/21(金) 22:15:10.02ID:ZlhIYDcEa
うまい釣りだ。このままじらしてじらしていつまでもソースを公開しなければこのスレは活性化して書き込みで溢れあっという間に3スレぐらい消費するだろう。流石としか言いようがない。
2018/09/21(金) 22:19:08.59ID:7TX+3hKV0
悔しいでも書き込んじゃう
33デフォルトの名無しさん (ワッチョイ c980-yqSl)
垢版 |
2018/09/22(土) 00:33:04.56ID:PGp2AKzL0
低学歴知恵遅れには質問の意味が理解できない
普通に質問の内容を再現すればだいたいこうなる

typedef struct tag_aho_list_t {
  char new[0x10];
  t_aho_list_t* next;
} t_aho_list_t;

ptr_new = (t_aho_list_t*)malloc(sizeof(t_aho_list_t));
strcpy(ptr_new->name, "aho1");
ptr_before = ptr_now;
ptr_now = ptr_new;
ptr_before->next = ptr_now;

ptr_new = (t_aho_list_t*)malloc(sizeof(t_aho_list_t));
strcpy(ptr_new->name, "aho2");
ptr_before = ptr_now;
ptr_now = ptr_new;
ptr_before->next = ptr_now;
2018/09/22(土) 01:01:16.23ID:16ZpsTnK0
>>33
お前も絶望的にダサいコードを書くな。
追加なら、

> ptr_before = ptr_now;
> ptr_now = ptr_new;
> ptr_before->next = ptr_now;

ではなくて、

ptr_now->next = ptr_new;
ptr_now = ptr_new;

だろ。
つか、単方向リストで before を使う時点で間違い。
2018/09/22(土) 01:01:57.05ID:alaCe2UCM
で?ってゆう
2018/09/22(土) 01:22:57.20ID:e+ifojdT0
遅くなりました。
ソース貼ります。

https://ideone.com/0kDpw1
2018/09/22(土) 01:42:06.64ID:16ZpsTnK0
>>36
マジでIDE使え。
そして貼るときはlanguageをCにしとけ。シンタックスハイライトが変わるから。
で、どれが分からんの?

> enter
> find
> delete
> show_all
> delete_all

mainはこの際分からなくていい。
最初に理解しないといけないのは show_all だ。

ただし細かいことを言ってもキリがないが、

> void show_all(void)

なんだこれ?引数 void って初めて見たぞ。文法的にありなのかこれ?
さらに酷いのは show_all 内でグローバル変数 address を掴んでいること。
普通は void show_all(tag_address* ta) だよ。
そうじゃないと複数のリストがあったときに使い物にならないだろ。

マジな話、このソースのレベルの本なら捨てた方がいい。
俺は大学の教材がいいと思うぞ。
(読んでないが)リストならググったら東工大とか出てきた。
http://www.is.titech.ac.jp/compview/clang/chap11.html
2018/09/22(土) 01:44:45.64ID:WyfQotM3a
voidはアリだぞ。
仕事だとなぜかvoidを書けと言われるわ
2018/09/22(土) 01:50:27.24ID:6j6Aecxq0
>>37-38
void show_all() が引数無しの意味になるのはC++。
Cだと show_all(...) と同じ意味になって何渡してもコンパイル通っちゃうからあぶない。
2018/09/22(土) 01:54:37.82ID:16ZpsTnK0
>>38
マジかーと思って linux kernel のコード見たが、書いてるな。
そして K&R 見てみたら、なんとこれも書いてた。

旧来の記法なら書くのが正しくて、物によってはコンパイル通らないとかか?
とにかく、 void がクソだというのは取り下げる。


>>39
> Cだと show_all(...) と同じ意味になって何渡してもコンパイル通っちゃうからあぶない。
マジ?今まで聞いたこと無かったわ。

しかし ( ... ) と同じ意味なら例の va_list を使う糞コードになるから、
コンパイラのチェックが甘くなるとはいえ、間違って使うって事はなさそうだが。

まあとにかくありがとう。
2018/09/22(土) 02:29:56.24ID:16ZpsTnK0
>>36
何度も言ってるがマジでIDE使え。
次にマジでこの本はソースがおかしいから捨てた方がいい。処理のフローがクレイジーだ。
何かおかしな規約に沿って書いているように思える。

178-205行目は、普通なら以下。

while(ptr_now != NULL && no >= ptr_now->no) {
if (no == ptr_now->no) {
if (address == ptr_now) address = ptr_now->next;
else ptr_before->next = ptr_now->next;
free(ptr_now);
return 0;
}
ptr_before = ptr_now;
ptr_now = ptr_now->next;
}
return -1;
2018/09/22(土) 02:55:23.92ID:16ZpsTnK0
>>36
ちなみに一応ちゃんとポインタで書いておくと、以下な。
whileの条件は分けた方が分かりやすいか?
書き込みターゲットは一つに纏める。

int delete(int no, tag_address* ptr_now) {
tag_address** ptr_tgt = &ptr_now;
while(ptr_now != NULL) {
if (no == ptr_now->no) {
*ptr_tgt = ptr_now->next;
free(ptr_now);
return 0;
}
if (no < ptr_now->no) return -1;
ptr_tgt = &ptr_now->next;
ptr_now = ptr_now->next;
}
return -1;
}
2018/09/22(土) 02:56:59.96ID:16ZpsTnK0
すまん、42は間違い。
引数を&で受けても意味無いな。書き直す。
2018/09/22(土) 03:03:32.99ID:16ZpsTnK0
>>36、42の訂正版

int delete(int no, tag_address** ptr_head) {
tag_address** ptr_tgt = ptr_head;
tag_address* ptr_now = *ptr_head;
while(ptr_now != NULL) {
if (no == ptr_now->no) {
*ptr_tgt = ptr_now->next;
free(ptr_now);
return 0;
}
if (no < ptr_now->no) return -1;
ptr_tgt = &ptr_now->next;
ptr_now = ptr_now->next;
}
return -1;
}

君には余計に分かりにくくなったかもしれないけど、こんな感じ。
まあ頑張れ。
2018/09/22(土) 03:13:04.00ID:16ZpsTnK0
>>36
enter関数も作りがおかしい。
25で言ったとおり、
> (挿入するのは『nowとnext』の間であって、『beforeとnow』の間ではない)
このソースは before と now の間に挿入しており、明らかに間違ってる。

マジでこの本はゴミだから捨てろ。
2018/09/22(土) 03:44:08.18ID:wyOkhzEz0
まあいいんじゃね?
処理内容毎に塊を分けて上から順番に並べているのは他人にわかりやすく説明するために都合がいいのだと思う。
きっと書籍では、N行目からM行目まではこんなことをしてます、とか、塊毎に処理内容のコメントが記述されてるのではないかと思う。
2018/09/22(土) 04:34:50.74ID:16ZpsTnK0
>>46
いやこれはさすがにアウトだろ。
実際部下にこのコード出されたら絶句するだろ。

178行目と194行目のヌルチェックなんてダブってるし、マジで意味無い。
頭が悪い奴が一生懸命書いたコードだぞこれは。手本にするには酷すぎる。
delete関数は筆者には難しすぎて、異常系を一つずつ外して行ってるから無駄にダブってる。
だけどこの規模でこれだと絶望的だろ。
マジでこの本は捨てた方がいい。

18が読めないのは18の技量の問題だけど、
読みやすいコードと読みにくいコードというのは実際にあって、
要するに腕前がいい奴が書いたコードは一般的に読みやすく、下手くそが書いたコードは読みにくい。
(勿論高速化等かけた場合は若干読みにくくなるが)

頭が悪いのなら、関数を分けて分割すべきであって、
breakして下に無理矢理繋げているから意味不明なコードになる。

なお高速コードは以下。
int delete(int no, tag_address** ptr_head) {
tag_address** ptr_tgt = ptr_head;
tag_address* ptr_now = *ptr_head;
while(ptr_now != NULL && no >= ptr_now->no) {
ptr_tgt = &ptr_now->next;
ptr_now = ptr_now->next;
}
if (ptr_now != NULL && no == ptr_now->no) {
*ptr_tgt = ptr_now->next;
free(ptr_now);
return 0;
} else return -1;
}
2018/09/22(土) 06:34:42.89ID:Ot5g8EvkM
もともこもないこというけど
カーネルの list.h 使え
2018/09/22(土) 08:07:18.41ID:MIXlgiXZd
C言語で
A,B,C,D,E,F,G,H,I,J,K,Lの12個のペアを、3個ずつの4つのグループに分ける場合
例えばA,BとA,CとD,Eは同じグループに入れないとして、実行時には(ADF,BCE,GHI,JKL)みたいな感じで返すプログラミングの書き方の例を教えてください
2018/09/22(土) 08:20:30.08ID:QxjPpR9VM
>>39が言ってることすら知らないID:16ZpsTnK0が偉そうに講釈たれてて笑うわ
2018/09/22(土) 08:21:44.04ID:d4QseA9MM
>>49
その例だと目的が分からないから、
それを何に使いたいのか具体例で書いてくれ。
2018/09/22(土) 08:32:14.74ID:Yqnou5lg0
>>45
このソースでは「beforeとnowの間にnewを挿入」するenter()で正しく動作するね。

リストの定常状態で、各要素はメンバnoの値で昇順整列している。
ポインタnextのつなぎ換えをする時点で、
beforeのnoは新要素のnoより小さい、nowのnoは新要素のnoより大きい、

よって new->next = now, before->next = new と格納すれば
before->no < new->no < now->no の順序が維持される。
ただし境界条件(リストの端っこの処理)はここでは考えていない。


変数やメンバの命名をもう少し工夫すれば…と思うけど。
この投稿を書いててnewとnow、メンバnoで混乱してきた。
2018/09/22(土) 08:58:29.84ID:bcuOiC7Q0
リスト操作に特化した関数を作ればいいのに
リスト操作といろんな処理を混ぜ込むから見通しが悪くなってる
教育目的ならなおのこと美しく書かないといけないのに
2018/09/22(土) 09:02:41.93ID:l48TeZqd0
>>37
>> void show_all(void)
>
>なんだこれ?引数 void って初めて見たぞ。文>法的にありなのかこれ?

この程度の知識でも偉そうに講釈垂れる事が出来るのがこのスレです
2018/09/22(土) 09:35:47.75ID:7nPJqZuh0
ワロタ
2018/09/22(土) 09:48:51.25ID:16ZpsTnK0
>>52
そりゃ糞コードでも動くだろうさ。
しかし教科書でこれはない。マジであり得ないくらい酷い。
必要のない変数を作って保持してるだろ。

走査は25に書いたとおり、(書き落とした点を修正するが)

while (now->next && value <= now->next->value) now = now->next;

でやるんだよ。そうすれば now と next だけの世界で済む。
enter()も頂けない。これは>>53の指摘通り、
int insert(tag_address* ta) と
tag_address* make_new_element(int no, char* name, char* addr)
に分けないと駄目だ。
マジでここまで酷いのはなかなか見かけないくらい酷い。
部下がこんなコード書いたら当然突き返す会社が大半だと思うぞ。

例も酷い。これは List ではなく SortedList だし、
そもそもこれをやりたいのならCではなくC++でやるべきだし。
2018/09/22(土) 09:49:43.97ID:16ZpsTnK0
>>54
そこで俺叩きに転じてるのが逆に、お前が馬鹿である証拠だ。
このコードは擁護のしようがないくらい酷い。ど素人でもここまで酷いコードは書かない。
お前にはそれが分からないから俺を叩こうとしてる。

お前みたいな初心者は文法のことばかり気にするが、文法の細かいところは本当に関係ないんだよ。
俺はC++コンパイラを使っているから>>39は関係なかったし、
>>38はそうじゃないから void を書くルールになってるんだろ。
そういうもんなんだよ。
文法的に問題があるケースはルールで禁止されてるか、環境で対策されてる。

まあ俺に文法知識が欠けているのは事実としても、この本がゴミなのは揺るがない。
理由は筆者が馬鹿だから、だから、マジですぐに捨てて他の本/サイトを参考にした方がいい。
嘘だと思うのなら、この事を覚えておいて、
数年後、お前らが上達してからもう一度このコードを見直して見ろ。絶句するから。
2018/09/22(土) 09:56:21.04ID:16ZpsTnK0
ちなみに余談だが K&R の良い点は、糞コードがないこと、余分な表現がないこと、なんだよ。
無駄を限界まで削ぎ落とした、極めて上質なコードが掲載されている。
筆者が頭が良く、一流のプログラマだからだ。

実際の所、入門書は総じてゴミだ。
これは入門書を書く奴は一般的に一流のプログラマではないからだ。
だから入門書のコードはマジで参考にしない方がいい。
今回のは特に。

お前らが上達すれば、このコードの酷さが分かるようになるだろうさ。
今回の顛末を覚えておいて、数年後に見直して見ろ。マジで。
2018/09/22(土) 10:10:07.07ID:l48TeZqd0
>>57
うんそだね〜
でもどんな言い訳してもここはC言語スレだしCプラプラコンパイラと言えどCの文法書けるわけだし
初心者に偉そうに講釈垂れるならCの最 低 限の文法くらい知ってた方がいいよ
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況