FreeBASIC マニュアルのトップに戻る

FreeBASIC Mid function

目次→ランタイム・ライブラリー参考→文字列関数MID(関数)←オリジナル・サイト

MID(関数) 左にメニュー・フレームが表示されていない場合は、ここをクリックして下さい

←リンク元に戻る プログラム開発関連に戻る

文字列の中の、一部分の文字列を返します。
渡辺注:
(1). Shift_JIS のソース・コード(.bas ファイル)で、Shift_JIS の全角半角を、扱うことができる、KMid を追加しています。
(2). 日本語 Windows の、コマンドプロンプトの標準の「ラスターフォント(Raster font ビットマップ・フォント)」で、ユニコード文字列を Print 表示させると、全角文字列の右半分が欠落します。
 ユニコード のソース・コード(.bas ファイル)で、WString の全角文字の Print を補助する、Expand を追加しています。


構文:
declare function Mid ( byref str as CONST String(文字列) , byval start as integer ) as String(文字列)
declare function Mid ( byval str as CONST wstring PTR , byval start as integer ) as wstring
declare function Mid ( byref str as CONST String(文字列) , byval start as integer, byval n as integer ) as String(文字列)
declare function Mid ( byval str as CONST wstring PTR , byval start as integer, byval n as integer ) as wstring

用法:
result = Mid[$] ( str, start [, n ] )

パラメタ:
str
元になる文字列
start
抽出元の文字列 str の中での、抽出する文字列の開始位置。
最初の文字は位置1で開始します。
n
抽出する文字列の文字数。

記述:
str で指定した文字列の、start 以下の文字列を返します。
str が空ならば、ヌル文字 ("") を返します。
start <= 0 ならば、ヌル文字 ("") を返します。
Mid で、抽出する文字数を指定しないときは、残っている文字のすべてを返します。
抽出する文字数を指定しても、 n < 0n >= len(str) なら、残っている文字のすべてを返します。

例:
半角全角が混在する場合
Print Mid ("abcdefg", 3, 2)
Print Mid ("abcdefg", 3)
Print Mid ("abcdefg", 2, 1)
Sleep


出力結果は下のようになります:
cd
cdefg
b

英数字と2バイトの日本語が混在する場合の処理例です。
  参考:ASCII 文字コード表
例 1:ソース・コード(.bas ファイル)は、Shift_JIS で保存
Dim As String mojiretsu 
Dim As Integer mojisu
Dim As Integer i
Dim As Integer cCode

Declare Function KLen (mojiretsu As String) As Integer
Declare Function KMid (mojiretsu As String, start As Integer, mojisu As Integer) As String

Width 60, 30 '横幅を60桁に狭めます
mojiretsu="、-K2011年11月03日(曜日Thur.)"
mojisu=Len(mojiretsu)
Print mojiretsu
Print "文字数= ";mojisu
For i=1 to mojisu
   cCode = Asc(Mid(mojiretsu, i, 1))
   If cCode >= 129 And cCode <= 255 Then  'コードが2バイト文字の範囲なら
      Print i,Mid(mojiretsu,i,2),Asc(Mid(mojiretsu,i,1)),"2バイト"
      i = i + 1
   Else
      Print i,Mid(mojiretsu,i,1),Asc(Mid(mojiretsu,i,1)),"1バイト"
   End If
Next i
Print "何かキーを押して下さい。"
Sleep

Print mojiretsu
mojisu=KLen(mojiretsu)
Print "文字数= ";mojisu

For i=1 to mojisu
   Print i,KMid(mojiretsu,i,1)
Next i

Print "何かキーを押して下さい。"
Sleep
End


Function KMid (mojiretsu As String, start As Integer, mojisu As Integer) As String
	Dim inS As Integer
	Dim inN As Integer
	Dim cCode As Integer
	Dim Counter As Integer
	Dim Modori As Integer
	
	Counter = 0
	inS = 0
	While Counter < start
		Modori = 1
		inS = inS + 1
		cCode = Asc(Mid(mojiretsu, inS, 1))
	   If (cCode >= &h81 And cCode <= &h9F) Or (cCode >= &hE0 And cCode <= &hFF)  Then  'コードがSJIS2バイト文字の範囲なら
	      inS = inS + 1
	      Modori = 2
	   End If
		Counter = Counter + 1
	Wend
	
	Counter = 0
	inN = 0
	While Counter < mojisu
		inN = inN + 1
		cCode = Asc(Mid(mojiretsu, inS - Modori + inN, 1))
	   If (cCode >= &h81 And cCode <= &h9F) Or (cCode >= &hE0 And cCode <= &hFF)  Then  'コードがSJIS2バイト文字の範囲なら
	      inN = inN + 1
	   End If
		Counter = Counter + 1
	Wend
	
	KMid = Mid (mojiretsu,inS - Modori + 1 ,inN)
