# 格式化字符串

请参考：[数据类型 - 字符串](../../../language-reference/datatype/datatype.html#varstring)

## 一. 格式化函数

string.format 用来格式化字符串(按指定的规则连接字符串或其他变量并返回新的字符串) 。使用方法与 C 语言的 printf 函数类似( 实际上很多编程语言中都有类似的格式化函数 ) 。
  
`result = string.format(fm,...);`

第一个字符串参数 @fm 指定输出的格式，每个 `%` 符号后面是一个格式化表达式，每个格式化表达式按顺序对应后面的参数。

所以用了 n 个格式化表达式，就必须在后面添加 n 个参数。  
  
下面是一个简单的例子：

```aardio
var int = 123;
var str = "字符串"

//下面的 %s 对应参数 str, %i 对应参数 int
var result = string.format("这是字符串:'%s' 这是数字值 %i",str,int);
 
//%05i表示格式化为至少五位的数字,不足在前面补 0
var str = string.format("%05i",int); 
```  

## 二. 格式化语法 

格式化表达式：

`%[零个或多个标志][最小字段宽度][.精度]格式化代码`

> 注意: 上面的方括号 `[]` 表示可选部分。 
  
### 格式化代码 <a id="type" href="#type">&#x23;</a>

- 格式化代码 `%g`,`%G`
参数：数字值(number)  
含义：参数以 `%f` 或 `%e` （如G则`%E`）的格式打印，取决于它的值。如果指数大于等于 -4 但小于精度字段就使用 `%f` 格式，否则使用指数格式。

  aardio 的数值类型是 64 位浮点数（ double ）, `%g` 通是最适合用于格式化这种浮点数的格式符。`%g` 的精度参数指定的是有效数字位数，可以在指定精度内避免科学计数法，并且可以避免在小数后补零。而浮点格式（ `%f` ）虽只能显示为指定的小数位数，不足补零（当然有时候有这个需求）。aardio 的数值转换为字符串默认使用的格式符 `%.14g`，因此大于等于 `1e14` (即 1 后面跟 14 个 0) 或者小于 `1e-4` (即 0.0001)的数值转换为字符串以后会以科学计数法显示。我们可以修改这个格式符，例如使用 `string.format("%.16g",1e15 )` 得到的字符串可以避免科学计数法。如果希望数值转换为字符串总是避免科学计数法，并且可以自适应小数位数而不补 0，则需要调用 `math.stringify( number )` 函数。

  注意浮点数表示的有效整数是有上限的，更大的 64 位无符号整数可以使用 math.size64 对象处理（支持 tostring ），超出 64 位无符号整数表示范围的大数可以调用 math.bignum 或者 System.Numerics.BigInteger 处理。

- 格式化代码 `%f`  
参数：数字值(number)  
含义：参数按照的常规浮点格式输出。精度字段决定小数点后面的位数（不足补 0），缺省值是 6。

  如果希望始终以浮点格式输出（不使用科学计数法）并且避免小数补 0，可以使用 `math.stringify( number )` 函数。

- 格式化代码 `%c`  
参数：数字值(number)  
含义：参数被裁剪为8位字节码并作为字符进行打印。

- 格式化代码 `%i`,`%d`  
参数：数字值(number)  
含义：参数作为一个十进制整数打印。如果给出了精度而且值的位数小于精度位数，前面就用 0 填充。

- 格式化代码 `%u`,`%o`,`%b`,`%x`,`%X`  
参数：数字值(number)  
含义：参数作为一个无符号数字值打印，`%u` 使用十进制，`%o` 使用八进制，`%b` 使用二进制，`%x` 或 `%X`  使用十六进制，两者的区别是 `%x` 约定使用小写的 abcdef，而 `%X` 约定使用大写的 ABCDEF。 `%u`,`%o`,`%x`,`%X`  等格式代码也可用于格式化 math.size64 对象（按64位无符号数值格式化 ）。

- 格式化代码 `%e`,`%E`  
参数：数字值(number)  
含义：参数根据指数形式打印。例如，6.023000e23 是使用代码 `%e` 输出，6.023000E23 是使用代码 `%E` 输出。小数点后面的位数由精度字段决定，缺省值是 6 。

- 格式化代码 `%s`  
参数：字符串值(string)  
含义：打印一个字符串。

- 格式化代码 `%q`  
参数：(无)  
含义：打印一个字符串，并将字符串置于一对引号中，如果字符串中包含引号换行等自动添加转义符。如果要读取一个字符串传为代码。为避免用户恶意注入引号等特殊字符，可以使用%q进行格式化。

- 格式化代码 `%%` 
参数：(无)  
含义：取消%转义打印一个%字符,即用%%表示本来的%。

### 格式化标志 <a id="flags" href="#flags">&#x23;</a>

- 标志 `-`  
含义：如果在填充宽度前加上 `-` 号，则值在填充结果中左对齐（缺省情况下是右对齐）。

- 标志 `0` 
含义：当数值为右对齐时，缺省情况下是使用空格填充值左边未使用的列。这个标志表示用零填充，它可用于格式化代码 d,i,u,o,x,X,e,E,f,g 和 G 。  
使用格式化代码 d,i,u,o,x 和 X 时，如果给出了精度字段，标志`0` 就被忽略。如果格式代码中出现了负号，标志 `0` 也没有效果。

- 标志 `+`  
含义：当用于一个格式化某个有符号值代码时，如果值非负，正号标志就会给它加上一个正号。如果该值为负，就像往常一样显示一个负号。在  
缺省情况下，正号并不会显示。

- 标志 空格  
含义：只用于转换有符号值的代码。当值非负时，这个标志把一个空格添加到它开始的位置。注意这个标志和正号标志是相互排斥的，如果两个  
同时给出，空格标志便被忽略。

- 扩展标志 `#`  
含义：用于选择某些代码的另一种转换形式。  

示例：   
  - `#o` 保证产生的值以一个零开头  
  - `#x`,`#X` 在非零值前面加 `0x` 前缀（ `%#X` 则为 `0X`）  
  - `#e`,`#E`,`#f` 确保结果始终包含一个小数点，即使它后面没有数字  
  - `#g`,`#G` 和上面的 `#e`, `#E` 和 `#f` 代码相同。另外，缀尾的 0 并不从小数中去除。

### 字段宽度 <a id="width" href="#width">&#x23;</a>


字段宽度是一个十进制整数，用于指定将出现在结果中的最小字符数。如果值的字符数少于字段宽度，就对它进行填充以增加长度。  
  
### 精度 <a id="precision" href="#precision">&#x23;</a>

精度以一个句点开头，后面跟一个可选的十进制数。如果未给出整数，精度的缺省值为零。

对于格式化代码为 d,i,u,o,x 或 X 的转换，精度字段指定将出现在结果中的最小的数字个数并覆盖零标志。如果转换后的值的位数小于宽度，就在它的前面插入零。如果值为零且精度也为零，则转换结果就不会产生数字。

对于格式化代码 e,E 或 f 类型的转换，精度决定将出现在小数点之后的数字位数。

对于格式化代码 g 和 G 的转换，它指定将出现在结果中的最大有效位数。

格式化代码为 s 的转换，精度指定将被转换的最多的字符数。

### 格式语法示例   

| 格式代码 | A | ABC | ABCDEFGH |
| --- | --- | --- | --- |
| `%s` | A | ABC | ABCDEFGH |
| `%5s` | ####A | ##ABC | ABCDEFGH |
| `%.5s` | A | ABC | ABCDE |
| `%5.5s` | ####A | ##ABC | ABCDE |
| `%-5s` | A#### | ABC## | ABCDEFGH |


| `格式代码` | 1 | \-12 | 12345 | 123456789 |
| --- | --- | --- | --- | --- |
| `%d` | 1 | \-12 | 12345 | 123456789 |
| `%6d` | #####1 | ###-12 | #12345 | 123456789 |
| `%.4d` | 0001 | \-0012 | 12345 | 123456789 |
| `%6.4d` | ##0001 | #-0012 | #12345 | 123456789 |
| `%-4d` | 1#### | \-12# | 12345 | 123456789 |
| `%04d` | 0001 | \-012 | 12345 | 123456789 |
| `%+d` | +1 | \-12 | +12345 | +123456789 |

  

| `格式代码` | 1 | .01 | .00012345 | 12345.6789 |
| --- | --- | --- | --- | --- |
| `%f` | 1.000000 | 0.010000 | 0.000123 | 12345.678900 |
| `%10.2f` | ######1.00 | #####0.01 | ######0.00 | ##12345.67 |
| `%e` | 1.000000e+00 | 1.000000e-02 | 1.234500e-04 | 1.234568e+04 |
| `%.4e` | 1.0000e+00 | 1.0000e-02 | 1.2345e-04 | 1.2346e+04 |
| `%g` | 1 | 0.01 | 0.00012345 | 12345.7 |

  

| `格式代码` | 6.023e23 |
| --- | --- |
| `%f` | 60229999999999975882752.000000 |
| `%10.2f` | 60229999999999975882752.00 |
| `%e` | 6.023000e+23 |
| `%.4e` | 6.0230e+23 |
| `%g` | 6.023e+23 |

用上面的格式化函数可以轻松实现数字的进制转换( 请参考：[数值与进制](../../../language-reference/datatype/number.html) )
  
```aardio
import console; 

//数字转换为二进制字符串
str = string.format("2#%b",23 );
console.log(str)

//二进制字符串转换为数字
n = tonumber(str,2)

//数字转换为八进制字符串
str = string.format("8#%o",23 );
console.log(str)

//八进制字符串转换为数字
n = tonumber(str,8)

//数字转换为十六进制字符串
str = string.format("%#x",23 );
console.log(str)

//十六进制字符串转换为数字
n = tonumber(str,16)

console.pause();
```