ページ 1 / 1
文字列の'\0'以降について
Posted: 2008年9月23日(火) 01:44
by kazuoni
お邪魔します。
例えばですが
char array[1000]
において[0][300]まで文字がはいっているとして
[299]と[300]の'\0'の境界を見つける関数を作ろうとしました。
この関数は引数として&array[0]を受けとり、出力に
char *reserch(char buffer[/url]){
int pl=0;
int pr=1000;
int pc;
while(1){
pc=(pl+pr)/2;
if(pr-pl==1)
return (&buffer[p[/url]);
if(buffer[pc=='(1)'])
pr=pc;
else
pl=pc;
}
}
この時、一回目にbuffer[500]を読みに行くことになるのですが
(1)に何を入れたらうまくいくのでしょうか?
(この関数自体怪しいですが・・・。)
これはやはり未定義なのでしょうか?('\n'以降は何があるか分からない)
文字列の長さを求めるのにstrlen関数が用意されています。
自分は上で示したほうの関数を使ったほうがちょっとは速くなるんじゃないかと思っていたのですが
strlenがどのように辿って行っているのかよくわからないので
なんとも言えない所です。。
だいたいの実現例はひたすらインクリメントをしていたので
かなり長い文字列よりはこっちのがいいのかなぁっと^^;
よろしくお願いします。
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 02:09
by バグ
初期化されているのが保障されている訳ではありませんし、実際問題何が入っているか分からない領域を参照するのはどうかと思いますが…
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 02:22
by kazuoni
調べてみたら
'フ'
になっていました。これでやればきちんと動きましたが
やはり止めておいたほうがいいですかね^^;
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 02:50
by 管理人
>一回目にbuffer[500]を読みに行くことになるのですが
ならない・・のでは?
pc=(pl+pr)/2;
if(buffer[pc=='(1)'])
pcは最初500だと思いますが、
500=='(1)'
の条件式の評価の結果は0か0以外が返るわけですから、
また、文字コードに500番はありませんから常に儀、つまり0になるでしょうから
buffer[0]が参照されると思います。
ですから、この段階だけなら大丈夫でしょう。
きっと全体の半分、半分、半分と探していけば早いんじゃないかと仰っているのだと思いますが
文字列の終端以降全部\0が入ってるわけじゃないので、それじゃ難しいんじゃないですか?
例えば「hellow」の間にいくつも\0が紛れ込んでいる時、これは文字列としては「he」ですが
1 2 3 4 5 6 7 8 9 10 11 12
h e \0 l \0 \0 l o \0 w ! \0
正しく判定出来るでしょうか?
最初に\0があった場所までなのでやはり最初から探していくしかないのでは。
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 02:57
by 管理人
そのようなアルゴリズムを考えるのが好きでしたら、是非ソートアルゴリズムを考えてみてはどうでしょう。
もう世界中の人間が考えてるのでなかなか新たなソートアルゴリズムの発見は難しいでしょうけど、
結構面白かったりしますよ。
クイックソートやヒープソートとか勉強してもなかなか為になると思います。
後、strlenの実装例です。
#include <stdlib.h>
size_t my_strlen(const char *p){
size_t n = 0;
while (*p++)
n++;
return (n);
}
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 03:02
by kazuoni
>if(buffer[pc=='(1)'])
でなく
if(buffer[pc]=='(1)')
でしたね^^;
いやーなかなか思った通りにいかないものですね。
バグさん、管理人さんご回答ありがとうございました。
PS、
過去ログでは2年ぐらい前から管理人さんは夜派だったような気がするのですが・・・
よく体がもつなぁと^^;
頭がカクカクしてきたので寝ます・・・(笑)
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 03:07
by バグ
では便乗して、私も実装例を…(笑)
unsigned long long mystrlen(char* str)
{
unsigned long long count = 0;
for (count = 0; *str != '\0'; ++count, ++str);
return count;
}
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 03:09
by バグ
あ、無駄な初期化をしてしまっている…ちょっと修正
unsigned long long mystrlen(char* str)
{
unsigned long long count = 0;
for (; *str != '\0'; ++count, ++str);
return count;
}
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 03:16
by kazuoni
じゃあ自分も・・・(えっ?w
size_t Strlen(const char *pointer)
{
size_t length = 0;
while(*pointer++)
length++;
return length;
}
確か前はこれで動いたと思ったんですが^^;
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 03:22
by kazuoni
ってか管理人さんとまるっきり一緒だ!!ww
やはり望洋先生についていくと、このコードを使ってしまいますねww
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 08:50
by 管理人
望洋さんは本もわかりやすいしすごいですよねぇ。
>睡眠時間
基本寝ないですね・・(ぇ
今日も寝てないですし・・。
寝る時間はプログラムを書いてるというのが基本スタイル(病気
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 10:49
by ibis
面白そうなので私も(笑
大きい文字列だとこっちの方が速いはず。多分。
int mystrlen(const char *begin){
const char *incremental = begin;
while(*incremental){
++ incremental;
}
return incremental - begin;
}
ついでに範囲を超えないことを保証してみます。
まぁ普通は必要ないでしょうけど。
なんか引数がSTLのアルゴリズムみたいですね。
int mystrlen(const char *begin, const char *end){
const char *incremental = begin;
while(*incremental && incremental != end){
++ incremental;
}
return incremental - begin;
}
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 11:06
by バグ
>ibisさん
たしかに、beginやendというと、なんだかイテレータみたいですね(笑)
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 11:39
by kazuoni
begin・・・
初めてみました^^;こんなのも使えるのですかっ。
これはCですか?
学校で触りだけやったpascalでなんだか使った記憶があります。
本当に表面だけだったのでpascalの書き方なんてもう覚えていませんが。。
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 12:54
by バグ
>>kazuoniさん
ibisさんのサンプルは変数名にbeginとendというのを用いているだけで、名前自体に特別な意味がある訳ではありませんよ。STLというC++のライブラリの中にイテレータという考え方がありまして、『その使い方に似ていますね』という話をしていたんです(^-^)
で、ibisさんのサンプルですが、これはCで書かれていますね。
中身を簡単に解説すると、文字列の最初を示すポインタをbegin、文字列バッファの最後を示すポインタをendとして渡してやることで、バッファサイズをオーバーしないように書かれている訳です。
つまり、仮に文字列用の配列であるarrayの要素数を500とするならば、mystrlen(&array[0], &array[499])としてやれば、いいわけですね。
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 13:13
by kazuoni
申し訳ありませんでした。。そのままでしたね。。
引数にbeginやendがありましたね。
コードをきちんと見直す癖をつけないとまずいですね・・・
いつもは(自分の環境では)型名などは色づけされており、パパッと判断してしまうのですが
こちらだとその区別が通用しないのに慣れていなくて。。
(本などでは型名等は太文字ですね)
失礼しました。
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 13:42
by ibis
Pascalのbeginとendは、Cの{と}みたいなものですよね。
あれは関係ないです。
細かいことはバグさんが仰ってる通り。
バグさん、解説ありがとうございます。
>mystrlen(&array[0], &array[499])
うわ、使いにくいw
第二引数はサイズを整数型で渡す方が良いでしょうか。
引数名をsizeに、型をintに。
いや、戻り値もだけど、size_t型の方が良いのかな。
あとはポインタ型変数endを宣言して、endを(begin + size)で初期化して。
あ、mystrlen(array, array + 499)はどうでしょ。
・・・うん。可読性がちょっと。
やっぱりサイズ渡すしか。
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 14:40
by Justy
>mystrlen(array, array + 499)はどうでしょ
あ、この begin/endって STLのとは違って、endの方は有効な領域の最後を渡すのですね。
>うわ、使いにくいw
>第二引数はサイズを整数型で渡す方が良いでしょうか。
個人的にはあんまり変わらないので、どっちでもいいと思うのですが、
サイズを渡した方がC言語しかやらない人には解りやすいかと思います。
>戻り値もだけど、size_t型の方が良いのかな。
どちらかといえば、size_tの方がいいのではないでしょうか。
符号が必要とも思えませんし、他の文字列関連の標準関数とも合いますし。
>うん。可読性がちょっと
与える引数がポインタならその方向で、配列ならマクロを経由して使うようにし
そのマクロで配列のサイズを計算して関数に入れるようにしてしまえば
多少使い勝手は向上するかも。
Re:文字列の'\0'以降について
Posted: 2008年9月23日(火) 14:53
by ibis
>あ、この begin/endって STLのとは違って、endの方は有効な領域の最後を渡すのですね。
あ、それは全く考えてなかったです。
自分でも「499」と書くときに違和感があったのですがスルーしてました。
なんかいろいろと考えが及んでなかったですね。