>> sprintf(buf,"文字列¥0”);
>> と記述する人が、(某所に)沢山います。
え~、確か文字列リテラルって「ヌル文字('¥0')でターミネートされた文字列」
で、「""」で囲むと問答無用(?)で文字列リテラルになってしまうはず。
故に、全く sprintf(buf,"string¥0"); は意味なしだと思うのですが…。
試しにこんなコードを書いてみました。
#include <stdio.h>
int main()
{
char buff[16];
int i;
FILE *fout;
for( i = 0 ; i < sizeof buff / sizeof(char) ; i++)
buff[i] = 0x20;
sprintf(buff , "012345¥0");
fout = fopen( "hogehoge.bin" , "wb+" );
fwrite( buff , sizeof( char ) , sizeof buff / sizeof(char) , fout );
fclose(fout);
return 0;
}
ここで、はき出されたバイナリファイルは
30 31 32 33 34 35 00 20 20 20 20 20 20 20 20 20
このようになっていました。あ、コンパイラはBCC5.5です。
本当のところどーなんでしょーか > 識者のみなさま
/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
/ hik...@mrh.biglobe.ne.jp /
/ 江畠 隆行(Ebata,Takayuki) /
/ 東京都調布市在住 /
/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
> 何で、¥0をわざわざ書くのでしょうか?
初めて知りました。
全然意味無いと思いますよ。
sprintf(buf,"文字列\n");
ならわかりますが…。
あ、わかった。
全角の¥0を付けたいのかな…。
tabeさんの<9tdpfv$oll$1...@bgsv5905.tk.mesh.ad.jp>から
> sprintfで
> sprintf(buf,"文字列¥0”);
> と記述する人が、(某所に)沢山います。
たとえば sprintf(buf, "012345"); としたときに、
bufの内容は 0x30 0x31 0x32 0x33 0x34 0x35 ときて
最後に 0x00がつくんだよ、というのを忘れないようにしておきたい、
という想いが込められているように思いました。
なんとなく固定長項目文化の影響を感じます。
--
P.S.
投票はお済みですか? > news:9t8jbi$i...@utogw.gssm.otsuka.tsukuba.ac.jp
詳細は http://www.t78.org/fj-election/ にて
Windows のプログラムではそのような表記が必要になったりします。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/commdlg_1hma.asp
--
red brick
This message is reply to Ebata Takayuki - san
(Subject was : Re: sprintf(buf,"\0");の¥0の意味。)
Message-ID: <20011121004015.79...@mrh.biglobe.ne.jp>
in 20 Nov 2001 15:40:15 GMT ...
> え~、確か文字列リテラルって「ヌル文字('\0')でターミネートされた文字列」
> で、「""」で囲むと問答無用(?)で文字列リテラルになってしまうはず。
>
> 故に、全く sprintf(buf,"string\0"); は意味なしだと思うのですが…。
> 試しにこんなコードを書いてみました。
sprintf(buff, "012345\0");
だと、"" の中のデータは、(ターミネータを含めて)
0x30 0x31 0x32 0x33 0x34 0x35 0x00 0x00
になります。
ちなみに、"" の場合は
0x00 だけ
あとは、sprintf() の方が(に限らず) '\0' をターミネータとして
認識しているので、最初の 0x00 までしか処理していないので、
sprintf(buff, "012345\0");
を通過したあとの、buff には、0x00 が1個しかないだけですね。
私は以前、「ターミネータは必要」という強迫観念で、"~\0" と
書いていたことがあります。
---
_/ -- Last 5071 hours until 2002 World Cup final ---------------------
_/ FUJIHARA Keiichi
_/ E-Mail : na...@sep.email.ne.jp <or> na...@qua.net
_/ URL : http://www.asahi-net.or.jp/~ig5k-fjhr/
--------------------------------------------+----- Luna Phase 5.79 ---
PGP FingerPrint = 7CC3 4F95 8CC7 87D3 7178 C348 CD65 7F08 D68F 69F6
red brickさんの<9tf8f2$j93$1...@news3.dti.ne.jp>から
>>> sprintf(buf,"文字列¥0”);
>>> と記述する人が、(某所に)沢山います。
>>
>>たとえば sprintf(buf, "012345"); としたときに、
>>bufの内容は 0x30 0x31 0x32 0x33 0x34 0x35 ときて
>>最後に 0x00がつくんだよ、というのを忘れないようにしておきたい、
>>という想いが込められているように思いました。
>
> Windows のプログラムではそのような表記が必要になったりします。
>
>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/commdlg_1hma.asp
これはAPIにわたす構造体のメンバがWindows 2000以降追加されたので、古い
ヘッダファイルを使うときは自分で何バイトか穴埋めしなければいけないです
よ、ということでしょうか?新しいヘッダを使ってコンパイル、
とかではなく。
# そんなことをしなくても、メンバの lStructSizeに sizeof (OPENFILENAME)
# をセットしておけばいいように読めるような…
## なかなか豪快な仕様だなあ…
>> Windows のプログラムではそのような表記が必要になったりします。
>>
>>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/commdlg_1hma.asp
>
> これはAPIにわたす構造体のメンバがWindows 2000以降追加されたので、古い
> ヘッダファイルを使うときは自分で何バイトか穴埋めしなければいけないです
> よ、ということでしょうか?
じゃなくて、lpstrFilter の終端が \0\0 であるということでしょう。
なんでこの話題の中で持ち出されたのかは不明ですが。
--
みやざき
sh...@miyazaki.email.ne.jp
In article <9tfgop$kr5$1...@news01cj.so-net.ne.jp>
Jun Taniguchi <tani...@tb3.so-net.ne.jp> writes:
> > Windows のプログラムではそのような表記が必要になったりします。
> >
> >http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/commdlg_1hma.asp
>
> これはAPIにわたす構造体のメンバがWindows 2000以降追加されたので、古い
> ヘッダファイルを使うときは自分で何バイトか穴埋めしなければいけないです
> よ、ということでしょうか?新しいヘッダを使ってコンパイル、
> とかではなく。
lpstrFilter (lpstrCustomFilter) ではないでしょうか. pairs of (a pair
of) null-terminated filter strings とありますから,
"a\0b\0c\0d"
とか
"foo\0bar"
とかいうことでは.
--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp
=> やっぱり、上の方が思いが強いのでしょうか?ね。
怠け者の私は、
打ち込み量が少なくて、
処理速度が速くて
メモリ消費も少ない
下の方を、選びますが。
何で、上の方を選ぶんだ労??(適切な誤字)
> なんとなく固定長項目文化の影響を感じます。
苦労する事が正しいと言う日本文化を感じます。?
以上
Kazuo Fox Dohzonoさんの<9tfqmf$2ouo$1...@news2.rim.or.jp>から
>lpstrFilter (lpstrCustomFilter) ではないでしょうか. pairs of (a pair
>of) null-terminated filter strings とありますから,
はい、確かにそのようです。みやざきさんのご指摘もあわせると、メンバ
lpstrFilterには "Text Files\0*.TXT;*.DOC\0\0" のように指定することに
なっているようですね。勉強になりました。
# ちょっと趣味にはあわない方式 (^^;)
ふと、昔がんばって読もうとしたLSI-C 86のcppを思い出しました。オプショ
ン -j で、画面に出力するメッセージを英語と日本語に切り替えることができ
るのですが、そのためにまず
char MSG_cntopnX[] = "can't open: '%s'\0"
"ファイル %s がオープンできない";
char MSG_incnst[] = "#include too nested\0"
"#include のネストが深すぎる";
とメッセージを定義しておいて、メッセージを利用するときは
int Jap;
char *chooseMsg(char *s)
{
return (Jap ? s + strlen(s) + 1: s);
}
とすることで、
fprintf(stderr, chooseMsg(MSG_cntopnX), filename);
などと書いておけばあとは Jap の値にあわせて出力文字列を変更できるとい
うもので、見たときは目から鱗がぽろりと落ちました。
> ふと、昔がんばって読もうとしたLSI-C 86のcppを思い出しました。オプショ
> ン -j で、画面に出力するメッセージを英語と日本語に切り替えることができ
> る
--
#if defined (ldef) || defined (kdef) || defined (mdef)
ldef (english)
ldef (japanese)
kdef (err_open)
mdef (
"can't open: '%s'",
"ファイル %s がオープンできない"
)
kdef (err_include_nest)
mdef (
"#include too nested",
"#include のネストが深すぎる"
)
#undef ldef
#undef kdef
#undef mdef
#else
typedef enum lang_t_ {
#define ldef(l) e_ ## l,
#define kdef(k)
#define mdef(e,j)
#include __FILE__
e_NLANG
} lang_t;
typedef enum kind_t_ {
#define ldef(l)
#define kdef(k) e_ ## k,
#define mdef(e,j)
#include __FILE__
e_NKIND
} kind_t;
const unsigned char * const errstr[e_NKIND][e_NLANG] = {
#define ldef(l)
#define kdef(x)
#define mdef(e,j) {e,j},
#include __FILE__
};
const unsigned char *
errmsg (kind_t k, lang_t l)
{
return errstr[k][l];
}
#endif
--
これじゃ mdef の末尾に , が書けないなぁ….
"Jun Taniguchi" <tani...@tb3.so-net.ne.jp> wrote in message
news:9tgc52$2dkef$1...@ID-96350.news.dfncis.de...
> ふと、昔がんばって読もうとしたLSI-C 86のcppを思い出しました。オプショ
> ン -j で、画面に出力するメッセージを英語と日本語に切り替えることができ
> るのですが、そのためにまず
>
> char MSG_cntopnX[] = "can't open: '%s'\0"
> "ファイル %s がオープンできない";
> char MSG_incnst[] = "#include too nested\0"
> "#include のネストが深すぎる";
>
> とメッセージを定義しておいて、メッセージを利用するときは
>
> int Jap;
> char *chooseMsg(char *s)
> {
> return (Jap ? s + strlen(s) + 1: s);
> }
>
> とすることで、
>
> fprintf(stderr, chooseMsg(MSG_cntopnX), filename);
>
> などと書いておけばあとは Jap の値にあわせて出力文字列を変更できるとい
> うもので、見たときは目から鱗がぽろりと落ちました。
なるほどー、確かに目から鱗、C言語ならではですね。
今度使ってみよ。
Jun Taniguchiさんの<9tgc52$2dkef$1...@ID-96350.news.dfncis.de>から
>はい、確かにそのようです。みやざきさんのご指摘もあわせると、メンバ
>lpstrFilterには "Text Files\0*.TXT;*.DOC\0\0" のように指定することに
>なっているようですね。勉強になりました。
>
># ちょっと趣味にはあわない方式 (^^;)
趣味に合うか合わないかは、嗜好の問題なので置いといて:-)MS-DOS~MS-WINDOWS
では結構普通に用いられているデータの表し方のような気がします。
MS-DOSでは環境変数がメモリ上でまさしく上記のような形で実装されていますか
ら、環境変数を直接取り出そうとすると
void print_all_env(char far *env_block)
{
char far *ep = env_block;
while (*ep) {
printf("%s\n", ep);
ep += strlen(ep) + 1;
}
}
てな、感じになりました。また、大抵のCコンパイラでは、mainに引き渡される
envpも直接同じ構造をさしている場合が多かったので、
void main(int argc, char **argv, char **envp)
{
print_all_env((char far *)envp);
}
なんて、やれば、環境変数の一覧が出るはずです。(実験しないで書いているの
で、間違ってたらごめんなさい)
その他、MS-WINDOWSでも、レジストリに、文字列配列型(REG_MULTI_SZ)を、
APIを使って書き込もうとするとき、上記の構造で書き込みます。
>char MSG_cntopnX[] = "can't open: '%s'\0"
> "ファイル %s がオープンできない";
>char MSG_incnst[] = "#include too nested\0"
> "#include のネストが深すぎる";
>
>とメッセージを定義しておいて、メッセージを利用するときは
>
>int Jap;
>char *chooseMsg(char *s)
>{
> return (Jap ? s + strlen(s) + 1: s);
>}
>
>とすることで、
>
>fprintf(stderr, chooseMsg(MSG_cntopnX), filename);
>
>などと書いておけばあとは Jap の値にあわせて出力文字列を変更できるとい
>うもので、見たときは目から鱗がぽろりと落ちました。
私は、書式をつけて文字列に書き足したいときなんかに、
sprintf(s + strlen(s), " & %d counts...", n);
なんて書き方をよくします。
ちなみに、冒頭にもどって、趣味の問題を述べるなら、エラーメッセージは、外
部ファイルからロードするほうが趣味だったりします。:-)
確か、TurboPascal3なんかがそうでしたね。日本語のエラーメッセージに置き換
えるのが楽でした。
--
Sincerely, Liu 'Hack' Saijo
http://www.vector.co.jp/authors/VA015250/
> void print_all_env(char far *env_block)
> {
> char far *ep = env_block;
>
> while (*ep) {
> printf("%s\n", ep);
> ep += strlen(ep) + 1;
> }
> }
ちゃちゃですが、この場合、strlen は使えません。
farstrlen(MSC、LSIC)か _fstrlen(TC;これであってましたっけ?)です。
========================================================================
飯嶋 浩光 / でるもんた http://www.ht.sakura.ne.jp/~delmonta/
IIJIMA Hiromitsu, aka Delmonta mailto:delm...@ht.sakura.ne.jp
mailto:delm...@pop01.odn.ne.jp
IIJIMA Hiromitsuさんの<3BFD1796...@ht.sakura.ne.jp>から
>> char far *ep = env_block;
>>
>> while (*ep) {
>> printf("%s\n", ep);
>> ep += strlen(ep) + 1;
:
>ちゃちゃですが、この場合、strlen は使えません。
おお!そうですね。うっかりしていました。確かにスモールモデルとかだと、駄
目ですね。というか、それを言うなら、printfも使えませんね。ま、LARGEモデ
ルだということで、勘弁してください。:-P
ちなみに、昔、このfar*なんちゃらの問題に対処するために、自前でfarポイン
タ対応のstrXXX関数やprintf関数を作ったのを思い出しました。
>farstrlen(MSC、LSIC)か _fstrlen(TC;これであってましたっけ?)です。
LSIC試食版を調べてみたら、far_strlenでした。あと、私の持っているTCには該
当する機能の関数はありませんでした。(バージョンの問題かな?)
ま、確かに、該当する機能の関数がなかったからこそ、自前で作ったんですが…
Kazuo Fox Dohzonoさんの<9tiaju$vtj$2...@news2.rim.or.jp>から
>#if defined (ldef) || defined (kdef) || defined (mdef)
(snip)
あまりの絶妙さに言葉がありません (^^;)
; #include __FILE__ か…なるほどなあ…
メッセージを必要とするソースファイルが複数にわたっていると
うまく使えなさそうなのがちょっと残念です。
> >#if defined (ldef) || defined (kdef) || defined (mdef)
> (snip)
>
> あまりの絶妙さに言葉がありません (^^;)
いや, 実は例としては恥ずかしかったなぁと思ってるんですけど.
const char * const str[LANG][KIND];
の順にしておけば起動時に言語を指定された時点で片方は演算する必要がなく
なるわけですよね? (あと kdef と mdef は分ける必要がないってのがまだま
だアマチュアだなあ, とか).
> メッセージを必要とするソースファイルが複数にわたっていると
> うまく使えなさそうなのがちょっと残念です。
その辺は grep なりなんなり使えばどうとてもなりますよね.
# #inlclude __FILE__ が思惑通りに動くかどうかは実は未確認 (規格漁って
# ません) :-p
> > メッセージを必要とするソースファイルが複数にわたっていると
> > うまく使えなさそうなのがちょっと残念です。
>
> その辺は grep なりなんなり使えばどうとてもなりますよね.
じゃなくて (--;
そういう場合は #include __FILE__ などとせずに lang_t と kind_t だけヘッ
ダファイルで定義して (メッセージを必要とするモジュールはこれらを用いて),
メッセージを返す関数のあるモジュールでメッセージを定義すればいいわけで
す.
--- foo.h
#if defined (ldef) || defined (kdef) || defined (mdef)
...
#else
typedef enum lang_t_ {
...
} lang_t;
typedef enum kind_t_ {
...
} kind_t;
extern const unsigned char *errmsg (kind_t k, lang_t l);
#endif
---
--- foo.c
static const unsigned char * const errstr[e_NKIND][e_NLANG] = {
#define ldef(l)
#define kdef(x)
#define mdef(e,j) {e,j},
#include "foo.h"
};
const unsigned char *
errmsg (kind_t k, lang_t l)
{
return errstr[k][l];
}
---
で, 先の「起動時に言語を指定された時点で片方は演算する必要がなくなる」というのは,
--- bar.c
static const unsigned char * const errstr[e_NLANG][e_NKIND] = {
{
#define ldef(l)
#define kdef(x)
#define mdef(e,j) e,
#include "foo.h"
},{
#define ldef(l)
#define kdef(x)
#define mdef(e,j) j,
#include "foo.h"
}
};
static const unsigned char * const *esp = errstr[e_english]; /* default */
void
setup_language (lang_t l)
{
esp = errstr[l];
}
const unsigned char *
errmsg (kind_t k)
{
return esp[k];
}
---
ということですね.
> MS-DOSでは環境変数がメモリ上でまさしく上記のような形で実装されていますか
> ら、環境変数を直接取り出そうとすると
>
> void print_all_env(char far *env_block)
> {
> char far *ep = env_block;
>
> while (*ep) {
> printf("%s\n", ep);
> ep += strlen(ep) + 1;
> }
> }
>
> てな、感じになりました。また、大抵のCコンパイラでは、mainに引き渡される
> envpも直接同じ構造をさしている場合が多かったので、
>
> void main(int argc, char **argv, char **envp)
> {
> print_all_env((char far *)envp);
> }
>
> なんて、やれば、環境変数の一覧が出るはずです。
# print_all_env ((char far *) *envp) の誤りかな?
しかし, そういう処理系でも
int
main (int ac, char **av, char **env)
{
while (*env)
puts (*env++);
return 0;
}
という形式でもあったりしません? これなら strlen でチマチマ長さを求める
必要もないと思うんですけど. env を入れ替えて次のプロセスを呼ぶのも楽だ
し.
In article <9tiaju$vtj$2...@news2.rim.or.jp>
doh...@hf.rim.or.jp (Kazuo Fox Dohzono) writes:
> kdef (err_open)
> mdef (
> "can't open: '%s'",
> "ファイル %s がオープンできない"
> )
これは別記事に書いた通りひとまとめにして
edef (
"can't open: '%s'",
"ファイル %s がオープンできない",
err_open
)
とするか, 使われない要素を用いて
edef (
err_open,
"can't open: '%s'",
"ファイル %s がオープンできない",
dummy
)
とすることで文字列の書式は揃いますね (エディタなどで一括生成する場合に
便利).
Kazuo Fox Dohzonoさんの<9tpie0$1mvn$1...@news2.rim.or.jp>から
># print_all_env ((char far *) *envp) の誤りかな?
うっ、そのとおりです。テストしないでポストしたので、あっちこっちミスだら
けですね。すみません。
>しかし, そういう処理系でも
>
>int
>main (int ac, char **av, char **env)
>{
> while (*env)
> puts (*env++);
> return 0;
>}
>
>という形式でもあったりしません? これなら strlen でチマチマ長さを求める
>必要もないと思うんですけど. env を入れ替えて次のプロセスを呼ぶのも楽だ
>し.
これも、そのとおりです。やはり、常識的にはこちらの方法でしょう。前回のは
あくまでもこんなこともできますというつもりで書きました。状況にもよります
が、何の前提条件もなしに、私の書いたようなコードを使って環境変数の一覧を
出そうとしている人がいたら、私もKazuo Fox Dohzonoさんと同じことを言うと
思います。
#「出来る事」と「やる事」は別。:-P