String

Sunday, January 7, 2018

字串相關整理

字串 (string)

strcpy、strcat比較

需使用#include <string.h>引入標頭檔

  • strcpy:string copy
  • strcat:string concatenation (字串連接)
#include <stdio.h>
#include <string.h>

int main(void) {
	char source_1[50], destination_1[50]; // use for strcpy
	char source_2[50], destination_2[50]; // use for strcat
	
	scanf("%s%s", source_1, destination_1);
	scanf("%s%s", source_2, destination_2);
	
	printf("Before strcpy:\n");
	printf("* source_1 string is: %s\n", source_1);
	printf("* destination_1 string is: %s\n\n", destination_1);
	
	strcpy(destination_1, source_1);
	
	printf("After strcpy:\n");
	printf("* source_1 string is: %s\n", source_1);
	printf("* destination_1 string is: %s\n\n", destination_1);
	
	
	printf("Before strcat:\n");
	printf("* source_2 string is: %s\n", source_2);
	printf("* destination_2 string is: %s\n\n", destination_2);
	
	strcat(destination_2, source_2);
	
	printf("After strcat:\n");
	printf("* source_2 string is: %s\n", source_2);
	printf("* destination_2 string is: %s\n\n", destination_2);
	return 0;
}
Output
Before strcpy:
* source_1 string is: Test_for_source_1
* destination_1 string is: Test_destination_1

After strcpy:
* source_1 string is: Test_for_source_1
* destination_1 string is: Test_for_source_1

Before strcat:
* source_2 string is: Test_for_source_2
* destination_2 string is: destination_2

After strcat:
* source_2 string is: Test_for_source_2
* destination_2 string is: destination_2Test_for_source_2

使用strcpy容易發生幾種狀況

  1. char string1[80] = "programming本身宣告80個位元組(Bytes)大小的字元陣列,使用strcpy(string1, "more programming");是沒問題的。 (除非source字串超過80 Bytes,就會發生如同狀況2)

  2. char string2[] = "programming本身就沒有宣告大小,因此在編譯時,編譯器會計算初始化該字串的總大小(包含’\0’字元)為12 Bytes。 在執行strcpy時,會發生緩衝區覆蓋(buffer overrun)

  • 緩衝區覆蓋(buffer overrun):使用strcpystrcat時,如果source string超過destination string的長度,將可能會覆蓋到其他變數的內容。
  1. char *string3 = "programming"本身是指標,占4 Bytes。 編譯器會在唯讀記憶體中放一個字元陣列,初始化成"programming”,再將*string3指向這個字元陣列。 因此一執行strcpy時,系統會宣告執行錯誤。
  • 第三種狀況多半放在唯獨記憶中,盡量不要嘗試寫入這個字串 (寫字元進入會執行錯誤)
#include <stdio.h>
#include <string.h> // 引入 string header file

int main(void) {
	char string1[80] = "programming";
	char string2[] = "programming";
	char *string3 = "programming";
	
	// string copy
	strcpy(string1, "more programming"); // 1. success
	strcpy(string2, "more programming"); // 2. buffer overrun 緩衝區覆蓋
	strcpy(string3, "more programming"); // 3. runtime error

	return 0;
}

反轉字串 Reverse a string

方法一

#include <stdio.h>
#include <string.h>

/*  Reverse a string 反轉字串  */

int main(void) {
	int i, length;
	char s[80]; // declare a string
	char temp;  // temporary
	
	scanf("%s", s);
	length = strlen(s);
	printf("The length of 『%s』 is %d\n", s, length);
	printf("The size   of 『%s』 is %d\n", s, sizeof(s));
	
	// Reverse a string 反轉字串
	for(i = 0; i < length / 2; i++){
		temp = s[i];
		s[i] = s[length - 1 - i];
		s[length - 1 - i] = temp; 
	}
	
	printf("The reversed string is : %s\n", s);
}

方法二

#include <iostream>
#include <cstring>
using namespace std;

void reverse_string(char *a);

int main() {
	char s[] = "ABCDEFGH";
	reverse_string(s);
	cout << s;
	return 0;
}

void reverse_string(char *a){ // 注意此行
	int l = strlen(a);
	for(int i=0, j=l-1; i<int(l/2); i++, j--){
		char temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}
}

strcmp介紹、字串排序 (string sort)

  • strcmp : string compare,同樣也在<string.h>標頭檔裡。strcmp是用來比較兩個字串的大小,並會回傳整數值。
  • strcmp的比較方式:兩字串的第一個字元開始,以ASCII碼大小比較,如果左字串大於右字串則回傳正數,反之回傳負數,一樣大(代表兩者字串相同)則回傳 0。

<方法一> 使用strcpy作swap

#include <stdio.h>
#include <string.h>

/* string sort : use bubble sort */

int main(void) {
	char zodiac[12][20];
	int i, j; // counter
	char temp[20]; // temporary
	
	for(i = 0; i < 12; i++)
		scanf("%s", zodiac[i]);
		
	for(i = 11; i >= 0; i--){
		for(j = 0; j < i; j++){
			if(strcmp(zodiac[j], zodiac[j + 1]) > 0){
				strcpy(temp, zodiac[j]);
				strcpy(zodiac[j], zodiac[j + 1]);
				strcpy(zodiac[j + 1], temp);
			}
		}
	}
	
	for(i = 0; i < 12; i++)
		printf("%s\n", zodiac[i]);
	return 0;
}

<方法二> 使用指標陣列作swap

#include <stdio.h>
#include <string.h>
 
/* string sort : use bubble sort */
 
int main(void) {
	char zodiac[12][20];
	char *zptr[12];
	int i, j; // counter
	char *temp; // temporary
 
	for(i = 0; i < 12; i++){
		scanf("%s", zodiac[i]);
		zptr[i] = zodiac[i];
	}
 
	for(i = 11; i >= 0; i--){
		for(j = 0; j < i; j++){
			if(strcmp(zptr[j], zptr[j + 1]) > 0){
				temp = zptr[j];
				zptr[j] = zptr[j + 1];
				zptr[j + 1] = temp;
			}
		}
	}
 
	for(i = 0; i < 12; i++)
		printf("%s\n", zptr[i]);
	return 0;
}

Reference

[1] 由片語學習C程式設計 劉邦鋒

ProgrammingC程式

Commonly Used Taylor Series

質數相關程式題