アプリ版:「スタンプのみでお礼する」機能のリリースについて

VC++6.0・Win32APIを用いて、ウィンドウズアプリケーションを作成しています。

エディットボックスに入力されている文字列が、スペース(全角スペース又は半角スペース)のみ
(それらの組み合わせでも構わない)で構成されているかどうかを判別するアルゴリズムを教えてください。
ヒントでも構いません。

エディットボックスの作成や、そこからの文字列の取得については理解しています。

あっ、でもよく考えてみたらエディットボックスかどうかは関係ないですね(^_^;)
『ある文字列が・・・』で十分ですね。

お手数をお掛けしますが、よろしくお願いいたします。

A 回答 (5件)

★アドバイス


>判別するアルゴリズムを教えてください。
 ↑
 1文字ずつ調べるしかないと思います。
 あるいはシェル関数の StrTrim() を使うと簡単にチェックできます。
・下に確認用のサンプルを載せます。

サンプル:
#include <stdio.h>
#include <shlwapi.h>
#include <windows.h>

// チェック関数
void check( char string[] )
{
 printf( "チェック前 = [%s]\n", string );
 StrTrim( string, "  " );
 printf( "チェック後 = [%s]\n", string );
 
 if ( string[0] == '\0' ){
  printf( "判定結果:空白文字のみ\n" );
 }
 else{
  printf( "判定結果:空白文字以外あり\n" );
 }
 printf( "\n" );
}

// メイン関数
int main( void )
{
 TCHAR s1[] = "   ";
 TCHAR s2[] = "   a b c ";
 
 // 半角空白,全角空白のみ
 check( s1 );
 
 // 空白以外が混ざっている
 check( s2 );
 
 return 0;
}

解説:
・まずエディットボックスなどから文字列を取得します。
 その後に StrTrim() 関数により文字列の両端から半角空白文字と全角空白文字を取り除く。
 その結果、まだ文字列が残っていれば空白文字以外が存在する事になります。
・check() 関数の if で '\0' 文字と同じか判定しています。
 この判定こそがすべて空白文字だけで構成されているかの判定となります。
 なお StrTrim() API 関数を利用するには <shlwapi.h> をインクルードしてさらに
 shlwapi.lib ライブラリをインポートする必要があります。注意。
 StrTrim() 関数は C 言語の標準関数(ランタイム・ライブラリ)ではなくて Win32 API に属します。
・以上。

この回答への補足

お礼の言葉を書き忘れてしまいました。
ご回答いただきありがとうございました。

補足日時:2007/08/24 11:27
    • good
    • 0
この回答へのお礼

毎度お世話になっております。

StrTrim()という関数があるのは初めて知りました。
もし知っていたとしても、こういう場面で使うといういことは思いつかなかったと思います。

ちなみに、ご回答いただく前に自分なりに考えたソースを載せさせていただきます。
問題点などがありましたら、ご指摘いただけると幸いです。

if(GetWindowText(hEdit, str, sizeof(str))){
 char *pPoint = str;
 BOOL bSpace = TRUE; // 文字列が『全角スペース』又は『半角スペース』のみで構成されているかどうか
 while(*pPoint != '\0'){
  if(!memcmp(pPoint, " ", 2)){
   pPoint += 2;
  }else if(!memcmp(pPoint, " ", 1)){
   pPoint++;
  }else{
   bSpace = FALSE;
   break;
  }
 }
}

お礼日時:2007/08/24 11:19

if(GetWindowText(hEdit, str, sizeof(str))){


 char *pPoint = str;
 BOOL bSpace = TRUE; // 文字列が『全角スペース』又は『半角スペース』のみで構成されているかどうか
 while(*pPoint != '\0'){
  if(!memcmp(pPoint, " ", 2)){
   pPoint += 2;
  }else if(!memcmp(pPoint, " ", 1)){
   pPoint++;
  }else{
   bSpace = FALSE;
   break;
  }
 }
}

動作も意図していますし、スマートで良いと思いますよ。
さらにスマートにするなら、

 char *pPoint = str;
 int rel;

 while(*pPoint && rel){
  rel=!memcmp(pPoint, " ", 2)?2:(!memcmp(pPoint, " ", 1)?1:0)
  pPoint+=rel;
  }
  if (*pPoint) 全てスペースです;
  else スペース以外の文字があります;

と言うのもOKですね。
    • good
    • 0
この回答へのお礼

VTClientさんのやり方ですと、さらにコンパクトなソースになりますね。
大変参考になりました。ありがとうございました。

お礼日時:2007/08/27 16:00

★ソースの感想。


