【Golang】strings库

func Count(s, substr string) int

源码及解析 

// count计算s中substr的非重叠实例的个数。
//如果substr是空字符串,那么按照逻辑,它应该出现在s的每个字符之间,以及字符串的开头和结尾。因此,返回值应该是字符串s中的字符个数加1。
//,字符串是UTF-8编码的,这意味着字符串中的每个字符可以是1到4个字节,计算字符个数要用utf8.RuneCountInString(s)。
func Count(s, substr string) int {
	// special case
	if len(substr) == 0 {
		return utf8.RuneCountInString(s) + 1
	}
	if len(substr) == 1 {
		return bytealg.CountString(s, substr[0])
	}
	n := 0
	for {
		i := Index(s, substr)
		if i == -1 {
			return n
		}
		n++
		s = s[i+len(substr):]
	}
}

单元测试 【count_test.go】 单元测试文件名称要以_test.go结尾,函数名称由TestXxx组成(Test也可以)

func TestCount(t *testing.T) {
	// 测试空字符串
	var c int
	if c = strings.Count("", ""); c != 1 {
		println(c)
		t.Errorf("Count of empty string should be 1")
	}
	println(c)
	// 测试子串为空
	if c = strings.Count("111c", ""); c != 5 {
		println(c)
		t.Errorf("Count of empty string should be 1")
	}
	println(c)
	// 测试单个字符的子串
	if c = strings.Count("hello", "l"); c != 2 {
		println(c)
		t.Errorf("Count of 'l' in 'hello' should be 2")
	}
	println(c)

	// 测试不存在的子串
	if c = strings.Count("hello", "z"); c != 0 {
		println(c)
		t.Errorf("Count of non-existent substring should be 0")
	}
	println(c)

	// 测试较长的子串
	if c = strings.Count("hello world", "world"); c != 1 {
		println(c)
		t.Errorf("Count of 'world' in 'hello world' should be 1")
	}
	println(c)
}

前后缀

// 前缀测试 字符串s是否以前缀开头。
func HasPrefix(s, prefix string) bool {
	return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
}

//后缀测试 字符串s是否以后缀结尾。
func HasSuffix(s, suffix string) bool {
	return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
}

const maxInt int = int(^uint(0) >> 1) // 9223372036854775807


maxInt是Go语言中int类型能表示的最大值,它的值在32位系统上是2^31 - 1,在64位系统上是2^63 - 1。

// repeat返回由字符串s的count个副本组成的新字符串。
//如果count为负或者(len(s) * count)的结果 
//溢出。
func Repeat(s string, count int) string {
	switch count {
	case 0:
		return ""
	case 1:
		return s
	}

	// Since we cannot return an error on overflow,
	// we should panic if the repeat will generate an overflow.
	// See golang.org/issue/16237.
	if count < 0 {
		panic("strings: negative Repeat count")
	}
	if len(s) >= maxInt/count {
		panic("strings: Repeat output length overflow")
	}
	n := len(s) * count

 func Trim(s, cutset string) string

// trim返回字符串s的切片,其中删除了cutset中包含的所有前导和尾unicode码位。
func Trim(s, cutset string) string {
	if s == "" || cutset == "" {
		return s
	}
	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
		return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0])
	}
	if as, ok := makeASCIISet(cutset); ok {
		return trimLeftASCII(trimRightASCII(s, &as), &as)
	}
	return trimLeftUnicode(trimRightUnicode(s, cutset), cutset)
}

 

// trim left返回字符串s的切片,并删除cutset中包含的所有前缀unicode码位。 
//删除前缀,使用trim prefix代替。
func TrimLeft(s, cutset string) string {
	if s == "" || cutset == "" {
		return s
	}
	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
		return trimLeftByte(s, cutset[0])
	}
	if as, ok := makeASCIISet(cutset); ok {
		return trimLeftASCII(s, &as)
	}
	return trimLeftUnicode(s, cutset)
}


func trimLeftByte(s string, c byte) string {
	for len(s) > 0 && s[0] == c {
		s = s[1:]
	}
	return s
}

//每个 uint32 类型的元素可以存储 32 位二进制数据,这意味着每个元素可以表示 32 个 ASCII 字符的存在状态。由于 ASCII 字符集只包含 128 个字符,因此使用 8 个 uint32 元素足以表示整个 ASCII 字符集。具体来说,asciiSet 数组的每个元素对应于 ASCII 字符集中的 32 个字符。数组的第一个元素对应于 ASCII 字符集中的前 32 个字符(即字符代码从 0 到 31),第二个元素对应于接下来的 32 个字符(即字符代码从 32 到 63),以此类推。例如,如果我们想要表示字符集中包含字符 'a'(其 ASCII 码为 97),我们需要找到 'a' 在 ASCII 字符集中的位置。由于 'a' 是第 97 个字符,它位于第二个 uint32 元素的第 1 位(因为每个元素代表 32 个字符,所以 97 除以 32 的商为 3,余数为 1)。因此,我们需要将第二个 uint32 元素的第 1 位设置为 1。

