Strings and Chars - HimxhMC/HimDSL GitHub Wiki

字符串与字符 / Strings and Chars

字符串是什么 / What a String Is

字符串是一串字符,用双引号包围。脚本里几乎所有跟玩家交互的文本都是字符串:广播内容、物品名、提示消息、配置项。本章讲怎么处理这些文本。

A string is a sequence of characters, wrapped in double quotes. Almost all player-facing text is a string: broadcasts, item names, prompts, config values. This chapter covers how to work with them.

string s = "Hello, Steve";
string empty = "";
string zh = "你好";

空字符串 "" 是合法的,长度为 0。不要和 null 混淆——null 表示"没有值","" 表示"有值,但是空的"。两者比较的结果不同。

An empty string "" is valid and has length 0. Do not confuse it with null — null means "no value", "" means "a value, but empty". They compare differently.


拼接 / Concatenation

用 + 拼接字符串:

Concatenate with +:

string a = "Hello, " + "Steve";       // "Hello, Steve"
string b = "血量: " + 20;              // "血量: 20"
string c = "第 " + 1 + " 名";          // "第 1 名"

任何类型和字符串用 + 连接,都会先转成字符串:

Any type concatenated with a string is first converted to text:

string s = "hp=" + 20.5 + ", alive=" + true;   // "hp=20.5, alive=true"

+= 也支持:

+= also works:

string msg = "警告";
msg += ":血量低";        // "警告:血量低"

取长度 / Length

length() 返回字符串中的字符数:

length() returns the number of characters:

int n = "Hello".length();     // 5
int m = "".length();          // 0
int z = "你好".length();       // 2,中文也算一个字符

length() 是方法,写在字符串后面。这是一种"对象式"调用。内置函数章节里会看到同名函数 length(s),但推荐用方法形式,因为它直接表达"这是对 s 本身的操作"。

length() is a method, written after the string. This is an "object-style" call. The built-ins chapter also lists a length(s) function, but the method form is preferred — it expresses that this is an operation on s itself.


大小写转换 / Case Conversion

string a = "Hello".toUpperCase();     // "HELLO"
string b = "Hello".toLowerCase();     // "hello"

常用于做不区分大小写的比较:

Common for case-insensitive comparison:

string input = "Steve";
if (input.toLowerCase() == "steve") {
    runcmd("CONSOLE", "say 匹配");
}

去除空白 / Trimming

trim() 去掉字符串首尾的空白字符(空格、制表符、换行),中间的空格不动:

trim() removes whitespace (spaces, tabs, newlines) from both ends. Internal spaces are kept:

string a = "  hello  ".trim();     // "hello"
string b = "a b c".trim();         // "a b c",中间空格保留

处理从玩家或文件读入的文本时,trim() 是必备的。命令行参数尤其容易带上多余空格。

trim() is essential when handling text from players or files. Command-line arguments often carry stray spaces.


查找与判断 / Searching

contains 判断是否包含子串:

contains checks for a substring:

bool a = "Hello, Steve".contains("Steve");   // true
bool b = "Hello".contains("xyz");            // false

startsWith 和 endsWith 判断开头和结尾:

startsWith and endsWith check prefixes and suffixes:

bool a = "Hello".startsWith("He");     // true
bool b = "Hello".endsWith("lo");       // true

这三个方法区分大小写。要不区分就先 toLowerCase():

These three are case-sensitive. For case-insensitive matching, call toLowerCase() first:

if (cmd.toLowerCase().startsWith("say")) {
    // 匹配 "say"、"SAY"、"Say" 等
}

替换 / Replace

replace(old, new) 把所有出现的 old 换成 new:

replace(old, new) replaces every occurrence of old with new:

string a = "Hello, Steve".replace("Steve", "Alex");   // "Hello, Alex"
string b = "a.b.c".replace(".", "-");                 // "a-b-c"

replace 不会修改原字符串,而是返回一个新字符串。这是理解字符串行为的关键:字符串是不可变的,所有看似"修改"的方法,其实都是返回新值。

replace does not modify the original string; it returns a new one. This is key: strings are immutable. Every operation that looks like "modification" returns a new value.

string s = "Hello";
s.replace("l", "L");        // 返回值 "HeLLo",但 s 本身不变
runcmd("CONSOLE", "say " + s);    // 仍然是 "Hello"

s = s.replace("l", "L");    // 要生效必须赋回 s

分割 / Split

split(分隔符) 把字符串拆成多个部分,返回列表:

split(separator) splits the string into parts, returning a list:

var parts = "a,b,c".split(",");
// parts 是 ["a", "b", "c"]
int n = parts.size();          // 3
string first = parts.get(0);   // "a"

分隔符支持正则表达式。日常用普通字符就够了,例如 ","、" "、"|"。要注意几个正则特殊字符(+、*、.、| 等)如果作为普通分隔符使用,需要加反斜杠转义:

The separator supports regular expressions. For everyday use, plain characters suffice: ",", " ", "|". Note that a few regex metacharacters (+, *, ., |, etc.) must be backslash-escaped when used literally:

