字符串在开发中经常用到,包括用户的输入,数据库读取的数据等,我们经常需要对字符串进行分割连接转换等操作,我们可以通过Go标准库中的stringsstrconv两个包中的函数进行相应的操作。

字符串操作常用方法总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package main

import (
    "fmt"
    "strings"
)

func main() {
    // func Contains(s, substr string) bool
    // Contains 字符串s中是否包含substr,返回bool值
    fmt.Println(strings.Contains("seafood", "foo"))
    fmt.Println(strings.Contains("seafood", "bar"))

    // func Join(a []string, sep string) string
    // Join 字符串连接,将slice a通过sep连接
    fmt.Println(strings.Join([]string{"I", "Love", "You"}, "-->"))

    // func Index(s, substr string) int
    // Index 在字符串s中查找substr所在的位置,返回位置值,找不到返回-1
    fmt.Println(strings.Index("zhaoxu", "ox"))
    fmt.Println(strings.Index("zhaoxu", "oocc"))

    // func Repeat(s string, count int) string
    // Repeat 重复s,count次,返回重复的字符串
    fmt.Println(strings.Repeat("Love", 5))

    // func Replace(s, old, new string, n int) string
    // Replace 在字符串s中,把old字符串替换成new字符串,替换n次(n<0表示全部替换),最后返回替换后的字符串
    fmt.Println(strings.Replace("ccoo ccoo ccoo", "co", "xo", 2))
    fmt.Println(strings.Replace("ccoo ccoo ccoo", "co", "xo", -1))

    // Split(s, sep string) []string
    // Split 把字符串按照sep分割,返回分割后的slice
    fmt.Println(strings.Split("I love you", " "))
    fmt.Println(strings.Split(" zxy ", ""))

    // Trim(s string, cutset string) string
    // Trim 将s字符串的首尾去除cutset指定的字符串
    fmt.Println(strings.Trim("!!!!!I Love you!!!!!", "!"))

    // func Fields(s string) []string
    // Fields 去除s字符串的空格字符,并按照空格分割返回slice
    fmt.Println(strings.Fields("  I love you   !  "))
}

// 运行结果
// true
// false
// I-->Love-->You
// 3
// -1
// LoveLoveLoveLoveLove
// cxoo cxoo ccoo
// cxoo cxoo cxoo
// [I love you]
// [  z x y  ]
// I Love you
// [I love you !]

字符串转换常用方法总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package main

import (
    "fmt"
    "strconv"
)

func checkError(e error) {
    if e != nil {
        fmt.Println(e)
    }
}

func main() {
    // Append 系列函数将整数等转换成字符串后,添加到现有的字节数组中
    str := make([]byte, 0, 100)

    // func AppendInt(dst []byte, i int64, base int) []byte
    str = strconv.AppendInt(str, 123, 10)
    fmt.Println(string(str))

    // func AppendFloat(dst []byte, f float64, fmt byte, prec, bitSize int) []byte
    str = strconv.AppendFloat(str, 3.141592, 'f', 4, 64) // 'f'换成'e'便是科学计数法
    fmt.Println(string(str))

    // func AppendBool(dst []byte, b bool) []byte
    str = strconv.AppendBool(str, false) // <==> append(str, "false"...)
    fmt.Println(string(str))

    // func AppendQuote(dst []byte, s string) []byte
    str = strconv.AppendQuote(str, "hello world") // 包括双引号
    fmt.Println(string(str))

    // func AppendQuoteRune(dst []byte, r rune) []byte
    str = strconv.AppendQuoteRune(str, '当')
    fmt.Println(string(str))

    // Format 系列函数把其他类型转换成字符串
    // func FormatBool(b bool) string
    a := strconv.FormatBool(true) // bool类型转换成字符串

    // func FormatInt(i int64, base int) string
    b := strconv.FormatInt(10, 2) // 整数10转换成二进制的字符串

    // func FormatUint(i uint64, base int) string
    c := strconv.FormatUint(123, 10) // 无符号intint类型转换成十进制的字符串

    // func Itoa(i int) string
    d := strconv.Itoa(10) // <==> strconv.FormatInt(int64(i), 10)
    fmt.Println(a, b, c, d)

    // Parse 系列函数把字符串转换为其他类型
    // func ParseBool(str string) (bool, error)
    aa, err := strconv.ParseBool("false")
    checkError(err)

    // func ParseFloat(s string, bitSize int) (float64, error)
    bb, err := strconv.ParseFloat("123.23", 64)
    checkError(err)

    // func ParseInt(s string, base int, bitSize int) (i int64, err error)
    cc, err := strconv.ParseInt("1011", 2, 64)
    checkError(err)

    // func ParseUint(s string, base int, bitSize int) (uint64, error)
    dd, err := strconv.ParseUint("12345", 10, 64)
    checkError(err)

    // func Atoi(s string) (int, error)
    ee, err := strconv.Atoi("1023") // <==> ParseInt(s, 10, 0)
    checkError(err)
    fmt.Println(aa, bb, cc, dd, ee) //false 123.23 11 12345 1023
}