End Function

Function KLen (mojiretsu As String) As Integer
	Dim i As Integer
	Dim cCode As Integer
	Dim Result As Integer
	
	Result = 0
	
	For i = 1 To Len(mojiretsu)
		cCode = Asc(Mid(mojiretsu, i, 1))
	   If (cCode >= &h81 And cCode <= &h9F) Or (cCode >= &hE0 And cCode <= &hFF)  Then  'コードがSJIS2バイト文字の範囲なら
	      i = i + 1
	   End If
	   Result = Result + 1
	Next i
	KLen = Result
End Function


例 2:ソース・コード(.bas ファイル)は、UNICODE で保存すること!

注意:FbEdit は、これを書いている時点のバージョンでは、UNICODE のファイルを保存すると、不要な文字が入るバグが有ります。
このため、FbEdit を使う場合は、FbEdit でソース・コードを編集した後、全画面コピーして、UNICODE保存できるテキスト・エディタに貼り付けて、ファイル保存します。すると、FbEdit 側に、変更内容が返ってきます。

*******************************************
ファイルは、外部エディタで変更されました!
ファイルを開きなおしますか?
*******************************************
ここで、「はい」を押します。そして「Go」します。
つまり、表示・編集・コンパイルだけに、FbEdit を使うと、うまく行きます。

UNICODE保存できる旧バージョン「fbedit1.0.7.4.zip」を、下でダウンロードできるようにしました。

http://www.hi-ho.ne.jp/makoto_watanabe/FbEdit/fbedit1.0.7.4Unicode.zip

Dim mojiretsu As WString * 40 
Dim mojisu As Integer
Dim i As Integer

Declare Function Expand(s As WString) as WString Ptr

Width 50, 30 '横幅を50桁に狭めます
mojiretsu="、-K2011年11月06日(曜日Sun.)"
mojisu=Len(mojiretsu)
Print *Expand(mojiretsu)
Print *Expand("文字数= ") ; mojisu

For i=1 to mojisu
   Print i,*Expand(Mid(mojiretsu,i,1)), Asc(Mid(mojiretsu,i,1))
Next i

Print *Expand("何かキーを押して下さい。")
Sleep

Function Expand(s As WString) as WString Ptr
   Dim buf As WString Ptr
   Dim i As Integer
   
   buf = Allocate((Len(s) * 2) * SizeOf(WString))
   *buf = s
   For i = 1 To Len(s)
      If Asc(Mid(s, i, 1)) > 256 Then   '全角文字の場合
         *buf = *buf & Space(1)
      End If
   Next
   Expand = buf
End Function
コマンド プロンプトのタイトルバーを右クリックしてプロパティを表示 注:日本語 Windows 標準設定の、コマンド プロンプトの「ラスターフォント(Raster font ビットマップ・フォント)」では、Print で、ユニコードの文字を表示しようとすると、半角ベースの幅しか確保しません。このため、全角の文字を含む文字列を表示すると、右端が欠落します。
上の例のコードでは、2ちゃんねるの「デフォルトの名無し」さんのアイデアを拝借して、全角文字の文字数だけ、空白を、Space で追加する、ユーザ定義関数「Expand」を使って、表示させる幅をかせいでいます。

 コマンド プロンプトのタイトルバーを右クリックしてプロパティを表示させて、右画面のように、フォントを、「MS ゴシック」に変更すれば、プログラムで細工しなくても、素の print で全角文字列を表示できます。
 これも、2ちゃんねるの、別の?「デフォルトの名無し」さんに教えていただきました。

追記:WString 型は、固定長のため、引数として関数に渡すことはできますが、WString 型の戻り値は、Ptrでしか返せません。
このため、上のユーザ定義関数「Expand」は、ポインターを使っています。
ポインターを使うために、メモリに Allocate したデータは、必ず セットで Deallocate する必要があります。そうしないと、メモリ・リークの恐れがあります。
このため、「Expand」 の正しい使い方は、面倒ですが、下のようにするのが正解です。


