這次小櫻前往水族館校外教學,卻不幸遇到可惡的「字串」Golang牌,導致水族館員和企鵝差點被淹死,小櫻的哥哥恰好在這裡打工,縱身一躍跳進水池解救了大家,像這樣
要如何把這個囂張的Golang牌繩之以法呢?
在了解字串前我們必需先了解什麼是字元,字元其實就是指「單一一個字」,這個字也是由數字所組成,在Golang中是以 utf8 來做為字元的轉法,舉個例子,小櫻的「小」在是以 23567 的二進位來儲存「櫻」則是以 27387 的二進位來儲存
我們在更細的來說,為什麼要有型態,有型態主要是為了方便魔法使做事,不然沒有型態的情況下,根本不知道是要用「小」還是要用 23567,因為這兩個在魔仗中都長的一樣。
要宣告一個字元我們會用 rune
(中文:符文)來表示,rune
其實就是 int32
的代稱,只是因為 rune
聽起來更接近字元所代表的「意義」,這件事在魔法牌中非常重要,越是能貼近魔法使使用上的直覺越好
package main
import "fmt"
func main(){
var a rune = '小' // 以單引號包住字元
var b rune = '櫻'
fmt.Println(a)
fmt.Println(b)
}
執行結果:
23567
27387
為什麼會這樣?
因為 rune
就是 int32
,通過 fmt.Println
當然會把他當作數字來做處理,如果我們要印「文字」出來,則必需使用 fmt.Printf
, printf
指的就是 print
+ format
,format
(中文:格式)決定要以什麼形式印出,使用方法如下:
package main
import "fmt"
func main(){
var a rune = '小'
var b rune = '櫻'
fmt.Printf("%c", a)
fmt.Printf("%c", b)
}
其中的 %c
就是告訴魔仗我要印字元出來,至於要印哪個字元呢?則是看 ,
後面第一個變數
執行結果:
小櫻
當然也可以用 %c %c
他會依序對應 ,
後面的變數
package main
import "fmt"
func main(){
var a rune = '小'
var b rune = '櫻'
fmt.Printf("%c%c", a, b)
}
執行結果:
小櫻
另外常用的還有
%d
,%f
,%s
%c
的 c 是指 character 以字元印出
%d
的 d 是指 decimal 以十進位印出
%e
的 e 是指 exponent 以科學計號方式印出
%f
的 f 是指 float 以浮點數印出
%s
的 s 是指 string 以字串印出
%%
是用來印出 % 不然 Printf 會有 bug
初學者可能一時之間覺得頭有點痛,好像了解但其實又不是很懂,這麼說好了,其實當我們在Golang牌上刻上 '小'
這個字時,魔仗會直接把他變成 23567
你甚至可以試試把 '小'
減去 23566
讓他變成 1
package main
import "fmt"
func main(){
var a rune = '小' - 23566
fmt.Printf("%d", a)
}
執行結果:
1
'小' - 23566
在魔仗的中會直接視為 23567-23566
,rune
則是會視為 int32
而 fmt.Printf("%d", a)
則是視為 fmt.Printf("%d", 1)
這種「視為」的情況太多了,所以我們要多利用這種方法來學習,才能收服差點把企鵝淹死的Golang牌
剛剛教了大家怎麼一眼看穿單引號,現在要教大家一眼看穿 Print,其實 Print 在做的事,就是用預設的型式來做印出,什麼是預設的型式?比如整數類型就以%d
來印,浮點數就以%g
來印(%e
for large exponents, %f
otherwise.),在 Golang 中,這個預設類型可以直接用 %v
來表示
package main
import "fmt"
func main(){
a := 10
fmt.Printf("%d", a)
fmt.Printf("%v", a)
fmt.Print(a)
}
執行結果:
101010
Print(a)
可以視為 Printf("%v", a)
又因為 a
的型態是 int
所以 %v
就是 %d
因此就是 Printf("%d", a)
在程式語言中,有一些字元沒辦法那麼容易表示,比如換行,因此可以用 \n
來表示
func main(){
a := 10
fmt.Printf("%d\n", a)
fmt.Printf("%v\n", a)
fmt.Println(a)
}
執行結果:
10
10
10
相信大家都知道字元是什麼了,「字元不過就是一串數字」,那「字串」呢?字串其實就是一串「字元」,這次教學只會點到這裡就停了,因為現在教的還不夠還沒辦法完美解釋。
就像小櫻只知道他哥很常打工,並且常常遇到他哥,但他根本不知道他哥是照著他的行程在打工,小櫻去水族館他哥就在水族館打工,去溜冰場他哥就在溜冰場打工,去採草莓他哥就去草莓園打工,(邦友可以留一下集數我忘了)
所以各位魔法使只要先知道怎麼用就好了,想了解原理,可以去學看「C魔法使」,但聽起來好爛,還是要出「Clang魔法使」、「科學超C語言」、「玩偶遊C」、「我們仍未知道那天所寫的C的意思」、「C利人妻」
package main
import "fmt"
func main(){
var release string = "封印解除"
release2 := "レリーズ"
fmt.Println(release)
fmt.Println(release2)
}
執行結果:
封印解除
レリーズ
舉個例子大家應該就懂了
字元的運算剛剛被我解惑了一下大家應該都懂了,就跟整數是一樣的,那麼字串呢?字串在用的只有「加法」啦,這個在魔法科學中常稱為 concatenate
package main
import "fmt"
func main(){
str1 := "隱藏著黑暗力量的鑰匙啊"
str2 := "在我面前顯示你真正的力量"
fmt.Println(str1 + str2)
}
執行結果:
隱藏著黑暗力量的鑰匙啊在我面前顯示你真正的力量
就是這麼簡潔有力!如果換做是C魔法牌,你必需再額外使用 string.h
並呼叫 strcat()
但是C魔法牌的彈性仍是有他的好處
另外提一個有趣的現象,大家有想過要怎麼把數字轉成字串一起填入嗎?
很好報錯了!因為 4 不是字串不能直接加,這是一個優勢但稍微麻煩是劣勢
圖源:https://www.youtube.com/watch?v=YFuqbgDqib4
這是一個不錯的設計,在某些卡牌中,比如 javascript
,在進行加法時,有時會誤把數字相加當作字串相加,因為魔法使並不好知道這個變數是數字還是字串,javascript自己知道但他不說。而同為弱型態的php
則是巧妙地避開這問題,php
字串相加用.
數字相加用 +
。而python
跟golang
一樣把數字和字串相加時會報錯。文末會繼續補充
在 Golang 中
字串 + 字串 Ok
數字 + 數字 Ok
字串 + 數字 噴錯
那麼不然我們把數字轉成字串好了?
首先如果只是要印出的話可以用 Printf 來印出
法一:Printf
package main
import "fmt"
func main(){
sakura := "小櫻今年"
grade := "年級"
fmt.Printf("%s%d%s", sakura, 4, grade)
}
執行結果:
小櫻今年4年級
法二:Print
package main
import "fmt"
func main(){
sakura := "小櫻今年"
grade := "年級"
fmt.Print(sakura, 4, grade)
}
執行結果:
小櫻今年 4 年級
這方法先前沒教
fmt.Print(sakura, 4, grade)
可以直接視為
fmt.Print(sakura)
fmt.Print(" ")
fmt.Print(4)
fmt.Print(" ")
fmt.Print(grade)
但印出來中間會多一個空白,跟 python
中的print
, javascript
中的 console.log()
,
以上提到的方法都是直接印在螢幕上(標準輸出 standard output),有沒有方法是直接印在變數裡
使用 fmt.Sprintf()
法三:法一、法二都垃圾要用就用 Sprintf
package main
import "fmt"
func main(){
sakura := "小櫻今年"
grade := "年級"
result := fmt.Sprintf("%s%d%s", sakura, 4, grade)
fmt.Printf(result)
}
這個用法跟 C 很類似但稍有不同,文末討論
如果今天我是想把 "4"
轉成 4
那要怎麼轉呢?
其實這個可以把字串拆成字元再用字元去做運算,但是剛剛就說了,依現在各位魔法使的實力,還不夠,所以我們就先跳過吧!
建議新手這裡可以跳過
剛剛說了 golang 在字串加數字的一些邏輯,我們來看一下其他語言
在 C 語言中我們可以用一樣sprintf
的方法來做,要注意的事第一個參數放的事有足夠大小的字串指標
sprintf()
如果成功,則返回寫入的字符的總數,不包括\0
,否則在發生故障的情況下,返回一個負數。
#include<stdio.h>
int main(){
char sakura[64] = "小櫻今年";
char* grade = "年級";
sprintf(sakura, "%s%d%s", sakura, 4, grade);
printf(sakura);
return 0;
}
在 javascript
中我們可以把字串直接與數字相加,在進行字串與數字相加時 javascirpt 會直接把數字做為字串處理
var sakura = "小櫻今年";
var grade = "年級";
var result = sakura + 4 + grade;
console.log(result);
在 php
中字串相加用 .
數字用 +
,缺點是物件導向時只能用 ->
不能用 .
但 php 一開始設計時就不是要走物件導向所以一開始問題不大,現在要用物件才發現有夠麻煩 .
要打 ->
另一種方法是把變數鑲進雙引號裡面,這感覺跟 dart
和新版的 javascript
有點類似
<?php
$sakura = "小櫻今年";
$grade = "年級";
$result = $sakura.(4).$grade;
echo $result;
$result = "{$sakura}4{$grade}";
echo $result;
?>
在 java
中就好玩了,雖然大家都覺得java
是強型態,python
是弱型態,但是 java
卻能支援字串加數字,因為 java 在做相加時會自動將 4 轉成字串
public class Strcat{
public static void main(String[] args){
String sakura = "小櫻今年";
String grade = "年級";
String result = sakura + 4 + grade;
System.out.println(result);
}
}
sakura = "小櫻今年"
grade = "年級"
# print(sakura + 4 + grade) 報錯
print(sakura + str(4) + grade)
dart 在數字加字串時習慣會直接像用 php 的那種方法將變數鑲進去
void main(){
var sakura = "小櫻今年";
var grade = "年級";
var number = 4;
print(sakura + number.toString() + grade);
print("$sakura$number$grade");
}
在 rust 中則是類似用 sprintf() 的做法來實現
fn main(){
let sakura = "小櫻今年";
let grade = "年級";
let result = format!("{}{}{}", sakura, 4, grade);
print!("{}", result);
}
rust 中的 string 挺複雜的,話說今年 2020 還沒看到鐡人賽有人教 rust 如果有可以留個言
圖片大多來自:庫洛魔法使第一季第三集以及庫洛魔法使第一季第四集