iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Software Development

0基礎也看得懂的程式設計-30天學會C語言系列 第 11

30天學會C語言: Day 10-你的字串不是字串

字元

電腦中的字元其實是由整數數字表示,就像是每一個字元都有一個屬於自己的編號,

printf() 可以查看代表字元的整數

#include<stdio.h>
#include<stdlib.h>

int main(){
	printf("%d %d\n", '0', '9');
	printf("%d %d\n", 'A', 'Z');
	printf("%d %d\n", 'a', 'z');
	
	return 0;
}

字元 0 ~ 9, A ~ Za ~ z 的數值是連號而且由小到大
大小寫和小寫字母相差42

利用這些性質,可以用來對字串進行一些操作

C語言中的字串

在C語言中,並沒有 String 這個型別,而是用字元的陣列 (character Array) 作為字串

在C語言中,空字元('\0')代表字串結束
所以 "123",其實是一個長度為四的一維字元陣列,它的元依序是 '1', '2', '3', '\0'

宣告

就和宣告陣列一樣,但因為陣列的大小上限在宣告的時候就決定了,所以宣告時要注意輸入的大小

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100];
	
	return 0;
}

可以用和陣列一樣的方法初始化字串的內容

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100]={'H', 'e', 'l', 'l', 'o', '!', '\0'};
	
	return 0;
}

或是用雙引號代表字串,但一樣只能在宣告時用這個方法指派

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100]="Hello!";
	
	return 0;
}

輸出

printf()

字串的預留位置用 %s 表示

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100]="PJ";
	printf("My name is %s.", s);
	return 0;
}

如果只要顯示字串中的內容,可以直接把字串作為 printf() 的引數

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100]="Hello!";
	printf(s);
	return 0;
}

puts()

puts() 函式的引數為一個字串,功能是將引數顯示到螢幕上,會自動在字串結尾換行,但沒有格式化字串的功能(無法顯示其他型別的資料)

#include<stdio.h>
#include<stdlib.h>

int main(){
	puts("1");
	puts("2");
	return 0;
}

顯示字串變數

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[10]="Hello!";
	puts(s);
	return 0;
}

輸入

scanf()

因為陣列實際上就是指標,所以字串變數前面不用 &
宣告時設定的陣列長度,要比輸入的字串還長,下面例子中的 name 最大可以儲存99個字元(99個字元加上一個'\0')

#include<stdio.h>
#include<stdlib.h>

int main(){
	char name[100];
	scanf("%s", name);
	printf("My name is %s.\n", name);
	
	return 0;
}

如果使用的預留位置是 %sscanf() 遇到空格就會以為是另一個數值,字串會不完整

如果輸入的字串 包含空格 必須用 %[^\n]

#include<stdio.h>
#include<stdlib.h>

int main(){
	char name[100];
	scanf("%[^\n]", name);
	printf("My name is %s.\n", name);
	
	return 0;
}

常見字串處理

字串長度

指從頭開始到空字元 '\0' 前的字元數量(不包含'\0')

可以用迴圈計算字串長度,或是透過函式庫 string.h 中的函式取得

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100]="Hello!";
	int len=0;
	for(int i=0; s[i]!='\0'; i++)
		len++;
	printf("%d\n", len);
	return 0;
}

除了先用一個迴圈計算字串長度,也常常直接把字串處理的內容寫在迴圈中

大小寫/英數 判斷

因為字元實際上是整數,所以可以用來進行比較運算
結合比較運算和邏輯運算,可以判斷某字元是數字、大寫字母或小寫字母

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100];
	scanf("%s", s);
	for(int i=0; s[i]!='\0'; i++){
		if(s[i]>='a' && s[i]<='z')
			printf("%c is a lowercase letter.\n", s[i]);
		else if(s[i]>='A' && s[i]<='Z')
			printf("%c is a capital letter.\n", s[i]);		
		else if(s[i]>='0' && s[i]<='9')
			printf("%c is a numerical digit.\n", s[i]);
	}
	return 0;
}

大小寫轉換

因為字元實際上是整數,所以可以做數學運算
因為大寫和小寫相差42,所以可以透過加減42達成大小寫轉換

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100];
	scanf("%s", s);
	for(int i=0; s[i]!='\0'; i++){
		if(s[i]>='a' && s[i]<='z')
			s[i]-=42;
		else if(s[i]>='A' && s[i]<='Z')
			s[i]+=42;
	}
	return 0;
}

或是加上 'A''a' 之間的差

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100];
	scanf("%s", s);
	for(int i=0; s[i]!='\0'; i++){
		if(s[i]>='a' && s[i]<='z')
			s[i]+=('A'-'a');
		else if(s[i]>='A' && s[i]<='Z')
			s[i]+=('a'-'A');
	}
	printf("%s\n", s);
	return 0;
}

偏移(凱薩加密)

例如將字串中的 'a' 變成 'b''b' 變成 'c'...'z' 變成 'a' 這類的題目,可以透過數學運算完成
因為 'z' 加上1不會變成 'a',所以要用 if() 另外處理

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100];
	scanf("%s", s);
	for(int i=0; s[i]!='\0'; i++){
		if(s[i]>='a' && s[i]<='z'){
			s[i]+=1;
			if(s[i]>'z')
				s[i]='a';
		}
	}
	printf("%s\n", s);
	return 0;
}

或是透過數學運算

#include<stdio.h>
#include<stdlib.h>

int main(){
	char s[100];
	scanf("%s", s);
	for(int i=0; s[i]!='\0'; i++){
		if(s[i]>='a' && s[i]<='z'){
			s[i]=s[i]-'a'+1;
			s[i]%=26;
			s[i]+='a';
		}
	}
	printf("%s\n", s);
	return 0;
}


挖坑清單:

  • main() 前面的 int,和最後一行的 return 0;
  • 可以拆成多行的情況
  • 指標

上一篇
30天學會C語言: Day 9-Arrrrrrrrrrrrray~~
下一篇
30天學會C語言: Day 11-什麼都可以取名字
系列文
0基礎也看得懂的程式設計-30天學會C語言30

尚未有邦友留言

立即登入留言