68user's page 掲示板

Prev< No. 4295〜4395> Next  [最新発言に戻る] [過去ログ一覧]
No. 4295 # 68user 2005/09/16 (金) 03:18:00
>>4294 hagu
案1. file1.txt を while で 1行ずつ読み込み、読み込んだ行が
          file2.txt に含まれるかを grep で調べる。
案2. file1.txt と file2.txt をそれぞれ sort し、diff をとって、
          行頭が < か、> かを調べる。重複する行は…どうしましょうねぇ。
案3. perl でハッシュに突っ込む。3行くらいで書けそうな気がします。

No. 4296 # hagu 2005/09/16 (金) 08:40:58
>> 4295

perl使用したことありません。
書くとしたらどうなりますか。

案1ですと、file1.txtで調べたあと、file2.txtのみで存在する物も調べるので
同様の処理が必要になります。重複する行が2回でることになります。

No. 4297 # 68user 2005/09/16 (金) 10:06:43
>>4296 hagu
Perl クックブック VOLUME 1 のレシピ 4.8・4.9 あたりを立ち読みして、
なんとかなりそうなら手を出してみるとよいでしょう。

> 重複する行が2回でることになります。
file2.txt を while で 1行ずつ読み込み、読み込んだ行が file1.txt に
含まれていれば何も表示しない、でいいのでは。

> 案2. file1.txt と file2.txt をそれぞれ sort し、diff をとって、
> 行頭が < か、> かを調べる。重複する行は…どうしましょうねぇ。
GNU diff があるなら (unified diff を出力できる diff があるなら)、
    % diff -u -U 10000 file1.txt file2.txt
として (10000 はファイルの行数を超える数)、
    ・行頭が - なら file1.txt のみ
    ・行頭が + なら file2.txt のみ
    ・行頭がスペースなら重複行
ですかね。

No. 4298 # シャチ 2005/09/17 (土) 11:00:02
>>4294 hagu

1.file1.txtとfile2.txtを辞書順にソートする。
2.diffコマンドで、file1.txtとfile2.txtの差異を表示する。
diffコマンドの出力結果の見方は、ご存じですよね。
">"は、右側に指定したファイル内に差異があることを示す。
"<"は、左側に指定たファイルにある差異があることを示す。

3.grepとかcutを使用して見やすいように編集。
4.file1.txtかfile2.txtをキーにして、grepで存在する文字列だけを抽出。

で、出来ると思います。

No. 4299 # has 2005/09/20 (火) 23:20:36
>>4294 hagu
動作未確認ですが、こういうのはダメですかね。

sort file1 | uniq > file1-2
sort file2 | uniq > file2-2
comm -23 file1-2 file2-2 | sed 's/^/file1 Only,/'
comm -13 file1-2 file2-2 | sed 's/^/file2 Only,/'
comm -12 file1-2 file2-2 | sed 's/^/common,/'

順序よく並んでしまいますが。

No. 4300 # hagu 2005/09/21 (水) 23:45:22
>> 4299
ありがとうございます。
確認してみます。

No. 4301 # hagu 2005/09/22 (木) 09:55:59
>>4299 has

ありがとうございます。
期待していた結果が得られました。

commというコマンドがあるのですね。
知りませんでした。
勉強になりました。

No. 4302 # tana 2005/10/01 (土) 17:56:09
突然すみません。私は、いま卒業研究で動画像を処理しようとしてるものです。bmpファイルからppmやpgmへの一括変換はできたのですが、それらが生(raw)なので、つまりP6なので処理に困ってます。P3にしたいのですが大量のPPM、PGMをまとめてASCIIに変換することは可能でしょうか?よろしければ教えていただけると助かります。

No. 4303 # 68user 2005/10/01 (土) 19:00:45
>>4302 tana
試してませんが、ppmtogif して giftoppm で戻すとか。

No. 4304 # tana 2005/10/01 (土) 22:40:59
giftoppmって一度に多数のファイルを変換できますか?

No. 4305 # 68user 2005/10/02 (日) 15:35:18
>>4304 tana
知りませんが、もしできないとしても
      for i in *.ppm; do ppmtogif < $i | giftoppm > out/$i; done
とか、
      ls *.gif | sed 's/\(.*\)/ppmtogif < \1 | gitoppm > out\/\1/' | sh
とか。

拡張子は適当に変更するということで。

No. 4306 # 68user 2005/10/02 (日) 15:37:52
blog なるものを始めてみました。
    http://68user.blog27.fc2.com/

入力が非常に面倒なのですが (HTML 手打ちと変わらない)、世の人たちは
使いこなしているんですかねぇ…。

No. 4307 # へにか [URL] 2005/10/03 (月) 06:52:49
日記を書く習慣の無い僕にとっては、blogを使う利点が未だに理解できないです。
もし、68userさんの視点でその利点を見出せたら、是非とも教えていただきたく、
宜しくお願いいたします。

追伸
FreeBSDでの活動は、今でもされているのですか?

No. 4308 # 68user 2005/10/03 (月) 15:43:22
>>4307 へにか
技術的なことは、最終的に web にまとめたいと思っています。しかしそれを
行うにはある程度の時間と労力がかかります。よって、とりあえず殴り書きを
するネタ帳として blog を活用できないかと考えました。

また、
    http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=4061
    http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=3774
のような、ひとつのコンテンツとしてまとめづらいメモを書く場所として
適切ではないだろうか、と思っています。

それと、コメントやトラックバックという仕組みがあるため、web よりは
フィードバックが得られるのではないかと。


しかし、perl+DBI のネタを書いてみてわかったのですが、わたしは完璧主義者
なので、結局はエディタで下書き・推敲しないと気がすまないようです。あまり
blog 向きではないのかもしれません。

あとこれは愚痴ですが、入力が非常に面倒です。まず、WRAP="OFF" 属性が付いて
いない TEXTAREA 要素の相手をすることが苦痛です。

また、ソースを張る際に <PRE>〜</PRE> で囲んでみましたが、行間に変な間が
空いてしまい、結局スペースを &nbsp; に置換して張っていたりします。
「blog は更新が簡単」と世の人は言いますが、fc2 に限れば嘘です。

> FreeBSDでの活動は、今でもされているのですか?
最近はしていませんが、するべき立場にあります。すべてはモチベーションの
問題です。

No. 4309 # へにか [URL] 2005/10/03 (月) 18:58:36
>>4308 68user
なるほど。コメントがつけられる掲示板のような使い方+トラックバックですね。
コメント:誰でも簡単に書きやすい。
トラックバック:細かい指摘事項が伝わりやすい。
ってところでしょうか。仕組みとしては、やりたいことに一番近そうに見えますが、
>「blog は更新が簡単」と世の人は言いますが、fc2 に限れば嘘です。
恐らく、今流行っているタイプのblogの使用目的に合致していない、と思います。
・・・と言いつつ、実はblogを理解して無いので、間違った事を言っているかもしれませんが。

>すべてはモチベーションの問題です
それはいえるかもしれませんね。元同僚は、とある部分のソースを書くという
立場にいるそうですが、結構(手続きが?)大変だ、といってましたし。
自分の時間がとれて、収入に余裕があって、FreeBSDに絶対に貢献したいという
意思が無ければ、なかなか腰が上がらないのだと、勝手ながら推測しております。

赤色の文字は 「Windows 機種依存文字」か、いわゆる「半角カナ」です。 この掲示板では自動変換されますが、今後は使用しないで下さい

No. 4310 # UNIX初心者 2005/10/06 (木) 00:40:29
突然ですみません、UNIX初心者です。
UNIXにて以下の様な事がしたいのですが、よい方法があれば教えて下さい。
随時追加されるあるファイル(aaa.txt)の内容を行単位ででCプログラムで読込みたい。
条件)
1.aaa.txtは行単位に随時追加される。
2.Cプログラムに渡すのはある文字が含まれる行のみ。

以下の様なことを試したのですが、うまくいきませんでした。
tail -f aaa.txt | grep ABC | Cプログラム
※Cプログラムは今の所、標準入力(gets)から読み込むだけのプログラムです。

No. 4311 # 68user 2005/10/06 (木) 00:57:33
>>4309 へにか
> なるほど。コメントがつけられる掲示板のような使い方+トラックバックですね。
そうですね。ただ、コメントやトラックバックより、思いついたことを
すぐに書くための場所、という方がわたしにとっては重要かなと思っています。

> 恐らく、今流行っているタイプのblogの使用目的に合致していない、と思います。
いや、ただインタフェースがイマイチなだけだと思います。空白を &nbsp; に
変換してくれればそれで解決する話ですから。

>>4310 UNIX初心者
こちらを。
http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=2800

No. 4312 # UNIX初心者 2005/10/06 (木) 23:11:25
>tail -f log | perl -ne '$|=1;print if m/foo/' >> log2
で試してみたのですが、perlがインストールされていない為、エラーとなってしまいました。
今回は急ぐので、プログラムで対応してしまいました。
また、利用させて下さい、ありがとうございました。

No. 4313 # 68user 2005/10/07 (金) 02:17:15
>>4312 UNIX初心者
解決したとのことなので返信不要ですが、perl がないなら
    % tail -f aaa.txt | awk '/ABC/{print;system("")}' | Cプログラム
ですかね。FreeBSD 5.2.1-RELEASE ではうまくいきました。

No. 4314 # hagu 2005/10/15 (土) 19:06:52
Solaris8のBシェルで、CSV形式のデータのソートを行っています。
数字順にソートしたいのですが、ソート対象の列が半角英数のため
数字順になりません。うまい方法はないでしょうか。
英字が先頭にある場合は、英字を取り除いて数字順にしたいのです。
うまい方法はないでしょうか。