・プログラムがマルチバイト文字の専用なら問題ないでしょう。
 でも私なら strncmp() 関数を使ったり、isspace()、全角文字(0x8140)との比較を
 使うようにソースを書きますけど。そこでマルチバイト文字専用のソースを載せます。

サンプル:
// 全角の空白文字コード
#define CHR_SPACE (0x8140)

// 半角空白文字,全角空白文字のチェック
BOOL IsStrSpace( const char string[] )
{
 while ( *string != '\0' ){
  if ( MAKEWORD(string[1],string[0]) == CHR_SPACE ){
   string += 2;
  }
  else if ( isspace(*string) ){
   string += 1;
  }
  else{
   return FALSE;
  }
 }
 return TRUE;
}

解説:
・ほとんど kenkenpo さんと同じ仕組みです。
 違う場所は memcmp() 関数を利用しないで MAKEWORD() マクロ関数と isspace() マクロを
 利用している点です。関数を呼ばない分だけ高速にチェックできると思います。
・また、memcmp() の代わりに strncmp() 関数に差し替えても同じになります。
 理由は関数名だけが異なり、引数や戻り値の意味は同じですので。
 別名として用意されている点が面白いですね。

その他:
・今回はマルチバイト文字を専用とした関数ですが、もし今後 Unicode 文字にも対応させる場合は
 関数を作り変える必要があります。なのでシェル関数の StrTrim() で同じようなことが出来る場合は
 大いに活用しましょう。StrTrim() には StrTrimA()、StrTrimW() の2つが用意されています。
 コンパイル・オプションにより適切な関数がリンクされます。よって簡単に Unicode 文字への対応が
 できます。お勧めは StrTrim() を使った判定方法です。
・以上。
    • good
    • 0
この回答へのお礼

memcmp()関数と、strncmp()関数という同じ処理をする関数が存在することは初めて知りました。

同じ処理を実装するのにも、いろんな書き方があることが分かり、大変勉強になりました。
処理速度や、可読性など、そのときの状況に応じて、より適切な方法を選べるようにならないといけませんね。

ありがとうございました。

お礼日時:2007/08/27 16:07

追記です。


複数行エディットに対応させました。
IsSpace 関数を変更しますね。

int IsSpace(const char* str)
{
int i,len=0;

for (i=0;*(str+i);)
{
if (*(str+i)>=0x20 && *(str+i)<=0x7f)
{
if (*(str+i)==0x20) len++;
i++;
}
else if (*(str+i)==0xd && *(str+i+1)==0xa)
{
len+=2,i+=2;
}
else
{
if (*(str+i)==(~0xff|0x81) && *(str+i+1)==0x40) len+=2,i+=2;
else i++;
}
}
return i-len-!(i+len);
}

オーバーフローのエラーにも対応させました。

この回答への補足

様々な場合に対応できるようなソースを提示していただき、誠にありがとうございます。

ちなみに、今の私の環境は単一行エディットで、入力文字制限を掛けてあります。

ご回答をいただく前に、自分なりに考えたソースを載せさせていただきますので、問題点等ありましたらご指摘いただけると幸いです。

if(GetWindowText(hEdit, str, sizeof(str))){
 char *pPoint = str;
 BOOL bSpace = TRUE; // 文字列が『全角スペース』又は『半角スペース』のみで構成されているかどうか
 while(*pPoint != '\0'){
  if(!memcmp(pPoint, " ", 2)){
   pPoint += 2;
  }else if(!memcmp(pPoint, " ", 1)){
   pPoint++;
  }else{
   bSpace = FALSE;
   break;
  }
 }
}

補足日時:2007/08/24 11:24
    • good
    • 0

アルゴリズムとおっしゃるので、すべて自作でやってみましょう。


尚、エディットボックスから文字列を得る際は、
GetWindowTextA など、Ansi バージョンを使ってください。

int IsSpace(const char* str)
{
int i,len=0;

for (i=0;*(str+i);)
{
if (*(str+i)>=0x20 && *(str+i)<=0x7f)
{
if (*(str+i)==0x20) len++;
i++;
}
else
{
if (*(str+i)==(~0xff|0x81) && *(str+i+1)==0x40) len+=2;
i+=2;
}
}
return i-len-!(i+len);
}

int main()
{
char str[]="取得文字列";

switch (IsSpace(str))
{
case -1:
printf("空の文字列です\r\n");
break;
case 0:
printf("すべてスペースです\r\n");
break;
default:
printf("すべてスペースではありません\r\n");
}
return 0;
}

を例に、IsSpace() の戻り値で判定します。
一応、参考として・・・。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています