Changeset 364 for trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab
- Timestamp:
- Oct 24, 2007, 12:32:20 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab
r359 r364 16 16 仮数は1の位から下へ17桁で、小数点を含まない。そのため、誤差を無視すればVal(仮数) * 10 ^ (e - 17) = Abs(x)が成り立つ。 17 17 18 xに無限大、 無限小、非数を渡した場合の動作は未定義。18 xに無限大、非数を渡した場合の動作は未定義。 19 19 */ 20 20 Function FloatToChars(x As Double, ByRef e As Long, ByRef sign As Boolean) As String … … 76 76 '! 何も指定がない。 77 77 None = &h0 78 '! 符号、+。符号付変換[diAaEeFfGg]のとき、正の値でも符号を付ける。 78 /*! 79 符号、+。符号付変換[diAaEeFfGg]のとき、正の値でも符号を付ける。 80 AdjustFieldWidthの仕様から、Format関数郡内からAdjustFieldWidthにかけて、 81 単に数値が符号付である(負の値である)ことを示す意味でも用いられる。 82 */ 79 83 Sign = &h1 80 84 /*! 空白、空白文字。 … … 101 105 102 106 /*! 103 @brief 浮動小数点数をprintfの%e, %E 相当の変換で文字列化する関数。107 @brief 浮動小数点数をprintfの%e, %E(指数形式、十進法)相当の変換で文字列化する関数。 104 108 @author Egtra 105 109 @date 2007/09/18 … … 110 114 @return xの文字列表現 111 115 112 @todo 末尾桁四捨五入116 @todo 他の実装での末尾桁の扱いを調べる(このコードでは何もしていないので切捨となっている)。 113 117 */ 114 118 Function FormatFloatE(x As Double, d As DWord, field As DWord, flags As FormatFlags) As String 119 If d = DWORD_MAX Then 120 d = 6 121 End If 122 123 Dim e As Long, negative As Boolean 124 Dim s = FloatToChars(x, e, negative) 125 115 126 Dim sb = New System.Text.StringBuilder 116 127 With sb 117 If d = DWORD_MAX Then 118 d = 6 119 End If 120 121 Dim e As Long, negative As Boolean 122 Dim s = FloatToChars(x, e, negative) 123 124 If negative Then 125 .Append("-") 126 Else 127 If flags And Sign Then 128 .Append("+") 129 ElseIf flags And Blank Then 130 .Append(" ") 131 End If 132 End If 128 129 AppendSign(sb, negative, flags) 133 130 134 131 .Append(s[0]) … … 153 150 .Append(FormatIntegerD(e, 2, 0, Sign Or Zero)) 154 151 155 AdjustFieldWidth(sb, field, negative,flags)152 AdjustFieldWidth(sb, field, flags) 156 153 End With 157 154 FormatFloatE = sb.ToString() 158 155 End Function 159 156 157 /*! 158 @brief 浮動小数点数をprintfの%f(小数点数形式、十進法)相当の変換で文字列化する関数。 159 @author Egtra 160 @date 2007/10/23 161 @param[in] x 文字列化する浮動小数点数値。 162 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 163 @param[in] field フィールド幅。 164 @param[in] flags 書式フラグ。 165 @return xの文字列表現 166 */ 167 Function FormatFloatF(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String 168 If precision = DWORD_MAX Then 169 precision = 6 170 End If 171 172 Dim e As Long, negative As Boolean 173 Dim s = FloatToChars(x, e, negative) 174 175 Dim sb = New System.Text.StringBuilder 176 With sb 177 AppendSign(sb, negative, flags) 178 179 Dim intPartLen = e + 1 180 Dim outputDigit = 0 As DWord 181 If intPartLen >= 17 Then 182 '有効桁が全て整数部に収まる場合 183 .Append(s) 184 .Append(&h30 As StrChar, intPartLen - 17) 185 outputDigit = 17 186 ElseIf intPartLen > 0 Then 187 '有効桁の一部が整数部にかかる場合 188 .Append(s, 0, intPartLen) 189 outputDigit = intPartLen 190 Else 191 '有効桁が全く整数部にかからない場合 192 .Append(&h30 As StrChar) 193 End If 194 195 If precision > 0 Or (flags And Alt) Then 196 .Append(".") 197 198 Dim lastDigit = s.Length - outputDigit 199 If lastDigit >= precision Then '変換して得られた文字列の桁数が精度以上ある場合 200 Dim zeroDigit = 0 201 If intPartLen < 0 Then 202 '1.23e-4 = 0.000123のように指数が負のため小数点以下に0が続く場合 203 zeroDigit = System.Math.Min(-intPartLen As DWord, precision) 204 .Append(&h30 As StrChar, zeroDigit As Long) 205 End If 206 .Append(s, outputDigit, (precision - zeroDigit) As Long) 207 Else 208 .Append(s, outputDigit, lastDigit) 209 .Append(&h30 As StrChar, (precision - lastDigit) As Long) '残りの桁は0埋め 210 End If 211 End If 212 AdjustFieldWidth(sb, field, flags) 213 End With 214 FormatFloatF = sb.ToString() 215 End Function 216 217 /*! 218 @brief 先頭に符号もしくはその分の空白を出力する。FormatFloat用。 219 @author Egtra 220 @date 2007/10/23 221 @param[in, out] sb 出力先 222 @param[in] negative 符号 223 @param[in, out] flags フラグ。negative = Trueなら、Signを立てて返す。 224 */ 225 Sub AppendSign(sb As System.Text.StringBuilder, negative As Boolean, ByRef flags As FormatFlags) 226 With sb 227 If negative Then 228 .Append("-") 229 flags Or= Sign 230 Else 231 If flags And Sign Then 232 .Append("+") 233 ElseIf flags And Blank Then 234 .Append(" ") 235 End If 236 End If 237 End With 238 End Sub 239 160 240 '! DWordの最大値4294967295の文字数 - 1。FormatIntegerU内で使用。 161 241 Const MaxSizeU = 9 162 242 163 243 /*! 164 @brief 符号無し整数をprintfの%u 相当の変換で文字列化する関数。244 @brief 符号無し整数をprintfの%u(十進法表現)相当の変換で文字列化する関数。 165 245 @author Egtra 166 246 @date 2007/09/18 … … 182 262 183 263 /*! 184 @brief 符号有り整数をprintfの% u相当の変換で文字列化する関数。264 @brief 符号有り整数をprintfの%d(十進法表現)相当の変換で文字列化する関数。 185 265 @author Egtra 186 266 @date 2007/10/13 … … 198 278 dwX = (-x) As DWord 199 279 signChar = Asc("-") 280 flags Or= Sign 200 281 Else 201 282 dwX = x As DWord … … 220 301 @param[in] signChar 符号部分の文字。\0なら存在しないとして扱われる。 221 302 @return xの文字列表現 303 304 signCharに何らかの値を指定するときには、必ずflagsにSignまたはBlankを指定すること。 305 さもないと、フィールド幅を指定したときに正しく整形されなくなる。 222 306 */ 223 307 Function FormatInteger(x As DWord, d As DWord, field As DWord, flags As FormatFlags, signChar As StrChar) As String … … 245 329 .Append(buf, i + 1, len) 246 330 247 AdjustFieldWidth(sb, field, signChar <> 0,flags)331 AdjustFieldWidth(sb, field, flags) 248 332 End With 249 333 FormatInteger = sb.ToString() 250 334 End Function 251 335 252 253 /*! 254 DWordの最大値の八進法表現37777777777の文字数 - 1。FormatIntegerO内で使用。 255 */ 256 Const MaxSizeO = 10 257 258 /*! 259 @brief 整数をprintfの%o相当の変換で文字列化する関数。 336 /*! 337 DWordの最大値の八進法表現37777777777の文字数 - 1 + 1。FormatIntegerO内で使用。 338 上の式で1を加えているのは、八進接頭辞の分。 339 */ 340 Const MaxSizeO = 11 341 342 Dim TraitsIntegerO As IntegerConvertTraits 343 With TraitsIntegerO 344 .Convert = AddressOf(IntegerO_Convert) 345 .Prefix = AddressOf(IntegerO_Prefix) 346 .MaxSize = MaxSizeO 347 End With 348 349 /*! 350 @brief 符号無し整数をprintfの%o(八進法表現)相当の変換で文字列化する関数。 260 351 @author Egtra 261 352 @date 2007/10/19 … … 267 358 */ 268 359 Function FormatIntegerO(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String 269 PreProcessFormatInteger(d, flags) 270 271 Dim sb = New System.Text.StringBuilder 272 With sb 273 Dim buf[MaxSizeO] As StrChar 274 Dim i = MaxSizeO 275 While x <> 0 276 buf[i] = ((x And &o7) + &h30) As StrChar 277 x >>= 3 278 i-- 279 Wend 280 281 Dim len = (MaxSizeO - i) As Long 282 283 If flags And Alt Then 284 .Append(&h30 As StrChar) 285 len++ 286 End If 287 288 If len < d Then 289 .Append(&h30 As StrChar, d - len) 290 End If 291 292 .Append(buf, i + 1, len) 293 294 AdjustFieldWidth(sb, field, False, flags And (Not (Sign Or Blank))) 295 End With 296 FormatIntegerO = sb.ToString() 360 FormatIntegerO = FormatIntegerEx(TraitsIntegerO, x, d, field, flags) 361 End Function 362 363 Function IntegerO_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord 364 Dim x = xq As DWord 365 Dim i = MaxSizeO 366 While x <> 0 367 buf[i] = ((x And &o7) + &h30) As StrChar 368 x >>= 3 369 i-- 370 Wend 371 If flags And Alt Then 372 buf[i] = &h30 373 i-- 374 End If 375 IntegerO_Convert = i 376 End Function 377 378 Function IntegerO_Prefix(x As QWord, flags As FormatFlags) As String 297 379 End Function 298 380 … … 302 384 Const MaxSizeX = 7 303 385 304 /*! 305 @brief 整数をprintfの%x, %X相当の変換で文字列化する関数。 386 Dim TraitsIntegerX As IntegerConvertTraits 387 With TraitsIntegerX 388 .Convert = AddressOf(IntegerX_Convert) 389 .Prefix = AddressOf(IntegerX_Prefix) 390 .MaxSize = MaxSizeX 391 End With 392 393 /*! 394 @brief 整数をprintfの%x, %X(十六進法)相当の変換で文字列化する関数。 306 395 @author Egtra 307 396 @date 2007/10/19 … … 313 402 */ 314 403 Function FormatIntegerX(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String 404 FormatIntegerX = FormatIntegerEx(TraitsIntegerX, x, d, field, flags) 405 End Function 406 407 Function IntegerX_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord 408 Dim i = MaxSizeX 409 Dim x = xq As DWord 410 While x <> 0 411 buf[i] = _System_HexadecimalTable[x And &h0f] 412 x >>= 4 413 i-- 414 Wend 415 IntegerX_Convert = i 416 End Function 417 418 Function IntegerX_Prefix(x As QWord, flags As FormatFlags) As String 419 If flags And Alt Then 420 If x <> 0 Then 421 IntegerX_Prefix = "0X" 422 End If 423 End If 424 End Function 425 426 Type IntegerConvertTraits 427 Convert As *Function(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord 428 Prefix As *Function(x As QWord, flags As FormatFlags) As String 429 MaxSize As DWord 430 End Type 431 432 /*! 433 @brief 整数変換全てを行う関数。これを雛形とし、形式毎の差異はIntegerConvertTraitsで表現する。 434 @author Egtra 435 @date 2007/10/22 436 @param[in] tr 特性情報。 437 @param[in] x 変換元の数値。 438 @param[in] d 精度。ここでは最低限出力する桁数。 439 @param[in] field フィールド幅。 440 @param[in] flags フラグ。 441 */ 442 Function FormatIntegerEx(ByRef tr As IntegerConvertTraits, x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String 315 443 PreProcessFormatInteger(d, flags) 316 444 317 445 Dim sb = New System.Text.StringBuilder 318 446 With sb 447 Dim prefixFunc = tr.Prefix 448 Dim prefix = prefixFunc(x, flags) 449 sb.Append(prefix) 450 319 451 Dim prefixLen = 0 As DWord 320 If (flags And Alt) Then 321 If x <> 0 Then 322 .Append("0X") 323 prefixLen = 2 324 End If 325 End If 326 327 Dim buf[MaxSizeX] As StrChar 328 Dim i = MaxSizeX 329 While x <> 0 330 buf[i] = _System_HexadecimalTable[x And &h0f] 331 x >>= 4 332 i-- 333 Wend 334 335 Dim len = (MaxSizeX - i) As Long 336 452 If String.IsNullOrEmpty(prefix) = False Then 453 prefixLen = prefix.Length As DWord 454 End If 455 456 Dim buf = GC_malloc_atomic((tr.MaxSize + 1) * SizeOf (StrChar)) As *StrChar 457 Dim convertFunc = tr.Convert 458 Dim bufStartPos = convertFunc(buf, x, flags) 459 460 Dim len = (tr.MaxSize - bufStartPos) As Long 337 461 If len < d Then 338 462 .Append(&h30 As StrChar, d - len) 339 463 End If 340 464 341 .Append(buf, i+ 1, len)342 343 AdjustFieldWidth(sb, field, False,flags And (Not (Sign Or Blank)), prefixLen)465 .Append(buf, bufStartPos + 1, len) 466 467 AdjustFieldWidth(sb, field, flags And (Not (Sign Or Blank)), prefixLen) 344 468 End With 345 FormatInteger X= sb.ToString()469 FormatIntegerEx = sb.ToString() 346 470 347 471 If (flags And Cap) = 0 Then 348 FormatInteger X = FormatIntegerX.ToLower()472 FormatIntegerEx = FormatIntegerEx.ToLower() 349 473 End If 350 474 End Function … … 365 489 Else 366 490 '精度が指定されているとき、ゼロフラグは無視される。 367 ' 左揃えのときも無視されるが、それはAdjustFieldWidthが行ってくれる。491 '仕様上、左揃えのときも無視されるが、それはAdjustFieldWidthが行ってくれる。 368 492 flags And= Not Zero 369 493 End If … … 377 501 @param [in] flags フラグ 378 502 @param [in] prefixLen (あれば)接頭辞の文字数。ゼロ埋めする際、この数だけ挿入位置を後ろにする。 379 */ 380 Sub AdjustFieldWidth(sb As System.Text.StringBuilder, field As DWord, hasSign As Boolean, flags As FormatFlags, prefixLen = 0 As DWord) 503 sbが"-1"のように負符号を持っている場合は、呼出元でSignフラグ(またはBlank)を立てること。 504 */ 505 Sub AdjustFieldWidth(sb As System.Text.StringBuilder, field As DWord, flags As FormatFlags, prefixLen = 0 As DWord) 381 506 With sb 382 507 If .Length < field Then … … 387 512 Dim insPos As Long 388 513 If (flags And Zero) <> 0 Then 389 If ( (flags And Blank) Or (flags And Sign) Or hasSign) Then514 If (flags And Blank) Or (flags And Sign) Then 390 515 insPos++ 391 516 End If
Note:
See TracChangeset
for help on using the changeset viewer.