ショッピングモール  Personal Health / Stress ( Anger Management )


掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板1

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.4907

文字列の代入変換
投稿者---カフェイン(2005/11/24 11:13:22)


ある文字列中に含まれる特定の文字の前に文字を代入したいのですが、
これを(できる限り)最速で行う方法を探しています。

具体的に言うと、例えば
"aaabbb^ccc|dddeee[fff" 中の '^'と'|'と'['をそれぞれ変換対象として
"aaabbb\^ccc\|dddeee\[fff" のように変換対象文字の前に'\'を代入したいのです。

代入が入るので、先頭から一文字ずつチェックしていく方法を思いついたのですが、
文字列長は大体200〜500文字で変換対象文字列の割合はそんなに高くはない(5%未満)ので、
無駄があるように思いました。

なにか良いアイディアはないでしょうか。

環境はUNIX Cです。よろしくお願いします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:文字列の代入変換 4908 円零 2005/11/24 11:47:49
<子記事> Re:文字列の代入変換 4909 wiz 2005/11/24 11:56:57
<子記事> Re:文字列の代入変換 4911 shu 2005/11/24 13:56:35


No.4908

Re:文字列の代入変換
投稿者---円零(2005/11/24 11:47:49)


結局処理としては先頭から一文字ずつチェックすることになるんだろうとは思いますが、
自分で普通にCで書くよりは、ライブラリ関数(strcspnとか)を使った方が
処理そのものも早くなるでしょうね。


この投稿にコメントする

削除パスワード

No.4909

Re:文字列の代入変換
投稿者---wiz(2005/11/24 11:56:57)


>具体的に言うと、例えば
>"aaabbb^ccc|dddeee[fff" 中の '^'と'|'と'['をそれぞれ変換対象として
>"aaabbb\^ccc\|dddeee\[fff" のように変換対象文字の前に'\'を代入したいのです。
>
>代入が入るので、先頭から一文字ずつチェックしていく方法を思いついたのですが、
>文字列長は大体200〜500文字で変換対象文字列の割合はそんなに高くはない(5%未満)ので、

strchr関数を使って対象文字が無ければ調べるのをやめて、
あればその文字のポインタを返すのでその前に挿入してそこから
また繰り返すみたいな感じでは。。。?

#あんまり変わらないかな。。。
#そもそもそんな変換が必要なコーティングが微妙ですね。。。
#入力時に何とかするほうが楽な気がしますが。。。


この投稿にコメントする

削除パスワード

No.4910

Re:文字列の代入変換
投稿者---Blue(2005/11/24 13:07:40)


> あればその文字のポインタを返すのでその前に挿入してそこから
挿入ができないのでは?

挿入することによって、それ以降の文字を挿入した文字数文後にずらさないといけないですから。

はやり先頭から1文字ずつチェックし、別バッファにコピーして、
該当文字がきたら、挿入文字を別バッファに設定して、コピー位置をずらして、、、
という風にしなければならなそう。

類似スレ
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200510/05100044.txt


この投稿にコメントする

削除パスワード

No.4912

Re:文字列の代入変換
投稿者---wiz(2005/11/24 14:02:58)


>> あればその文字のポインタを返すのでその前に挿入してそこから
>挿入ができないのでは?

確かに不適切な表現ですが、アルゴリズム的な表現としては間違っていないと思います。
誤解を与えそうなので、今後気をつけます。




この投稿にコメントする

削除パスワード

No.4911

Re:文字列の代入変換
投稿者---shu(2005/11/24 13:56:35)


一々代入しなおす事自体が、結果として非効率になっているのではないでしょうか?
//
//  結果的に画面なりファイルなりに出力するのだろうから、
//  無理に「代入」変換に拘らなくても良いと思うプログラム。
//

//
#include <stdio.h>

//
void puts_esc( const char *s, const char *esc );

//
//
int main( void )
{
    char *s = "aaabbb^ccc|dddeee[fff", *esc = "^|[";
    
    //
    puts_esc( s, esc );
    
    return 0;
}

//
static int is_esc( const char *esc, const char c )
{
    char *p;
    
    //
    for (p = esc; *p; p++)
        if (*p == c)
            return 1;
    
    return 0;
}

//
void puts_esc( const char *s, const char *esc )
{
    char *p;
    
    //
    for (p = s; *p; p++)
    {
        if (is_esc( esc, *p ))
            putchar( '\\' );
            
        putchar( *p );
    }
}



この投稿にコメントする

削除パスワード

No.4913

Re:文字列の代入変換
投稿者---wiz(2005/11/24 14:08:20)


sの中身を替えようとしているのにconstはつけるとまずくないですか?



この投稿にコメントする

削除パスワード

No.4914

Re:文字列の代入変換
投稿者---nop(2005/11/24 16:09:38)


>sの中身を替えようとしているのにconstはつけるとまずくないですか?

s の中身を変えようとしている箇所が見つかりませんが?
出力先は標準出力ですし。