type asciiSet [8]uint32

// makeASCIISet creates a set of ASCII characters and reports whether all characters in chars are ASCII.
func makeASCIISet(chars string) (as asciiSet, ok bool) {
	for i := 0; i < len(chars); i++ {
		c := chars[i]
		if c >= utf8.RuneSelf {
			return as, false
		}
		//对应的ASCII位图位置置1
		as[c/32] |= 1 << (c % 32)
	}
	return as, true
}


func trimLeftASCII(s string, as *asciiSet) string {
	for len(s) > 0 {
		if !as.contains(s[0]) {
			break
		}
		s = s[1:]
	}
	return s
}

func trimLeftUnicode(s, cutset string) string {
	for len(s) > 0 {
		r, n := rune(s[0]), 1
		if r >= utf8.RuneSelf {
			r, n = utf8.DecodeRuneInString(s)
		}
		if !ContainsRune(cutset, r) {
			break
		}
		s = s[n:]
	}
	return s
}

持续更新...

### 回答1: 在 Go 中,你可以使用 `==` 运算符来判断两个字符串是否完全匹配。例如: ``` s1 := "Hello, World" s2 := "Hello, World" if s1 == s2 { fmt.Println("The strings are equal.") } else { fmt.Println("The strings are not equal.") } ``` 上面的代码会输出 "The strings are equal.",因为两个字符串完全匹配。 注意,这种方法只能用于比较两个字符串的完全匹配,如果你想要进行模糊匹配(例如,忽略大小写,或者只匹配字符串的一部分),你可以使用 Go 的内置函数 `strings.EqualFold()` 或 `strings.Contains()`。 例如: ``` s1 := "Hello, World" s2 := "hello, world" if strings.EqualFold(s1, s2) { fmt.Println("The strings are equal (ignoring case).") } else { fmt.Println("The strings are not equal.") } if strings.Contains(s1, "World") { fmt.Println("s1 contains the string 'World'.") } ``` 上面的代码会输出 "The strings are equal (ignoring case)." 和 "s1 contains the string 'World'."。 ### 回答2: golangstrings包提供了多种方法来处理字符串,其中包括字符串的完全匹配。 要判断一个字符串是否与另一个字符串完全匹配,可以使用strings包中的Equal方法。这个方法接收两个字符串作为参数,并返回一个布尔值,表示这两个字符串是否完全相同。 下面是一个使用Equal方法判断字符串是否完全匹配的示例代码: ```go package main import ( "fmt" "strings" ) func main() { str1 := "Hello" str2 := "Hello" if strings.EqualFold(str1, str2) { fmt.Println("字符串完全匹配") } else { fmt.Println("字符串不完全匹配") } } ``` 在这个示例中,我们定义了两个字符串变量str1和str2,并将它们分别赋值为"Hello"。然后,我们使用Equal方法判断这两个字符串是否完全匹配。如果它们完全相同,我们就打印"字符串完全匹配",否则打印"字符串不完全匹配"。 在实际应用中,字符串的完全匹配可以用于判断用户输入是否与特定字符串相等,或者判断两个字符串是否相同等场景。使用strings包中的Equal方法,我们可以方便地实现这一功能。 ### 回答3: 在Golang中,可以使用strings包中的函数来进行字符串的完全匹配。具体而言,可以使用strings包中的EqualFold函数来判断两个字符串是否在不区分大小写的情况下完全匹配。 EqualFold函数的用法是:strings.EqualFold(str1, str2),其中str1和str2分别是要比较的两个字符串。如果两个字符串在不区分大小写的情况下完全匹配,该函数将返回true,否则将返回false。 除了EqualFold函数之外,还可以使用等号直接比较两个字符串,比如str1 == str2。这种方式只有当两个字符串完全相同(包括大小写)时才返回true,否则返回false。 需要注意的是,strings包中提供的函数只能进行简单的字符串比较,不能进行更为复杂的匹配操作。如果需要进行更复杂的匹配,可能需要使用正则表达式或其他相关的工具包。 总之,在Golang中,可以使用strings.EqualFold函数或直接使用等号来判断两个字符串是否完全匹配。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值