var a = "a.b.c".split("\\.");      // ["a", "b", "c"],正确的
var b = "a.b.c".split(".");        // 结果是空列表,"." 匹配任何字符

字符 / Characters

单个字符用单引号包围,类型是 char:

A single character is wrapped in single quotes and has type char:

char c = 'A';
char zh = '中';
char nl = '\n';

字符和字符串的区别:

  • 字符串是多个字符的序列,长度可以任意。
  • 字符是单个,长度永远是 1。
  • 字符串用双引号,字符用单引号。

Differences:

  • A string is a sequence of characters, any length.
  • A char is one character; its length is always 1.
  • Strings use double quotes; chars use single quotes.

从字符串取字符 / Getting a Char from a String

用下标 [i] 取字符串的第 i 个字符(下标从 0 开始):

Use [i] to get the i-th character of a string (0-indexed):

string s = "Hello";
char first = s[0];       // 'H'
char third = s[2];       // 'l'

越界会报错。取之前先检查长度:

Out-of-bounds errors. Check length first:

if (s.length() > 0) {
    char first = s[0];
    runcmd("CONSOLE", "say 首字母: " + first);
}

字符串的字符替换 / Replacing a Char in a String

字符串本身不可变,但可以通过下标赋值创建一个新字符串:

Strings are immutable, but you can create a new one via index assignment:

string s = "Hello";
s[0] = 'J';              // s 变成 "Jello"

这一条看似违反"字符串不可变",其实是语法层面自动做了"取原值、改一个字符、写回"。底层的处理不影响使用,但要知道每次这样做都会创建一个新字符串。循环里频繁修改字符串开销较大。

This looks like it violates immutability but is really "read, modify one char, write back" under the hood. Every such operation creates a new string; frequent in-loop edits are costly.


数值与字符串互转 / Converting Numbers and Strings

把字符串转成数字:

String to number:

int n = toInt("42");         // 42
double d = toDouble("3.14"); // 3.14

转换失败不报错,返回默认值:

On failure, no error, a default is returned:

int a = toInt("abc");        // 0
double b = toDouble("xyz");  // 0.0

如果不确定输入是否合法,可以先验证:

When unsure about input validity, validate first:

string input = "abc";
if (input.contains(".")) {
    double v = toDouble(input);
    // ...
} else {
    int v = toInt(input);
    // ...
}

数字转字符串更简单,直接拼空字符串就行:

Number to string is simple: concatenate with an empty string:

string a = "" + 42;          // "42"
string b = "" + 3.14;        // "3.14"

或者用 toString:

Or use toString:

string c = toString(42);     // "42"

常用模式 / Common Patterns

检查空字符串 / Checking for Empty

string s = $player(p, name)$;
if (s == null || s == "") {
    runcmd("CONSOLE", "say 未知玩家");
}

null 和 "" 都要检查,它们不相等。

Check both null and ""; they are not equal.

拼接列表 / Joining a List

HimDSL 没有内置 join,手动循环:

There is no built-in join; loop manually:

var names = {"Steve", "Alex", "Herobrine"};
string result = "";
for (int i = 0; i < names.size(); i = i + 1) {
    if (i > 0) result += ", ";
    result += names.get(i);
}
// result 是 "Steve, Alex, Herobrine"

处理多行文本 / Multi-line Text

\n 是换行符,可以拼进字符串:

\n is a newline; concatenate it into strings:

string msg = "第一行" + "\n" + "第二行";

但注意:大多数 Minecraft 聊天组件不支持真正的换行,\n 只会显示成一个空格或方块。如果需要多行消息,用多条命令分别发送。

However, most Minecraft chat components do not render real newlines; \n shows as a space or placeholder. For multiple lines, send multiple commands.


小结 / Summary

  • 字符串用双引号,字符用单引号。

  • 字符串不可变,所有方法返回新值。

  • 常用方法:length、toUpperCase、toLowerCase、trim、contains、startsWith、endsWith、replace、split。

  • split 参数支持正则,特殊字符要转义。

  • s[i] 取字符,s[i] = c 改字符。

  • toInt / toDouble 转换失败返回默认值,不报错。

  • 检查字符串前先想清楚是否可能出现 null。

  • Strings use double quotes; chars use single quotes.

  • Strings are immutable; methods return new values.

  • Common methods: length, toUpperCase, toLowerCase, trim, contains, startsWith, endsWith, replace, split.

  • split takes a regex; escape metacharacters.

  • s[i] reads a char; s[i] = c writes one.

  • toInt / toDouble return defaults on failure.

  • Always consider whether a string could be null.


下一步 / Next Steps

下一章 [控制流 / Control Flow] 从最基础的 if / else 开始,到 for、while、do-while,再到 break、continue、return,把脚本里的"分支与重复"讲透。

Next up is [控制流 / Control Flow], from the simplest if / else, through for, while, do-while, to break, continue, and return — the "branching and repetition" of scripts.