sortコマンドだけでは、だめでした。

--データ
山本 こうたろう,企画,100
山下 大介,企画,A101
山田 太郎,営業,80
山田 花子,営業,A92
山田 一郎,営業,A82
鈴木 一郎,販売,85
鈴木 一郎,海外,1001
松井 英樹,海外,2001
斉藤 次郎,製造,125
佐藤 三郎,組立,A124
武藤 五郎,検査,130

--結果
山田 太郎,営業,80
山田 一郎,営業,A82
鈴木 一郎,販売,85
山田 花子,営業,A92
山本 こうたろう,企画,100
山下 大介,企画,A101
佐藤 三郎,組立,A124
斉藤 次郎,製造,125
武藤 五郎,検査,130
鈴木 一郎,海外,1001
松井 英樹,海外,2001




sortコマンドの「-n」を付けてやってみたのですが、数値として判断するため
上手くできません。
また、付けないと、数値順に並んでくれません。

No. 4315 # hagu 2005/10/15 (土) 19:19:00
>>4314 hagu
訂正です。
名前の前に社員IDがあり、
半角英数字でソートし、社員IDでソートとなります。
データは、「社員ID、名前、仕事、コード」
コードの半角英数字で数字順に並び替えで、
コードが同じな場合は、社員IDで並び替えです。
英字が先頭にある場合は、英字を取り除いて数字順にしたいのです。
No.4314の結果にしたいのです。

No. 4316 # 68user 2005/10/15 (土) 19:51:38
>>4314 hagu
101 と A101 という社員 ID が存在する可能性があるか、存在するならソート順は
どうするかという仕様が不明確ですが、それは置いておくとして。

> 山本 こうたろう,企画,100
> 山下 大介,企画,A101
> 山田 太郎,営業,80
> 山田 花子,営業,A92
わたしなら一度 sed などで
    山本 こうたろう,企画,,100
    山下 大介,企画,A,101
    山田 太郎,営業,,80
    山田 花子,営業,A,92
と別項目にし、sort して、再度 sed で元に戻します。

No. 4317 # hagu 2005/10/15 (土) 23:47:12
>>4316 68user

ありがとうございます。
一度、コードの値を分解しには、気がつきませんでした。
いいかも知れません。

>101 と A101 という社員 ID が存在する可能性があるか、存在するならソート順は
>どうするかという仕様が不明確ですが、それは置いておくとして。
コードでソートした後、同じコードないで、社員IDをソートします。
ただし、数字のコードは、数字のコード内で、
英字付きのコードは、英字付きコード内で、
社員IDを並びかえます。

No. 4318 # 匿名希望 2005/10/18 (火) 19:47:44
お世話になります。
C言語でHTTPクライアントを作成しています。ここのサイトもありますが、自作で行いました。
AのHPを取得してうまく表示されますが、BのHPを取得すると、表示されません。
取得したページのヘッダ情報はどっちも異常はありませんでした。
デバックではどっちでも表示されます。でも、BのHPが取得しても表示されません。
何か助言をして頂けたら幸いです。よろしくお願い致します。

No. 4319 # 68user 2005/10/18 (火) 23:11:48
>>4318 匿名希望
- 現象が再現する最小限まで削ったソースを提示してください。
- A と B の URL を提示してください。
- そちらで実行した結果を提示してください (ヘッダ情報とかデバッグを含む全部)
- OS・コンパイラなどの情報を提示してください。

なお、UNIX 以外であれば、わたしはコンパイル環境がないのでわかりません。

No. 4320 # SSL初心者 2005/10/19 (水) 16:09:35
初めて投稿します。
自分はSSLを組み込もうとしていろいろ調べているんですが、
調べていると、WindowsでのSSLの設置方法がかかれてないんです。
やっっぱりリナックスで設置したほうがいいのでしょうか?

No. 4321 # 68user 2005/10/20 (木) 01:13:13
>>4320 SSL初心者
まずは検索を。
http://www.google.co.jp/search?q=windows+apache2+ssl&hl=ja&lr=lang_ja&ie=utf-8&oe=utf-8

No. 4322 # マッケーブ 2005/10/20 (木) 15:39:43
お世話になります。
「マッケーブの循環的複雑度」を出力するツールを探しており、
当ホームページから コマンドcccc(C言語・C++・Java のソース
コードのステップ数を調べるツール。)を探し当てました。
ところが、身近にあるサーバで試してみると、
$ cccc hoge.java
-bash: cccc: command not found
と出力されます。

コマンドccccを実行するための条件等、ありますでしょうか。
ご教示、よろしくお願いします。

No. 4323 # ミケフォ [E-mail] 2005/10/20 (木) 18:12:00
初めまして。
『UNIXの部屋』の localtime(3) のサンプルコードにある
tm_timeの一連の変数参照が間違っています。

No. 4324 # hoge 2005/10/20 (木) 22:15:02
>> 4322
http://x68000.q-e-d.net/~68user/unix/pickup?Command+not+found

2 又は 6 では無かろうか.

No. 4325 # Netboy 2005/10/22 (土) 14:28:50
サーバーの件でメールをお送りしました

No. 4326 # SSL初心者 2005/10/26 (水) 12:59:02
すみません。SSLをWindowsで設定しているんですが、
Apacheのインストールで下記のエラーが出ます。

(OS 10048)通常、各ソケット アドレスに対してプロトコル、ネットワーク アドレス、
たはポートのどれか 1 つ のみを使用できます。 : make_sock: could not bind to
dress 0.0.0.0:80
no listening sockets available, shutting down
Unable to open logs

これは、どういった意味のエラーなのかさっぱりわかりません。
自分で調べてもどの方面から調べるのかわからずじまいで投稿しました。
環境は以下のとうりです。

OS - Windows98
Apache - Apache_2.0.55-Openssl_0.9.8a-Win32をダウンロード
OpenSSL - Win32OpenSSL-v0.9.8を使用

参考HP - www.rinzo2.jp/~rinzo/apache_ssl/apache_and_ssl_00.htm

ご意見お待ちしております

No. 4327 # awk初体験。 2005/10/26 (水) 14:54:35
シェル内にて以下の記述を入れるとエラーが発生します。

■エラー発生箇所
cat ./temp.txt | awk 'BEGIN{FS=","}{if(match($1,"^${_XXX_}")!=0){print $0}}' > ./test.csv