// 运行结果
// 123
// 1233.1416
// 1233.1416false
// 1233.1416false"hello world"
// 1233.1416false"hello world"'当'
// true 1010 123 10
// false 123.23 11 12345 1023

在LeetCode找了两个题目简单的练练手

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main

import (
    "fmt"
    "strconv"
    "strings"
)

/*
    【字符串操作】
    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

    示例 1:
    输入: "abcabcbb"
    输出: 3
    解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

    示例 2:
    输入: "bbbbb"
    输出: 1
    解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

    示例 3:
    输入: "pwwkew"
    输出: 3
    解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
        请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
*/

func lengthOfLongestSubstring(s string) int {
    var Length int // 最大长度
    var s1 string  // 不含重复字符的字符串
    // 双指针想法,检查s中的字符是否在s1中,如果不在,则记录在s1中并计算长度,否则左指针定位在重复字符的位置
    for left, right := 0, 0; right < len(s); right++ {
        if index := strings.IndexByte(s1, s[right]); index != -1 {
            left += index + 1
        }
        s1 = s[left : right+1]
        if len(s1) > Length {
            Length = len(s1)
        }
    }
    return Length
}

/*
    【本来是想用字符串转换做的,但是对于较大数会出现溢出的情况!!】
    给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

    解题思路:
            9  8
    ×       2  1
    -------------
           (9)(8)  <---- 第1趟: 98×1的每一位结果
      (18)(16)     <---- 第2趟: 98×2的每一位结果
    -------------
      (18)(25)(8)  <---- 这里就是相对位的和,还没有累加进位
*/

// BigMulti 大数相乘
func BigMulti(a, b string) string {
    if a == "0" || b == "0" {
        return "0"
    }

    // string转换成[]byte,容易取得相应位上的具体值
    bsi := []byte(a) // 强制类型转换
    bsj := []byte(b)

    //两数相乘,结果位数不会超过两乘数位数和,即temp的长度只可能为 len(num1)+len(num2) 或 len(num1)+len(num2)-1
    temp := make([]int, len(bsi)+len(bsj)) // [0 0 0 ... 0 0]

    // 选最大的,免得位数不够
    for i := 0; i < len(bsi); i++ {
        for j := 0; j < len(bsj); j++ {
            // 对应每个位上的乘积,直接累加存入 temp 中相应的位置
            temp[i+j+1] += int(bsi[i]-'0') * int(bsj[j]-'0')
        }
    }

    // 统一处理进位
    for i := len(temp) - 1; i > 0; i-- {
        temp[i-1] += temp[i] / 10 // 取整:对该结果进位(进到前一位)
        temp[i] = temp[i] % 10    // 取余:对个位数保留
    }

    // a 和 b 较小的时候,temp的首位为0
    // 为避免输出结果以0开头,需要去掉temp的0首位
    if temp[0] == 0 {
        temp = temp[1:]
    }
    // 转换结果:将[]int类型的temp转成[]byte类型,
    // 因为在未处理进位的情况下,temp每位的结果可能超过255(go中,byte类型实为uint8,最大为255),
    // 所以temp选用[]int类型
    // 但在处理完进位后,不再会出现溢出
    res := make([]byte, len(temp)) //res 存放最终结果的ASCII码

    for i := 0; i < len(temp); i++ {
        res[i] = byte(temp[i] + '0')
    }

    return string(res)
}

func main() {
    s := "abcabcbb"
    fmt.Println(s[0:0] == "")
    n := lengthOfLongestSubstring(s)
    fmt.Println(n)

    a := "498828660196"
    b := "840477629533"

    res := BigMulti(a, b)
    fmt.Println(res)

    // 字符串相乘(小数),使用字符串转换即可
    str1 := "98"
    str2 := "21"

    n1, _ := strconv.ParseInt(str1, 10, 64)
    n2, _ := strconv.ParseInt(str2, 10, 64)
    result := n1 * n2
    res = strconv.FormatInt(result, 10)
    fmt.Println(res)
}
// 运行结果:
// 3
// 419254329864656431168468
// 2058

当然,大数相乘,有一种投机的方式,使用Python的内置函数eval,一行代码就可解决…

1
2
3
4
5
6
7
8
class Solution(object):
    def multiply(self, num1, num2):
        """
        :type num1: str
        :type num2: str
        :rtype: str
        """
        return str(eval(num1 + "*" + num2))

在这里插入图片描述
但是执行用时和内存消耗,跟Go语言没法比。