この投稿にコメントする

削除パスワード

No.4918

Re:文字列の代入変換
投稿者---wiz(2005/11/24 17:16:43)


書き間違えですね;
sの中身ではなくs自身ですね。。。
sはconstなのでchar型のpに変換することはできません。
コンパイラによってはconst修飾子が失われるのでエラーとなります。
ってことです。


この投稿にコメントする

削除パスワード

No.4919

Re:文字列の代入変換
投稿者---円零(2005/11/24 17:37:44)


>sはconstなのでchar型のpに変換することはできません。
>コンパイラによってはconst修飾子が失われるのでエラーとなります。
>ってことです。

そういう場合、普通は
「pにもconstをつけるべきでは?」
と指摘するような気がしますが。


この投稿にコメントする

削除パスワード

No.4920

Re:文字列の代入変換
投稿者---shu(2005/11/24 17:54:48)


wizさん、こんなんでどうでしょうか?

//
//  結果、ほとんどconst char *になったプログラム。
//

//
#include <stdio.h>

//
void puts_esc( const char *s, const char *esc );

//
//
int main( void )
{
    const char *s = "aaabbb^ccc|dddeee[fff", *esc = "^|[";
    
    //
    puts_esc( s, esc );
    
    return 0;
}

//
static int is_esc( const char *esc, const char c )
{
    const char *p;
    
    //
    for (p = esc; *p; p++)
        if (*p == c)
            return 1;
    
    return 0;
}

//
void puts_esc( const char *s, const char *esc )
{
    const char *p;
    
    //
    for (p = s; *p; p++)
    {
        if (is_esc( esc, *p ))
            putchar( '\\' );
            
        putchar( *p );
    }
}


……そういえば、
予め初期化する文字列がある場合や、関数の引き数以外で、
const * って使った覚えがあまり無い。


この投稿にコメントする

削除パスワード

No.4922

Re:文字列の代入変換
投稿者---REE(2005/11/24 18:18:54)


>wizさん、こんなんでどうでしょうか?

>, const char c )
ちなみにこのconstはあってもなくても意味は変わりません。




この投稿にコメントする

削除パスワード

No.4921

Re:文字列の代入変換
投稿者---wiz(2005/11/24 17:56:21)


>そういう場合、普通は
>「pにもconstをつけるべきでは?」
>と指摘するような気がしますが。
普通なのかは知りませんが、sのconstを取るか
pにconstをつけるかどちらかだと思います。

#私は質問者が「表示」で文字を入れるだけでなくデータとして
#必要なのではと思った為,sの中身自体を変えなければならない
#ことがあるのではないかと思ってそう書いただけですので。。。
#とりあえず、提示されたサンプルについては以降のレスを
#控えたほうが良いようなのでこれまでに。。。


この投稿にコメントする

削除パスワード

No.4923

Re:文字列の代入変換
投稿者---カフェイン(2005/11/24 19:20:33)


返信遅くなりました。大変申し訳ありません。

現象を中途半端に説明してしまい申し訳ありません。
今、問題となっているのは、
char buf = "aaa.exe arg01 arg02 arg03 …";
system(buf);
のようになっていて、aaa.exeの引数にシェルの禁則文字などが入ると誤動作してしまう。
というのを何とかしたいのです。
ここで、各引数はファイルから取得しており、このファイルを操作することはできないので、
system()に受け渡す前に置換したいのです。
(system実行は複数回実行されるので、少しでも早く置換したい)


皆様のアドバイスを拝見させていただき、以下で行おうと思います。
[case1]
1.strcspnまたはstrchrなどを使用して対象文字を検索
2.memcpyなどにより対象文字列の手前までを、別バッファにコピー
3.エスケープ文字を追加して次の対象文字を検索
4.対象文字があったら、前回対象文字から今回対象文字の手前までを別バッファに追加
5.終端まで繰り返し

[case2]
1.文字列の先頭から一文字ずつ別バッファにコピー
2.対象文字があったらコピーする前にエスケープ文字を入れる
3.終端まで繰り返し

case1とcase2で速度を比べてみようと思います。
貴重な情報ありがとうございました。


この投稿にコメントする

削除パスワード

No.4937

Re:文字列の代入変換
投稿者---かずま(2005/11/25 02:31:13)


> system()に受け渡す前に置換したいのです。
> (system実行は複数回実行されるので、少しでも早く置換したい)

> case1とcase2で速度を比べてみようと思います。

ぜひとも、測定結果をここで発表してくださいね。

私の予想では、case1 と case2 にほとんど差はなく、仮にどちらかが
1ミリ秒で、もう一方が 2ミリ秒だったとしても、system() の実行に
100ミリ秒ぐらいかかって、結局意味がないと思いますよ。

速くしたいんだったら、system() なんか使わずに、fork() + exec() に
したほうが何倍も速くなるような気がします。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧




掲示板提供:Real Integrity