■出力エラー
awk: There is a regular expression error.
                ?, *, or + not preceded by valid regular expression
  The source line number is 1.
  The error context is
                                  >>> BEGIN{FS=","}{if(match($1,"^${_XXX_}") <<<

"^${_XXX_}"の部分がエラーとなっているようですがここでは変数は使用できないのでしょうか?

No. 4328 # 68user 2005/10/27 (木) 11:45:32
>>4326 SSL初心者
「OS 10048」で検索した結果の 1番目に出てくるのがおそらく答えです。
    http://www.google.co.jp/search?q=OS+10048&start=0&start=0&hl=ja&lr=lang_ja

>>4327 awk初体験。
ウチの環境ではエラーにならないのでよくわかりませんが、
    ${_XXX_}
って変数のつもりで書いてるんですよね? どこで ${_XXX_} に値をセット
しているのですか?

もしシェルスクリプトでシェル変数や環境変数にセットしているのなら、
引数全体を '' で囲んでいるので置換されません。というわけで

    cat ./temp.txt | awk 'BEGIN{FS=","}{if(match($1,"^'${_XXX_}'")!=0){print $0}}' > ./test.csv

などと ${_XXX_} を外に出します。

No. 4329 # 68user 2005/10/27 (木) 11:58:11
>>4323 ミケフォ
> 『UNIXの部屋』の localtime(3) のサンプルコードにある
> tm_timeの一連の変数参照が間違っています。
ありがとうございます。bugid 18 として登録しました。
    http://x68000.q-e-d.net/~68user/bugnote/viewbug.php?projectid=1&bugid=18

# 登録する暇があるなら、さっさと直せと。

No. 4330 # Netboy 2005/10/27 (木) 12:02:11
すみません,昨日18時頃から本日11時まで
サーバーの通信が切れていました.

昨日13時頃に回線工事があって無事完了したのですが,
終端装置の接続が雑だったらしく,17時頃に突然接続が落ちました.

すぐ業者に連絡したのですが既に営業時間外で,
朝まで修理を呼べませんでした.
本日11時に業者が来て直りました.

ご報告まで.

No. 4331 # キック 2005/10/27 (木) 16:56:13
お世話になります。

C言語でHTTPクライアントを作成してますが、HTTPSの場合のポート番号が
サイトを探しても見つからないですが、ご存知でしょうか?
よろしくお願い致します。

No. 4332 # 68user 2005/10/27 (木) 17:12:26
>>4330 Netboy
対処いただきありがとうございます。IP アドレスの件はもう少々お待ちください。

>>4331 キック
「https ポート番号」で検索したら一番最初に出てきます。
    http://www.google.co.jp/search?q=https+%E3%83%9D%E3%83%BC%E3%83%88%E7%95%AA%E5%8F%B7&hl=ja&lr=lang_ja

No. 4333 # キック 2005/10/27 (木) 17:19:59
>>4332 68user

ありがとうございます。
初歩的ですみません(^ ^;)>

No. 4334 # hagu 2005/10/28 (金) 10:37:09
シェルで、ftpを自動で実行しています。
ftpの接続、ログインの判定や、ファイルのput/getの判定
ができたか判断したいのですが、できるのでしょうか。
エラーが発生したら、「exit 1;」などで終了させて、その
ステータスを判断するといったことはできないのでしょうか。

-----------------
ftp -v -n ${SERVER} <<END >/dev/null
user ${FTP_USER_ID} ${FTP_PASSWORD}
cd ${FTP_DIRECTORY}
lcd ${LOCAL_DIRECTORY}
get ${GET_FILE}
bye
END

環境:
    Solaris8i
    Bシェル

No. 4335 # awk初体験。 2005/10/28 (金) 17:15:32
No. 4327 で質問させていただきました。
変数はシェル内で実行していました。
そのため""で括った所上手くいきました。
ご回答ありがとうございます。

さらに別の質問させてください。
カンマ及びスラッシュを区切り文字としたいのですが…
-FオプションやFS=の指定で複数の区切り文字を指定することはできるのでしょうか?

No. 4336 # zsh 2005/10/30 (日) 11:51:51
>>4335 awk初体験。
区切り文字に正規表現を使用できるawkであれば可能です。
(gawkやnawkなら使用可能ですが、Solaris標準のawk等では使用できません。)

$ nawk -F"[,/]" '{ .... }' file
$ nawk 'BEGIN{ FS="[,/]" } { .... }' file

No. 4337 # 68user 2005/10/30 (日) 15:35:42
2005/10/29(金) 00:00:00 ごろから IP アドレスの変更・それに伴う DNS 設定変更を
行いました。Refresh とか Retry とか Expire などを理解していないので、何も対策
せずいきなり切り替えました。そのせいで つながらなかった人もいると思いますが、
ご迷惑をおかけしました (わたしも数時間つながらなかった)。

ご協力ありがとうございました>Netboy さん

>>4323 ミケフォ
遅くなりましたが、修正しました。
ご指摘ありがとうございました。

# http://x68000.q-e-d.net/~68user/bugnote/viewbug.php?projectid=1&bugid=18

>>4334 hagu
わたしなら Perl の Net::FTP モジュールなどできっちりエラーチェックしますが、
どうしても ftp コマンドを使わざるをえないなら、
    - ftp コマンドに -d オプションなどをつけて実行結果のログをとる。最後に
        ログを解析してステータスコードに 4xx 系・5xx 系 がないことをチェックする。
    - 接続した時点でリモートに同名のファイル名がないならば、get/put を行って、
        最後に ls して、結果をログに保存する。ls の結果を解析し、ファイル一覧・
        ファイルサイズ・ファイル個数などのチェックを行う。
くらいしかないような気がします。

No. 4338 # 68user 2005/10/30 (日) 15:41:23
>>4337 68user
> 2005/10/29(金) 00:00:00 ごろから
2005/10/29(土) 00:00:00 の誤りでした。

No. 4339 # TKG 2005/10/31 (月) 21:57:21
A君とB君(ユーザーIDはそれぞれAとB)は同じグループG(グループIDはG)に属しているとします。
A君は、自分のホームディレクトリ(~A)にあるディレクトリDの中の全てのファイルを、B君など同じ
グループに属する人にだけ閲覧可能にしたいと考えました。ただし、A君はディレクトリD以外の
ファイル・ディレクトリは(それらのリストを取る(lsコマンド)ことも許可したくありません。
A君はどのようなパーミッションを設定すればよいでしょうか?

No. 4340 # 68user 2005/11/01 (火) 01:23:05
>>4339 TKG
    ~A/ 710
    ~A/D/ 750
    ~A/X/ (D 以外) 700
でしょうか。

No. 4341 # 2005/11/02 (水) 11:36:55
Solarisでシェルスクリプトを起動する場合。
$ csh script.cshと入力しなければなりませんが、
最初のcsh を省略して$ script.cshで起動する方法を教えて下さい。
宜しくお願いします。

No. 4342 # zsh 2005/11/02 (水) 17:49:42
> 68user様
http://x68000.q-e-d.net/~68user/unix/genre.html#genre22
にheadが二つ表示されています。

>>4341
UNIXの部屋を読めば判ると思いますが・・・
  1.スクリプトの一行目にシェルのパスを指定する。
  2.環境変数PATHを設定する。
  3.スクリプトに実行権をつける。
といったところでしょうか。
http://x68000.q-e-d.net/~68user/unix/pickup?Command+not+found

No. 4343 # hoge 2005/11/02 (水) 18:54:10
>> 誠さん

4342 で言われている PATH の設定は csh が置かれている場所にパスを通すって
意味であって、PATH に "."(カレントディレクトリ) を加えるって話では無い筈です。
従って、 単に script.csh ではなく ./script.csh って起動方法になると思います。

PATH に "." を加える事の問題とか、csh スクリプトを覚えるよりも sh 系の
スクリプトを覚えた方が良いって話は検索すれば出てきますので読んでみましょう。

No. 4344 # zsh 2005/11/03 (木) 13:34:58
>>4343 hoge
スクリプト専用のの格納ディレクトリがあるのかと思い
PATHの設定が必要と書きました。
・・・・ちょっと意地悪したくなったのも事実ですが。

No. 4345 # hagu 2005/11/04 (金) 17:19:50
>>4337 68user
返事が遅くなって申し訳ありません。
アドバイスありがとうございます。
ログに出力し、ログをチェックする方法でやってみます。

No. 4346 # hagu 2005/11/04 (金) 17:23:52
sedを使用して大文字から小文字に変換したいのですが、
なかなか上手くいきません。
例えば、「YAMADA」を「Yamada」と先頭の1文字目は大文字で、
2文字目以降を小文字に変換したいのですが、以下の様にsed
を使ってやったのですが上手く行きません。
sedでは、無理なのでしょうか。
環境は、Solaris8、Bシェルです。

----------------------
NM=Ya1AMADA
echo $NM | sed 's/[A-Z].*/[a-z]/g'

NM=YAMADA
echo $NM | sed 's/\(.\)[A-Z]*/\1/g'

No. 4347 # 2005/11/04 (金) 18:25:03
>>4346 hagu
多分、sedだけでは無理だと思います。

sedを使わなくても、awkだけでも可能です。

echo $NM | nawk '{for(j=i=1;i<=length($0); i++) if(i==1) {NM[i]=substr($0,i,1)} else {NM[i]=tolower(substr($0,i,1))}} END{for(count in NM) printf("%c",NM[count]); printf("\n")}'

No. 4348 # hagu 2005/11/04 (金) 21:58:31
>>4347

試してみましたが、出方が変です。
amadaY となります。

No. 4349 # マーブル 2005/11/05 (土) 08:16:10
始めまして、ネットワークプログラミング周辺読ませて頂きました。
簡潔なソースで読みやすかったです。
お礼に掲示板カキコ、それにしてもみなさん勉強熱心ですね(笑

----------------------------------------
echo $NM | \
sed -e h -e 's/^\(.\)\(.*\)/\1/g' \
-e 'y/[abcdefghijklmnopqrstuvwxyz]/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/' \
-e x \
-e 's/^.\(.\)/\1/g' \
-e 'y/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/[abcdefghijklmnopqrstuvwxyz]/' \
-e H \
-e g \
-e 's/\n//'
----------------------------------------

なんとなしsedの勉強してしまった、本買う気にはならないけどね。
http://web.archive.org/web/19961202111128/http://yase.yajima.kuis.kyoto-u.ac.jp/staffs/sengoku/sedlec/

No. 4350 # has 2005/11/05 (土) 11:03:28
>>4346 hagu
もしperlならこんな感じなんでしょうか?
echo $NM | perl -ple 'y/A-Z/a-z/;substr($_,0,1)=~y/a-z/A-Z/;'

No. 4351 # 2005/11/05 (土) 13:43:04
>>4347
>>4348 hagu

連想配列の場合、表示の順序は、ハッシュ法に従うのでランダムとなります。
すみません。

echo $NM | nawk '{for(i=1;i<=length($0); i++) if(i==1) {NM[i]=substr($0,i,1)} else {NM[i]=tolower(substr($0,i,1))}} END{for(j=1; j<i; j++) printf("%c",NM[j]); printf("\n")}'

No. 4352 # hagu 2005/11/05 (土) 13:58:38
>>4349 マーブル
凄い。
sedだけでですね。
でも、凄く、複雑すぎます。

>>4351
今度は、期待したいた結果が得られました。
awkを使っているのも複雑ですね。

No. 4353 # zsh 2005/11/05 (土) 14:28:08
>>4352 hagu
これじゃだめ?

$ echo $NM | nawk '{ a=toupper(substr($0,1,1)); b=tolower(substr($0,2)); printf "%s%s\n",a,b; }'

No. 4354 # 2005/11/05 (土) 23:53:05
>>4353 zsh

そうですよね。
substr()で2文字目以降すべてを変換してしまえばいんですよね。
何、ループで1文字ずつ変換し、表示しているんだろう。

No. 4355 # マーブル 2005/11/06 (日) 02:06:34
あまり知られていないscanfの用法。
既出でしたか残念。>>4041>>4042
http://www.linux.or.jp/JM/html/LDP_man-pages/man3/scanf.3.html

以下同意
-------------------------------------
sscanf(host_path,"%[^/]%s",host,path);
-------------------------------------
p = strchr(host_path, '/');
if ( p != NULL ){
    strcpy(path, p);
    *p = '\0';
    strcpy(host, host_path);
} else {
    strcpy(host, host_path);
}
-------------------------------------

No. 4356 # マーブル 2005/11/08 (火) 01:39:16
fdopen()で作成されたストリームが閉じられたときにファイル記述子も 閉じられる。
http://www.linux.or.jp/JM/html/LDP_man-pages/man3/fdopen.3.html
よって以下のページのL:125は不要です。
http://x68000.q-e-d.net/~68user/net/c-http-2.html

No. 4357 # 68user 2005/11/08 (火) 02:42:15
>>4356 マーブル
ありがとうございます。とりあえず POSIX を確認させてください (明日以降)。
    http://www.opengroup.org/onlinepubs/009695399/functions/fdopen.html

No. 4358 # 68user 2005/11/08 (火) 02:51:42
>>4357 68user
明日以降と言いつつ今確認してみましたが、POSIX にはそういう記述は
ないように見えます。また、Solaris9 のマニュアルにも書いてないように
見えます。
    http://www.freebsd.org/cgi/man.cgi?query=fdopen&sektion=3C&manpath=SunOS+5.9

しかし BSD ならば、4.4BSD-Lite2 にはそのような記述があります。
    http://www.freebsd.org/cgi/man.cgi?query=fdopen&manpath=4.4BSD+Lite2&format=html

Solaris や HP-UX が手元にある方にお願いなのですが、fdclose して fclose した
ときにソケットディスクリプタがクローズされるかどうか truss コマンドなどで
確認していただけないでしょうか (わたしのまわりは FreeBSD と Linux しかないので)。

いずれにせよ何かしらの補足は追記したいと考えています。

No. 4359 # 68user 2005/11/08 (火) 03:00:02
>>4358 68user
> fdclose して fclose したときに
「fdopen して fclose したときに」の誤りでした。

ちなみに「UNIX ネットワークプログラミング第2版」からは、この件についての
記述を読み取ることはできませんでした。

No. 4360 # マーブル 2005/11/08 (火) 04:30:12
>>4359 68user
機種依存等深く考えずに書き込んでしまって申し訳ございません。
また知合いに話せる人がいない為に決めつけたような書き込みになってしまったこともお詫びします。

基本的にFILE構造体にfileディスクリプタが含まれているものと理解していたもので、
fclose時に連動してcloseされるかな?と単純に考えてしまいました。

trussで確認した結果が以下でcloseされているようでした(これおもしろいですね)
SunOS eibw23 5.9 Generic_112233-03 sun4u sparc SUNW(Solaris8か9)
-----------------------------------------------------------
read(0, 0xFF3414EC, 1024) (sleeping...)
read(0, "\n", 1024) = 1
llseek(3, 0, SEEK_CUR) = 0
close(3) = 0
read(0, 0xFF3414EC, 1024) (sleeping...)
read(0, "\n", 1024) = 1
_exit(0)

No. 4361 # マーブル 2005/11/08 (火) 04:33:00
>>4360 マーブル
うゎ、アドレス込みで貼っちまった、ハズカシィ

No. 4362 # マーブル 2005/11/08 (火) 04:48:39
>>4360 マーブル
opensolarisがsolarisとどれだけ違うかわかりませんが、
http://cvs.opensolaris.org/source/xref/on/usr/src/lib/libc/port/stdio/fdopen.c#64
fdの値は単純に渡されているように見えます。
(↑のサイト使い安くて良く使ってます、BSDでこのような感じのページご存知ですか?)

No. 4363 # 68user 2005/11/08 (火) 13:23:30
>>4360 マーブル
昨日は変なことを書いてしまいました。fclose したんだから close するのは
当然ですよね。まぁ fdopen したものはフラッシュだけ行って close しない
実装があっても不思議ではないですが、素直に考えれば close するはず。

よって、125行目の close は削除します。

>>4362 マーブル
> (↑のサイト使い安くて良く使ってます、BSDでこのような感じのページご存知ですか?)
普通の cvsweb でよければ、以下のものが cvsgraph が組み込まれているのでよく使います。
    http://cvsweb.allbsd.org/cvsweb.cgi/src/lib/libc/stdio/fdopen.c
ソース閲覧なら GLOBAL を使ったFreeBSD Source Code Tour が便利ですが、ファイル名が
ころころ変わるので URL を保存しておいても役に立たないのがが困りものです。
    http://snapshots.jp.freebsd.org/tour/
    http://snapshots.jp.freebsd.org/tour/current/userland/cgi-bin/global.cgi?pattern=fdopen&id=&type=definition
    http://snapshots.jp.freebsd.org/tour/current/userland/S/9687.html#53

OpenSolaris のソースを見られるところは知りませんでした。今後活用させて
いただきます。

No. 4364 # がちゃぴ 2005/11/08 (火) 15:45:39
初めましてWindowsユーザですが、仕事上 LinuxやCVSを使うことがあります。
コマンドをなかなか覚えられなくて、いつも参考にさせて頂いています。

No. 4365 # hagu 2005/11/08 (火) 18:05:43
>>4353 zsh

凄いです。
変換されました。

No. 4366 # anonymous 2005/11/08 (火) 22:03:49
よくパーミッションでrは読む権利を、wは書く権利を、
xは実行する権利を与えるといいますが、それぞれの権利が
与えられている時、いない時は具体的にどのようなコマンド
が有効であるのか、いまいちはっきり理解できません。
どなたか詳しくをしえてください。

No. 4367 # has 2005/11/09 (水) 00:01:04
>>4366 anonymous
> それぞれの権利が与えられている時、いない時は具体的にどのようなコマンドが
> 有効であるのか
何か哲学的なニオイがするので(?)、そもそも私が答えられる内容でも無い気は
しますがそれでもよければ教えてください。
ええと、ちょっと見た限りでは書き込み中の「有効」の意味がよくわかりません。
もしかしたら具体的に何か目的があるんでしょうか。
あと、パーミッションが与えられているのはプログラム?読み書きするファイル?

No. 4368 # 68user 2005/11/09 (水) 00:14:27
>>4364 がちゃぴ
ありがとうございます。ご意見・ご指摘がありましたら遠慮なくどうぞ。

なお、世の中いろんな人がいますので、文章の一部を削除させていただきました。
削除した部分に関する話題はご遠慮いただきたく思います。ご理解ください。

>>4366 anonymous
紛らわしいのでハンドルを「68user」から「anonymous」と変更しました。
今後は適切なハンドルを使用してください。

No. 4369 # マーブル 2005/11/09 (水) 01:36:27
>>4363 68user
御回答ありがとうございました。
また情報交換ができてうれしく思います、重ねてお礼申し上げます。

>>4367 has
話に割り込んでしまってごめんなさい。
>>4366 anonymous
コマンドが読み書きするファイルのアクセス権限を考慮して判断するのが良いと思います。
例えばmountコマンドでは一般userにデバイスへのアクセス権限がないので(当方FreeBSD)、
コマンドは実行できてもmountはできません。
また許可を与えたい場合、デバイスファイルのパーミッションを変更すれば使用できますが、
いろいろ問題がありそうなので、
http://x68000.q-e-d.net/~68user/unix/pickup?sudo
の方法を取ったりするそうです。

ついでにちょっと変な話。
実行権限がないディレクトリに対して移動(cd)もディレクトリの内容の確認も(ls)もできません。
が、opendir(c言語)を用いいると実行権限がなくても内容の確認ができてしまいます。
なんだか不思議な感じがしませんか?

No. 4370 # 68user 2005/11/09 (水) 02:02:19
>>4369 マーブル
> 実行権限がないディレクトリに対して移動(cd)もディレクトリの内容の確認も(ls)もできません。
> が、opendir(c言語)を用いいると実行権限がなくても内容の確認ができてしまいます。
少々誤解があるようですが、実行権限がないディレクトリに対しては、移動 (cd) は
できませんが、ディレクトリの内容の確認 (ls) はできます (読み込み権限があれば)。
しかし ls -l はこけます。

引数なしの ls が行っていることは opendir(2) なわけですが、opendir(2) は
ディレクトリの下にアクセスしません。ディレクトリエントリを読むだけなので
    % cat ディレクトリ名
相当の処理しかしていません。よって、ディレクトリに対する読み込み権限があれば
ファイル一覧を取得できます (ディレクトリも広義のファイル)。

一方 ls -l は opendir(2) して、取得したファイル名それぞれについて stat(2) する
わけですが、stat(2) するには それぞれのファイルの i-node を知る必要があります。
しかし i-node を知るには、そのファイルが属する上位ディレクトリの実行権限が必要です。

結局のところ、ディレクトリに対する実行権限とは
      「ファイル名から i-node への変換を許可するかどうか」
であり、言い換えると
      「namei(9) を許可するかどうか」
だとわたしは思っていますが、違っていたら誰か教えてください。

No. 4371 # マーブル 2005/11/09 (水) 08:21:56
>>4370 68user
すいません-Fのエイリアス掛かってました。
\lsで動作します、掲示板汚してごめんなさい。

truss ls -F testdirの結果の一部
fchdir(0x5) ERR#13 'Permission denied'
よりディレクトリ内に移動できないということらしいです(FreeBSD)
(Linuxで試したらfstatでのエラーだったのでものによりけりな予感

No. 4372 # 68user 2005/11/09 (水) 11:15:37
~はunixではどのような存在なのですか?

No. 4373 # マーブル 2005/11/09 (水) 13:24:33
>>4368 68user
>>4366 anonymous
は解決したのですか?

No. 4374 # DNS勉強中 2005/11/10 (木) 14:36:15
はじめまして。
学校の課題で、C言語でnslookupみたいな動作をするプログラムを作るように言われ
こちらのサイトを参考に作成させていただいております。

それで一箇所気になったのですが、

http://x68000.q-e-d.net/~68user/net/resolver-3.html
> タイプが TXT なら、そのまま表示します。
> これは多分間違い。
> % ./resolver-1.pl www.jp.freebsd.org version.bind txt chaos
> リソースデータは「&Sorry, no version string is available」と表示されるが、
> dig や nslookup は「Sorry, no version string is available」となります
> (& がない)。
> 先頭の & を削るような規則があるようだが、それが何なのかはわからなかった。

の部分ですが、&の文字コードは0x26(10進数で言う38)。
そしてその後に続く
【Sorry, no version string is available.】
は38文字。
つまりドメイン名の3www8livedoor3com0と同じような意味かなと思います。
そのため先頭の1バイト目を出力しないようにすればdigやnslookupと同じような
表記になるのではと思います。

例) sega.jpを調べるとunknownが帰ってきますが、その中身は
【07 75 6e 6b 6e 6f 77 6e】です。

文字数が32文字以上ないと画面上には何も表示されないので、
それ以下の文字数のところでは結果的にうまく出力されているのかなと思います。
そのため【タイプが TXT なら、そのまま表示します。】ではなく、
【タイプが TXT なら、先頭1バイト以外をそのまま表示します。】かなと思います。
ぜんぜん的外れな事言っていたらすいません。

No. 4375 # DNS勉強中 2005/11/10 (木) 16:55:45
こちらのサイトを参考にresolver-1.plと似たような動作をする
C言語のプログラムを作成したのですが、一箇所分からないところがあったので、
もしお分かりになるようでしたらアドバイスをいただけないでしょうか。

作成ソース(一応問題なく動くと思います)
windows版(CPad 2.31使用)
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1052.txt
linux版(gcc 2.96使用)
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1053.txt

それで、分からないのは【DNS query 送信時にごみデータが後ろに大量に付く】事です。
ごみが付いてしまう理由は、
DNS query の質問レコードの照会名(可変長)の長さは
実際に名前解決ホスト名を入力されないと分からないので、
char QUERIES[400];と宣言し、そこに名前解決ホスト名を格納しているからです。
そして、その後ろに、タイプとクラスを連結しています。
そのためQUERIES[400]の余った部分がごみデータとなってしまいます。
実際の動作には問題が無いみたいで、
パケットをキャプチャしなければごみが付いているのは分からないのですが、
気持ち悪いので改善したいと思っております。

アドバイスをいただけるようでしたら、どうかよろしくお願いします。

No. 4376 # DNS勉強中 2005/11/10 (木) 16:58:56
たびたびすいません。
No 4375のソースですが、
掲示板から直接クリックするとアップロードしたソースが見えないようなので、
ブラウザを新規に立ち上げてアドレス欄にコピーしてアクセスしていただけますでしょうか。

No. 4377 # Yuusuke 2005/11/10 (木) 18:07:20
テストサーバ:solaris8
本番サーバ :solaris8
ワークステーション間のファイル転送について質問です。
テストサーバで構築したディレクトリを本番サーバに移行しようとしています。
条件としてファイルのパーミッション、ユーザ.グループ、タイムスタンプは
変わらないようにします。
そのため
"tar cvf /tmp/system.tar ."
でアーカイブして"rcp"で本番サーバにアーカイブファイルを転送してファイルを
展開したのですがユーザ.グループが本番サーバのログインユーザのものになって
しまいました。
tarは既存の状態をそのままアーカイブすると思っていたのですがrcpで転送すると
変わってしまうのでしょうか?
よろしくお願いします。

No. 4378 # Yuusuke 2005/11/10 (木) 18:57:26
No.4377の質問をした者です。
本番サーバでアーカイブしたファイルを展開時に"root”ユーザで実行したところ
既存の環境のままで展開できました。
solarisでは["o"オーナーシップ]というオプションが"root"ユーザ以外のユーザが
アーカイブファイル展開時に付属するようでした。
おさわがせしましたm(__)m

No. 4379 # 68user 2005/11/10 (木) 20:19:47
>>4374 DNS勉強中
ありがとうございます。

以前も length では、というご指摘をいただいたのですが、RFC などの
一次資料を見つけられずにいます。
    http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=4283
    http://x68000.q-e-d.net/~68user/cgi-bin/wwwboard.cgi?log=4293

この件に関する一次資料をご存知でしょうか?

>>4375 DNS勉強中
> 分からないのは【DNS query 送信時にごみデータが後ろに大量に付く】事です。

> sendto(s, (const char *)&DNS_Send, sizeof(DNS_Send), 0, (struct sockaddr *)&server, sizeof(server)) < 0) {
sizeof(DNS_Send) バイトを送信しているのがまずいので、必要なバイト数分だけ
送信すればよいと思います。この例なら送信バイト数は

    (DNS_Send.QUERIES - &DNS_Send.id + count + 4) バイト

ですかね? (自信なし) まぁこれだと汚いので、質問数や長さを保持する変数を
追加した方がよいと思います。

あとは struct DNS_Packet のパディングが心配です (実際は id や flag は
short なのでほとんどの環境では問題ないと思いますが)。わたしなら
    struct DNS_Query {
        ....
    };
    struct DNS_Question {
        short id
        short flag;
        short QDCOUNT;
        short ANCOUNT;
        short NSCOUNT;
        short ARCOUNT;
      struct DNS_Query *q;
    };
    struct DNS_Packet {
        char data[1000];
        int length;
    };
として (命名は適当)、問い合わせ内容を DNS_Question に構築し、送信時に
DNS_Packet にコピーして send すると思います。といっても、わたしのソースの方
では全く実践できていないですけれども。

ところで、全体的にはかなり読みやすいと思うんですが、このソースのライセンスを
教えてください。要は、これを修正したものを、わたしのページに C のサンプル
コードとして記載することは可能でしょうか? ということです。


>>4378 Yuusuke
一般ユーザで展開したときに他ユーザの所有者でファイルを作成できてしまうと、
適当な tar ファイルをでっちあげれば他のユーザのファイルを自由に作成できる
ことになってしまうので、普通の UNIX ではできません。

root で展開するのもひとつの方法ですが、Solaris では /etc/system で
    rstchown=0
と設定することで一般ユーザが chown できるようになります (セキュリティを
犠牲にするので、わたしはしません)。そうしておけば、一般ユーザが tar xfp
すると、他ユーザが所有するファイルを作成できるかもしれません (試してません)。

No. 4380 # DNS勉強中 2005/11/11 (金) 01:20:02
>>4379 68userさん
ご返答をいただきありがとうございます。

length の件ですが、もうしわけありませんが一次資料は存じておりません。
今回のプログラムで私が一次資料として利用したのが、
こちらのサイトということもありまして(^^;。

それとごみデータの件ですが、おっしゃりたいことは分かりました
(まだソース上では試しておりませんが)。
送信するデータ量で調整すると言う発想は出てきませんでした。
明日にでもその部分は組めそうな気がします。
どうもありがとうございます。

後、構造体の中に構造体を書くスタイルも勉強になりました。
このスタイルを取り入れた形で動かせるよう努力してみたいと思います。

それとライセンスの件ですが、このソースの中に書かれている関数
( make_domain, parse_response, get_domain )や
出力結果を見ていただければ分かるかと思いますが、
resolver-1.pl を C に移植しようとしたものがこのソースです。
移植作業自体は私が行いました。
もっとも pack とかの動作をどうやって C で再現すればよいのか等
わからない事が多かったので、
resolver-1.pl の出力結果や etherealの結果から
自分なりに解釈して組んでいる部分はありますので、
完全移植は出来ておりません。

そのため、このサイトで有効利用していただけるのでしたらありがたいです。
私がこのサイトから学んだことを還元できればうれしいですし、
修正したソースを見て勉強させていただけたらと思います。

とりあえず自分で組んだソースなので、
現在このソースが抱えている内部的な問題とか分かる範囲で明日まとめてみます。
実際にソースを読んでいただいているようですが、
情報を提供しないよりは、提供した方が良いかなと思いますので。

No. 4381 # 68user 2005/11/11 (金) 03:06:30
>>4380 DNS勉強中
> length の件ですが、もうしわけありませんが一次資料は存じておりません。
了解しました。一次資料を発見されたら、ご教示いただけると幸いです。

> そのため、このサイトで有効利用していただけるのでしたらありがたいです。
ありがとうございます。C でのサンプルソースとしてぜひ使わせていただければ
と思います。ただ、今は時間がとれないので、半年後とか 1年後、もしかしたら
数年後となるかもしれません。その点はご了承ください。

> resolver-1.pl を C に移植しようとしたものがこのソースです。
そうなんですか。わたしはこんなわかりやすいソースを書いた覚えはないんですが、
とても可読性が高いように感じます。

なぜでしょうね? コメントが充実しているから? わたしは「適切な変数名・関数名を
使用していれば、あまりコメントを書かなくても問題ない」という考え方だった
のですが、ちょっと考えが変わりそうです。

No. 4382 # 68user 2005/11/11 (金) 03:08:04
人材募集です。ご興味を持たれた方はお気軽にどうぞ。
    http://X68000.q-e-d.net/~68user/tmp/job.html

No. 4383 # DNS勉強中 2005/11/11 (金) 09:44:05
>>4381 68userさん
今回作成したソースは resolver-1.pl を参考に書かせていただきましたが、
どちらかというと書かれているソースではなく、
書かれているコメントを参考に作成しました。
理由は単に perl が分からないからです(^^;。

ただ、コメントから行っている動作が分かれば、
それを C で実現するにはどうすればよいかを考えれば良いのかなと。

以上のことより、 resolver-1.pl と同じような事を実現していても
ソース自体は似つかないものになっているかもしれません。
と言いますか perl が読めないので「似てるか否かわからない」
というのが実際のところです(^^;。

後、ソースを利用する/しない、時期などはすべてお任せします。

それとごみデータの件ですが、下記の記述でうまくいきました。
sizeof(DNS_Send) - sizeof(DNS_Send.QUERIES) + count + 4
アドバイスを頂き、どうもありがとうございました。

No. 4384 # DNS勉強中 2005/11/11 (金) 11:15:02
投稿した DNS のソースコードの問題点 その1

( Linux版のみ )照会タイプと照会クラスを共に指定しないと、
照会クラスに PWD=/root/src が挿入され (null にならず)、エラーになってしまう。

その部分にだけ絞ったサンプルソース( Windows/Linux 兼用 )
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1057.c
windowでの実行結果
argv[0] = C:\src\argv.exe(←これは私の実行ファイル名です)
argv[1] = (null)
argv[2] = (null)
argv[3] = (null)
argv[4] = (null)

linuxでの実行結果
argv[0] = ./test24(←これは私の実行ファイル名です)
argv[1] = (null)
argv[2] = PWD=/root/src
argv[3] = HOSTNAME=gifu-vm-35
argv[4] = LESSOPEN=|/usr/bin/lesspipe.sh %s

思いつく回避方法は、
1,照会タイプを入力必須にする。
2,照会クラスのみ引数ではなく、別途入力するようにする。
3,照会クラスの先頭3文字が PWD なら INTERNET に置き換えてしまう。
と言った所ですが、1,2は resolver-1.pl にくらべ多く入力する必要があり、
3は環境依存度が高いかも知れません。
このサイトで公開される際は、この部分は何かしか改善を加えた方が良いかもしれません。

No. 4385 # 68user 2005/11/11 (金) 14:01:36
>>4384 DNS勉強中
> 後、ソースを利用する/しない、時期などはすべてお任せします。
ありがとうございます。有効に活用させていただきたいと思います。再配布
ライセンスやクレジット表記について要望があれば、今のうちに承っておきます。

> printf("argv[0] = %s\n", argv[0]);
> printf("argv[1] = %s\n", argv[1]);
C の話になりますが、argv の要素数は argc を参照しなければいけません。領域を
超えた部分に何が入っているかは環境依存です。Windows で NULL が入っているのは
たまたまです。OS のバージョンやコンパイラを変えたらどうなるかわかりません。

Linux の場合は、環境変数を保持している environ の環境にアクセスしていますが、
これもたまたまです。

# この領域は、普通は int main(int argc, char *argv[], char *envp[])
# などとアクセスします。

よって、
    char query_type[256];
    char query_class[256];
    if ( argc >= 4 ){
          strcpy(query_type, argv[3]);
    } else {
          strcpy(query_type, "A");
    }
    if ( argc >= 5 ){
          strcpy(query_class, argv[4]);
    } else {
          strcpy(query_class, "INTERNET");
    }

    char *query_type = "A";
    char *query_class = "INTERNET";
    if ( argc >= 4 ) query_type = argv[3];
    if ( argc >= 5 ) query_class = argv[4];
などとするのがよいでしょう。

No. 4386 # DNS勉強中 2005/11/11 (金) 17:12:48
>>4385 68userさん
ライセンスなどは不要です。

それと引数の御指導どうもありがとうございます。
よく理解でき、Linuxでの動作も確認いたしました。
おかげで問題点が1つ解消されました。

後、パディングが心配との事で、構造体を書いていただきましたので、
それを参考にソースを書き直してみました。

Windows版
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/1058.txt

ただ
        struct DNS_Query {
                ....
        };
の .... の意味するところが分からなかったので
ここは私なりに解釈して記述しています。
またstruct DNS_Query *q;の必要性が分からなかったので、これは記述していません。

しかし、
> 問い合わせ内容を DNS_Question に構築し、
> 送信時にDNS_Packet にコピーして send すると思います。
の部分は実現したつもりです。

もっともパディングが心配という事が良く理解できていないので、
果たして組んだソースが意図を汲んでいるかどうかは自信がありません。

後このソースの問題点ですが、いま自分が気づいているところでは2点あります。
変数 search と 変数 DNS_question.flag の保守性です。
動作自体には問題はないと思います。
ただこれは自分で直せる気がするので週末にでも直したいと思います。

No. 4387 # Yuusuke 2005/11/11 (金) 18:06:11
>>4379 68user
ありがとうございます。
おかげさまでつい先ほど本番サーバへ移行が完了しました。
本番サーバではリモートコマンドはできないポリシーになっていたようなのでftp
でtarファイルを転送し、rootで展開しました。

No. 4388 # 68user 2005/11/12 (土) 14:20:21
>>4386 DNS勉強中
> ここは私なりに解釈して記述しています。
わたしの意図どおりの実装になっています。

> またstruct DNS_Query *q;の必要性が分からなかったので、これは記述していません。
        struct DNS_Question {
            short id
            short flag;
            short QDCOUNT;
            short ANCOUNT;
            short NSCOUNT;
            short ARCOUNT;
            struct DNS_Query *query;
        };
と書くと、DNS_Question というものは
    「id・flag・{QD,AN,NS,AR}COUNT・DNS_Query から成り立つ」
という関係がソース上に明示されます。プログラムは「データ構造+アルゴリズム」
ですので、正確なデータ構造を最初に明示しておけば、ソースを理解しやすくなる
ということです。

また、こうしておけば、
    main(){
        make_question(&DNS_question);
    }
    make_question(DNS_Question *question){
        question->id = ...;
        question->flag = ...;
        make_query(question->query);
    }
    make_query(DNS_Query *query){
        query を作成
    }
というふうに、変数の受け渡しがすっきりします。

ただ、フラットな構成の方がわかりやすい場合もありますので、ケースバイケースかと
思います。

> もっともパディングが心配という事が良く理解できていないので、
わたしの環境では
    int main (){
        struct {
            char a[1];
            int b;
        } hoge;
        printf("%d\n", sizeof(hoge));
    }
の結果は 8 になります。構造体のメンバ間にどれだけのパディングが入るかは
環境依存なので、パディングが入らないことを前提としたコーディングをするのは
怖いなぁ、ということです。

> 後このソースの問題点ですが、いま自分が気づいているところでは2点あります。
> 変数 search と 変数 DNS_question.flag の保守性です。
なるほど、学校の課題にも関わらず細かな部分の完成度を高めたいというのは
素晴らしいですね。余計なお世話かもしれませんが細かいところまで見てみました。

> #include <netdb.h>
必要なヘッダファイルを include していません。その結果、引数チェックが
行われず、戻り値は int として扱われているはず。

このことに気づかないということは、警告オプションを有効にしていないと推察
されます。gcc であれば -Wall オプションを付けると幸せな人生を送れます。

> char *make_domain(char *domain_name);
プロトタイプ宣言で変数名は不要で、
    char *make_domain(char *);
でよいです。別に引数名を記述しても動作には影響ないですが、引数名を変更
したときに直し忘れてズレが出るので、わたしは書きません。/usr/include/*.h
にも書いてないです。

> fprintf(stderr, "Error: Socket作成失敗\n");
なぜ失敗したのかがわからないため、システムコールのエラー時には errno を
出力しましょう。わたしは
      fprintf(stderr, "Error: Socket作成失敗。errno[%s]\n", strerror(errno));
とするのが好みですが、perror(3) などを使う人も多いです。

bind 失敗時も同様。エラーメッセージが
    Bind error
であるのと
    Bind error [Address already in use]
と表示されるのでは、対処時間に大きな差が出ると思います。

ちなみに gethostbyname(3) のエラー処理が抜けています。gethostbyname は
ソケットまわりのシステムコール呼び出し時のエラー以外にも、データ内容の
エラーが発生する可能性があるので herror(3) や hstrerror(3) を使います。

> return -1;
main で戻せる値は 0〜255 です。あと、exit と return が混在しているのが
気になります。

> questions = two_bytes(int_buf[search], int_buf[search+1]);
> search += 2;
two_bytes・four_bytes のインタフェースがいまいちです。データ取得と
インクリメントを別々に行うと、インクリメント忘れ・インクリメントミスが
発生する危険性があります。

たとえば
    questions = two_bytes(&int_buf, &search);
とインタフェースを変え、
    int two_bytes(int *int_buf, int *search){
          int sum;
          sum = int_buf[*search] * 16 * 16 + int_buf[*(search+1)];
          *search += 2;
          return sum;
    }
とすればデータ解析とインクリメントを同時に行えます。ここまでくれば、
      struct DNS_Response {
          char data[10000];
          int int_data[10000];
          int pos;
      };
という構造体を作った方がよいかもしれません。

上記と関連しますが、
    additional = two_bytes(&int_buf[search], &search);
    search += 1;
これは一見すると謎なコードです。2バイト取得しているのに 1バイトしか進めて
いないので、わたしはしばらく悩みました。結局は get_domain() の先頭で 1バイト
進めているから問題ないのですが、直感に反するコーディングだと思います。

> int conv_class(char *class){
> switch (class) {
> case 1: printf("1 (INTERNET)\n"); break;
> case 2: printf("2 (CSNET)\n"); break;
> case 3: printf("3 (CNAME)\n"); break;
> case 4: printf("4 (HESIOD)\n"); break;
> case 5: printf("5 (ANY)\n"); break;
> }
わたしなら、
    typedef struct {
        char name[100];
        int code;
    } codelist_t;
としておいて、
    int conv_class(char *class){
        codelist_t class_list[] = {
            {"INTERNET", 1},
            {"CSNET", 2},
            {"CHAOS", 3},
            {"HESIOD", 4},
            {"ANY", 5},
        };
        for ( i=0 ; i<sizeof(class_list)/sizeof(class_list[0]) ; i++ ){
            if ( strcmp(class, class_list[i].str) == 0 ){
                return class_list[i].code;
            }
        }
と直します。class_list は void class_print(int class) で共用してもよいでしょう
(resolver-1.pl と同じやり方)。

> memset(&client, '\0', sizeof(client));
> host[j] = 0; /* 最後に0を代入する */
memset は 0 で埋めて、host[j] は '\0' で終端すべきです。文字終端の '\0' と
値としての 0 を区別しておくと、後から読んだ人に意図が伝わりますので。


あとは命名について。関数名は動詞、変数名は名詞という基本ルールがあるよう
ですが、徹底されていないように思います。

いまいちだと思う関数名:
    int domain_count(char *);
        → get_domain_length などが適切では。
    int end_domain(int, int *);
        → is_XXX とか check_XXX がよいのでは。
    int resource_data(int *, int, int, char *);
        → 名詞になっている。しかし他の hogehoge_print より一段レベルが高いので、
              混同しないような命名をしたいところ。
    void conv_time(int);
        → 「変換」といいつつ実際に行っているのは「出力」。

いまいちだと思う変数名:
    int search;
        → 動詞に見える。pos あたりでいいのでは。
    int questions;
    int answer;
    int authority;
    int additional;
        → s が付いていたり付いていなかったり。あと、この変数の本質は「個数」で
              あるはず。であれば question_count とか question_num などにしたい。
    int flag = 0;
        → flag や tmp という変数名が許されるのは変数スコープが 5行以内の場合
              (わたしの中では)。それ以上ならもう少し長い名前を。

> int resource_data(int *int_buf, int search, int max, char *print);
    int max
        → record_num あたりで。
    char *print
        → record_name あたりで。

> int domain_count(char *argv)
argv は渡す側の変数名であって、この引数の本質は「ホスト名」であるため、
    int domain_count(char *hostname)
    int domain_count(char *host)
などがよいと思います。


と、わたしならこう書くという部分はあるものの、それでも可読性が高い
と感じました。たとえば codelist_t は保守性は高いのですが、ぱっと見
読みやすいのは case 文の羅列です。勉強用のソースであれば、下手に
構造化しすぎることなく、あえてベタ書きしたほうがいいのではないかと
考え始めています。

あと、hoge_print 関数も、わたしはこういう書き方をせずに
      char *a_record_print(int_buf, search);
と文字列を返すほうですが、メモリ確保を行うのは呼び出し側か、関数の
中で static に持つか、など悩ましいです。すっぱり割り切って関数内で
printf するのも、保守性はともかく可読性は悪くない、と思いました。

あと、

    - two_bytes・four_bytes という関数は便利で読みやすい。
    - int_buf にコピーするのは、型変換のバグを避ける手法としては
        優れているのかも (ちょっと逃げっぽいけど)。
    - perl 版の可読性を落としているのはやはり pack。num2bin などの
        関数を作り、直接 pack を呼ぶのは避けた方がよいのかも。
    - やはり C は構造体がすっきり書けるのがよいところ。perl の場合、
        ハッシュだとタイプミス耐性がないし、Class::Struct だとインクリメント
        が面倒だし、package を作るのは大げさ。

などといろいろと思うところはありました。自分が書いたものを他人が
リライトすると、いろいろと気づくことがあっておもしろいですね。

いろいろ偉そうに書きましたが、指摘したことは当ページでは全然実践できて
いません (エラーチェックは甘いし、herror(3) は使っていないし、resolver-1.pl
ではデータ取得とインクリメントを別々に行っているし)。その辺はご容赦ください。

No. 4389 # DNS勉強中 2005/11/12 (土) 17:37:13
>>4388 68userさん
いろいろと細かい点までアドバイスをしていただきましてありがとうございます。
大変勉強になります。

全てに指摘点に対しご回答差し上げたいのですが、
まだ指摘された部分の修正作業を行っておりませんので、
一通り読ませていただき、気づいた点について記述させていただきます。

まず return と exit の混在ですが、
これは conv_type 関数や conv_class 関数の部分だけを
指した指摘でしょうか。
それとも exit を一つも使わない方が良いという事でしょうか。
return と exit の混在のデメリットが分からなかったので。

後、変数 search ですが、仰るとおりインターフェースがいまいちです。
何故なら現在位置を返す関数と返さない関数が混在しているからです。
ここの処理がうまく思いつかなかったので search += 2; で逃げていました(^^;。

そして変数 search の大きな問題が仰るとおり
> additional = two_bytes(&int_buf[search], &search);
> search += 1;
です。
ここは作った当人で無いと分からないですよね(^^;。
その理由は、開発途中で方針を変更してしまったためです。
そのため現在位置は
・解析し終わった部分の、次の部分の先頭に現在位置を合わせている所
・解析し終わった部分の末尾に現在位置を合わせている所
の2パターンが発生してしまいました。
その代償が search += 2; と search += 1; の混在です。
ここは人に解析してもらう際にはまずいので修正します。

あと host[j] = 0; ですが、ここでは www.livedoor.com というドメイン名を
3www8livedoor3com0(数字の部分は文字ではなく、文字コード)に変換しているのですが、host[j] = 0; は ドメインの最後に文字コードの 0 を連結する
と言う意味で記述しました。
何となく思ったのですが、 3www8livedoor3com0 の最後の 0 は終端という意味かな。
そう考えると仰られている意味が分かりました。
その部分に関しては、記述ミスと言うより、私の理解が間違っていたのかなと思います。
それと、int_buf は完全に逃げです(^^;。
ここの部分のうまい処理が思いつきませんでした。


他の指摘された部分につきましても、順次修正して良いものを作りたいと思います。
お忙しい中、いろいろご指摘いただきありがとうございます。

No. 4390 # 68user 2005/11/12 (土) 23:12:39
>>4389 DNS勉強中
> まず return と exit の混在ですが、
main から抜ける際に return と exit が混在していることを指したつもりでした。

下請け関数から exit するのは、狙っているのなら別にいいんじゃないかと思います
(課題のプログラムですし)。変な値がやってきたら終了してしまうようでは、本格的な
運用で使うことはできませんが、

    - 本格的な運用では使えないことを認識している。
    - どういう要求が出てきたときに問題が起こるかなんとなく想像できる。
        たとえば web サーバのログから IP アドレスを拾って、複数の名前解決を
        高速に行うプログラムを作りたいという要求があったとすると、この
        プログラムではひとつでも変なレスポンスがくると exit してしまうので
        実運用には耐えられない。
    - 本格的な運用で使用する場合は、どこをどういうふうに書き換えればよいか
        だいたい把握している。

なら問題ないと思います。

> return と exit の混在のデメリットが分からなかったので。
わたしの中では以下のようなルールにしています。

    1. 基本的に main まで戻る。エラー発生時の情報出力を行うことを考えると、
          各関数の役割分担が明確になるから。

    2. 例外として、引数解析エラー表示の usage 関数内では exit してよい。
          理由は、処理が始まっておらず後始末が不要であることと、usage は
          数箇所〜数十箇所から呼ばれる可能性があり、呼び出し元での exit
          忘れが怖いこと。
              if ( argv[i][0] != '-' ){
                    usage();
                    exit(1); /* これを書き忘れると処理が続行してしまう */
              }

1 の詳細は以下のとおり。

    今回のように 1件だけのデータを処理する場合は、変な値がきたときに
          ほげフラグが 1〜5 の範囲外です
    などと出力すれば問題ないが、 一度に複数のデータを処理するバッチの場合は
          ほげフラグが 1〜5 の範囲外です。受注番号[%d] レコード番号[%d] 顧客番号 [%d]
    などとより多くの情報を出力しないと、どのデータがおかしいのか特定できない。

    とはいえ、下請け関数である 文字列→コード変換関数に、
          conv_type(query_type, order_no, rec_no, customer_no);
    などとエラー発生時に備えて各種情報を渡すのは変。エラー出力用のグローバル変数を
    作って
          err_order_no = order_no;
          err_rec_no = rec_no;
          err_customer = customer_no;
          conv_type(query_type);
    とする、なんてのも馬鹿馬鹿しい (後者はたまに見かけてイラッときますが)。

    となると、
          int main(){
              ret = file_main();
              if ( ret == -1 ){
                  logging("エラー発生。処理中断・ロールバックし、全データを元に戻します");
                  /* 後始末を一箇所にまとめる */
              }
          }

          int file_main(){
              fp = fopen(filename[i], "rw");
              while (1){
                  fgets(fp, buf, sizeof(buf));
                  ret = hoge_main(buf);
                  if ( ret == -1 ){
                      logging("hoge_main でエラー発生。ファイル名[%d] 行番号[%d]", filename[i], line);
                      return -1;
                  }
              }
          }

          int hoge_main(char *buf){
              type = conv_type(query_type);
              if ( type == -1 ){
                  logging("query_type に変換に失敗。受注番号[%d]", rec_no):
                  return -1;
              }
          }

          int conv_type(char *type){
              if ( 異常値 ){
                  logging("type が異常値 [%s]", type);
                  return -1;
              }
          }
    として main まで戻るのが現実的。conv_type はファイル名だの受注番号だの
    責任範囲外のことを知らなくてもよいが、最終的にはエラーリカバリに必要な
    情報が揃う。

Java などのいまどきな言語であれば例外を使うべきだろうと思います。


> 3www8livedoor3com0(数字の部分は文字ではなく、文字コード)に変換して
> いるのですが、host[j] = 0; は ドメインの最後に文字コードの 0 を連結
> すると言う意味で記述しました。
戻り値を
      strcpy(DNS_Send.QUERIES, make_domain(argv[2]));
と文字列として扱うのであれば、末尾は文字終端 '\0' であるべきで、
      host[j] = 0;
より
      host[j] = '\0';
にすべきという意味で書きましたが、たしかに文字列終端でもあり、DNS 的な
0 終端でもあるわけで微妙なところですね。

バイナリ列とみなして長さを明示的に管理し、strcpy のかわりに memcpy を
使うか、あるいは動作的には問題ないのでコメントで補足しておくか、あるいは
修正は不要なのか…。

> それと、int_buf は完全に逃げです(^^;。
いいんじゃないでしょうか。「バグを出さない」ということを第一目的とするなら
アリだと思います。わたしなどいまだに char と unsigned char あたりの暗黙の
型変換ではまったりしていますので、キャストがちりばめられているソースだったら
解読に苦労していたかもしれません。

ちなみに単なる「char」が signed であるか unsigned であるかは環境依存です。
とはいえ、わたしは一般的な UNIX しか知らないので、char が unsinged char
である環境は見たことはないですが。

No. 4391 # 68user 2005/11/12 (土) 23:36:45
>>4389 DNS勉強中
あと、さらに細かいことをひとつ。インデントは正確につけましょう。フラグ表示
の部分をわかりやすくするために、ひとつ余計にインデントしていますが、
      {
          フラグ表示
      }
と、ブロックで囲めばすみます。

インデントはプログラマがつけるものではなくエディタが勝手につけるものであり
(emacs の M-x indent-region などで)、もしエディタが変なふうにインデントして
しまったら、それは括弧の過不足や文字列の閉じ忘れが原因、などと気づくことが
できます (python などは除く)。

# というわたしのポリシーはなかなか理解してもらえない。なぜ手でインデントを
# 付ける人が多いのだろう (って、素の vi やメモ帳を使ったりするからだが)。
# めんどくさくないのかなぁ。

No. 4392 # DNS勉強中 2005/11/14 (月) 00:18:28
>>4388 68user
>>4390 68user
>>4391 68userさん
今日は上記3レスでアドバイスいただいた内容についてある程度修正したり、
理解に努めておりました。

・ struct DNS_Query *query; の必要性について理解いたしました。
確かに仰られるとおり、ソースが理解しやすくなると思いました。
そのため、その部分は修正しました。
(ただ make_question, make_query との関係上、一部修正しております)。
また、make_question と make_query を作成することにより、
main 部の記述を減らし、ソースを読みやすくしました。
ただ、記述していただいたとおりに作れなかったので、メイン部に
    make_question(&DNS_question);
    count = make_query(&DNS_query, argc, argv[2], argv[3], argv[4]);
と2つにわけて記述しております。

・ パディングについても理解いたしました。
確かに私の以前のソースはパディングが入らない前提で組んでありました。
やっと意図されたことが分かりました(^^;。

・ /usr/include/bfd.h をみて、
プロトタイプ宣言について仰られていることを確認・理解し、修正しました。

・ perror を用いエラー処理を追加しました。

・ 抜けていた gethostbyname のエラー処理を追加しました。
ただし、 herror や hstrerror を Windowsで使う方法が分からなかったので、
とりあえず perror を使っております。

・ return と exit の混在を解消しました。
それにともない、 main に戻らずに終了していた所を、
main に戻って終了するように変更しました。
またそれらしいエラー情報を出力するように変更しました。

・ two_bytes の記述変更について理解いたしました。
アドレス渡しで現在位置を変更して、
戻り値で2バイトの値を取得する方法は大変参考になりました。
確かに、教えていただいた記述の方が何かと便利ですので、
ほぼ同じソースを移植させていただきました。
それに伴い、謎の search += 1; を修正しました。
また four_bytes も同様にソースを変更しました。
この作業を実施したことにより、
search += 2; や search += 4; を大幅に減らすことが出来ました。

・ conv_type, conv_class, class_print, type_print を
codelist_t を使用する形に変更しました。
ただし、 void class_print(int class) を用いた共用の記述の仕方が
分からなかったので、
codelist_t {class, type}_list[] = { ... };をグローバル化して共用しています。
また、 qr_print, opcode_print, aa_print, tc_print, rd_print, ra_print,
rcode_print も同様に codelist_t { ... }_list[]化しました(こちらはローカル)。

・ 0 と \0 の混在を修正しました。

・ 変数名や関数名の命名を修正しました。

・ フラグ部分のインデントを変更しました。
ブロックで囲むと言う発想が出てこず、
かといって、インデントなりコメントで上下を囲むなどしないと、
のちのち分からないだろうなと思い、
インデントしてしまったのですが、
ブロックで囲むと言う方法が教えていただき、大変参考になりました。


とりあえず今日修正できたところは以上です。
上記以外の部分についてはまだ手をつけておりません。
他に、今まで教えていただいた事を他の部分にも流用できないか、
ソースを一通り読み直してみて調べてみようと思います。
また search を触ったことのより、ある程度検証をする必要があるのかなと思います。
月曜日は予定が入っているので、まとめるのは難しいかも知れませんが、
火曜日くらいにある程度まとめて一度アップしてみようと思います。

いろいろ参考になるアドバイスをいただきまして、ありがとうございます。

No. 4393 # DNS勉強中 2005/11/14 (月) 09:44:17
to 68userさん

さっそくですが、IPv6 のアドレス省略について
双方のプログラム(resolver-1.pl, 1058.txt)に
バグがあるかも知れないのでご報告します。

一例として、 198.41.0.4 www.yahoo.co.jpと入力して、
{A, B, C, D, E, F}.DNS.jpを表示させたとき、
追加情報の F.DNS.jp の出力結果は下記のとおりになります。

resolver-1.pl
2001:2F8::100::153

私の出力結果
2001:2f8::100:0:0:0:153

ちなみにEtherealの出力結果は下記のとおりです。
2001:2f8:0:100::153

IPv6 のアドレス省略表記に関する説明を下記のサイトで拝見したのですが、
http://www.soi.wide.ad.jp/iw2001/slides/04/04-1/53.html
そこには IPv6 のアドレス表記に関して2つの原則が書かれていました。
1,【連続する】0 のブロックは省略できる。
2,省略できるのは【1ヶ所】だけ。

そして出力結果から推察するに、
resolver-1.pl では、原則の1, 2共に満たしてないように見受けられます。
perl が分からないので想像ですが、
resolver-1.pl では 0 を見つけたら即座に :: に置き換え、
何回でも省略が使用できるように組んであるのかなと思われます。

私の方では、一度省略を使用したら、二度と使えないようには組んでいるのですが、
0 は即座に :: に置き換えております。
そのため 0 を見つけたら、次の場所を見て、
・次の場所も 0 なら :: に置き換える
・次の場所が 0 で無ければ、 0 を出力する。
というコードを追加しないといけないかもしれません。

勘違いでしたらすいません。

No. 4394 # 68user 2005/11/15 (火) 01:45:04
>>4393 DNS勉強中
ありがとうございます。

とりあえず TYPE=TXT の件と IPv6 の件を bugid20・21 として登録しました。
    http://x68000.q-e-d.net/~68user/bugnote/bugindex.php?projectid=1


ちなみになぜわたしが web を更新しないのは、解説文からソースへの
リンク方法が
    http://x68000.q-e-d.net/~68user/cgi-bin/cvsweb.cgi/public_html/net/org/resolver-3.html?rev=1.11&content-type=text/x-cvsweb-markup
のように
    :preinclude 21-106
などと行番号で指定しているため、修正が非常に面倒であるからです
(まぁただの言い訳なのですが)。

+10 などの相対指定にしようかとか、
      m/bind\(/
などと文字列で引っ掛けようかとか迷いつつここまで来てしまいました。
ご指摘を頂いたことについては大変感謝しておりますが、修正が遅いのは
なにとぞご容赦ください。

No. 4395 # 68user 2005/11/15 (火) 01:55:14
>>4392 DNS勉強中
> ただし、 void class_print(int class) を用いた共用の記述の仕方が
> 分からなかったので、
> codelist_t {class, type}_list[] = { ... };をグローバル化して共用しています。
一般的には、codelist_t を扱う関数を別ソースにし、ソース先頭で
    static codelist_t class_list[] = { ... };
と配列を宣言して、conv_class()・class_print() でその配列を使用
します。static をつければ外部ソースからアクセスできないので、
隠蔽できます。

ただ、複数ファイルに分けると、ヘッダファイルが必要だったり Makefile を
書きたくなったりするので、サンプルであれば分ける必要はないかもしれません。


それはそれとして複数のソースから構成される場合に、グローバル変数の
宣言をヘッダファイルで一元管理する方法をご存知なければ、一度書いて
みるとよいでしょう。

      --- var.h ----
      #ifdef THIS_IS_MAIN
      #define GLOBAL
      #else
      #define GLOBAL extern
      #endif
      GLOBAL class_list[] = {...};
      
      --- main.c ---
      #define THIS_IS_MAIN
      #include "var.h"

      --- sub.c ---
      #include "var.h"

こんな感じです。

Prev< No. 4295〜4395> Next  [最新発言に戻る] [過去ログ一覧]