Dim Japanese As WString * 100
Dim mojisu As Integer
Dim ResultPt As WString Ptr     ' 格納するポインタ 

Declare Function Expand(s As WString) as WString Ptr

ResultPt = Expand("今日は、世界! hello world!") ' アドレスを格納
Print *ResultPt                 ' そのアドレスにある値を表示
Deallocate(ResultPt)            ' ResultPtが指し示しているアドレスに入っている値を開放 
ResultPt = 0                    ' ポインタに0を与えてポインタからアドレスを抹消 

Japanese="今日は、世界! hello world!" 
ResultPt = Expand(Japanese)     ' アドレスを格納
Print *ResultPt ; Len(Japanese) ' そのアドレスにある値を表示
Print *ResultPt , Len(Japanese) ' そのアドレスにある値を表示
Print *ResultPt & *ResultPt     ' そのアドレスにある値を表示(なぜか & の右が表示されない)
Print Len(Japanese) & *ResultPt & Len(Japanese)    ' そのアドレスにある値を表示(なぜか & の右が表示されない)
Deallocate(ResultPt)            ' ResultPtが指し示しているアドレスに入っている値を開放 
ResultPt = 0                    ' ポインタに0を与えてポインタからアドレスを抹消 

ResultPt = Expand("何かキーを押して下さい。") ' アドレスを格納
Print *ResultPt                 ' そのアドレスにある値を表示
Deallocate(ResultPt)            ' ResultPtが指し示しているアドレスに入っている値を開放 
ResultPt = 0                    ' ポインタに0を与えてポインタからアドレスを抹消 

Sleep


ユニコードの例:
渡辺 注:どのマシン上でも、すべてのユニコード文字を見せることができる、というわけではありません。利用できる文字は、実行画面(コンソール)で現在使用中のフォントに依存します。
 
ユニコードの例
Dim textA As wstring * 80
Dim textB As WString * 80

Declare Function Expand(s As WString) as WString Ptr

textA = "Привет, мир!"
textB = "Привет,мир!"

Print " " ,*Expand(textA)      '表示結果 "Привет, мир!"
Print "mid(textA, 6, 4)" , *Expand(Mid(textA, 6, 4)) ' "т, м"
Print "mid(textA, 6, 5)" , *Expand(mid(textA, 6, 5)) ' "т, ми"
Print "mid(textA, 6, 6)" , *Expand(mid(textA, 6, 6)) ' "т, мир"
Print "mid(textA, 6, 7)" , *Expand(mid(textA, 6, 7)) ' "т, мир!"
Print "mid(textA, 6) "   , *Expand(mid(textA, 6))     'т, мир!"
Print
Print " " ,*Expand(textB)      '表示結果 "Привет,мир!"
Print "mid(textB, 6, 4)" , *Expand(mid(textB, 6, 4)) ' "т,ми"
Print "mid(textB, 6, 5)" , *Expand(mid(textB, 6, 5)) ' "т,мир"
Print "mid(textB, 6, 6)" , *Expand(mid(textB, 6, 6)) ' "т,мир!"
Print "mid(textB, 6) "   , *Expand(mid(textB, 6))     'т,мир!"

Sleep


Function Expand(s As WString) as WString Ptr
   Dim buf As WString Ptr
   Dim i As Integer

   buf = Allocate((Len(s) * 2) * SizeOf(WString))
   *buf = s
   For i = 1 To Len(s)
      If Asc(Mid(s, i, 1)) > 256 Then '全角文字の場合
         *buf = *buf & Space(1)
      End If
   Next
   Expand = buf
End Function

 
プラットホーム差:
方言差:
QBからの違い:
参照:
文字コード判定のサンプル(VB6)
http://homepage2.nifty.com/nonnon/SoftSample/SampleModJUDG.html

文字列関数
http://afsoft.jp/program/p07n.html

文字列関数に戻る
←リンク元に戻る プログラム開発関連に戻る

ページ歴史:2012-02-05 15:34:34
日本語翻訳:WATANABE Makoto、原文著作者: SysOp

ホームページのトップに戻る

表示-非営利-継承