說明:

C語言對於字串的定義非常簡單,由0結尾的字元陣列就是字串。常數字串的寫法是由雙引號將字串的內容括起來, 以下的變數p,q,r都可當作字串:

int main() {
    char *p = "abc"; // 指標宣告, "abc"這個陣列會放在記憶體的"常數區塊",不允許被修改
    char q[] = {'a','b','c',0}; // 陣列宣告,同時給予初始值
    char r[] = "abc"; // 陣列宣告, 此空間就放在堆疊上
    q[0] = '!'; // q字串變成 "!bc"
    r[0] = '!'; // r字串變成 "!bc"
    *p = '!'; // 這在Unix系統上會造成Segmentation fault (core dumped)
}

常見的字串操作函數

由於C語言對字串的定義非常簡單,因此需要一些函數幫我們操作字串。常見的範例如下列,每個範例又可能列出數種寫法,以幫助讀者熟悉指標和陣列的操作

字串長度

int strlen(char s[]) {
    int i;
    for (i = 0; s[i] != 0; i++) ;
    return i;
}
int strlen(char *s) {
    int i;
    for (i = 0; *s != 0; i++, s++) ;
    return i;
}
int strlen(char *s) {
    char *e;
    for (e = s; *e != 0: e++) ;
    return e - s;
}

字串複製

void strcpy(char d[], char s[]) {
    int i;
    for (i = 0; s[i] != 0; i++) {
        d[i] = s[i];
    }
    d[i] = 0;
}
void strcpy(char s[], char d[]) {
    int i;
    for (i = 0; d[i] = s[i]; i++) ;
}
void strcpy(char *s, char *d) {
    for (; *d = *s; s++, d++) ;
}

字串相加(String Concatenation)

將"abc"加上"def"變成"abcdef"

\
void strcat(char *s1, char *s2) {
    int i, j;
    for (i = strlen(s1), j = 0; s1[i] = s2[j]; i++, j++) ;
}

字串比對

int strcmp(char *s1, char *s2) {
    for (; *s1 && *s1 == *s2; s1++, s2++) ;
    return *s1 - *s2;
}

反轉字串(把"abcde"變成"edcba")

void reverse(char *s) {
    int i, j;
    char c;
    // 假設字串長度為n,將0和n-1調換,再換1和n-2,直到字串中間為止
    for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

印出base進位系統的加法表和乘法表

/**
 * 將val以b進位系統來表達,結果存放在字串s裡
 */
void convert(char s[], int val, int b) {
    int i = 0;
    int digit;
    while (val / b > 0) {
        digit = val % b; // 計算最後一位的大小
        // 大於10的數字以A-Z來代表
        s[i++] = (digit < 10) ? digit + '0' : digit - 10 + 'A';
        val /= b;
    }
    s[i++] = (val < 10) ? val + '0' : val - 10 + 'A';
    s[i] = 0;
    reverse(s);
}
int main() {
    char buf[5];
    int i, j;
    int base = 10;
    printf("Please input base:");
    scanf("%d", &base);
    // 印出base進位系統的加法表
    printf("%d進位系統的加法表:\n", base);
    for (i = 1; i < base; i++) {
        for (j = 1; j < base; j++) {
            convert(buf, i + j, base);
            printf("%3s", buf);
        }
        printf("\n");
    }
    // 印出base進位系統的乘法表
    printf("%d進位系統的乘法表:\n", base);
    for (i = 1; i < base; i++) {
        for (j = 1; j < base; j++) {
            convert(buf, i * j, base);
            printf("%3s", buf);
        }
        printf("\n");
    }
}

注意空間分配問題

由於C語言的字串定義為以'\0'結尾的字元陣列, 因此設計人員必需小心處理陣列空間不足的問題. 以下面程式碼為例:

main() {
    int x = 0;
    char s1[5] = "abc";
    int y = 0;
    char s2[] = "defghijklmno";
    strcat(s1, s2);
    printf("x = %d, s1 = '%s', y = %d\n", x, s1, y);
}
請你試試執行的結果.

又如下面的例子, 如果使用者輸入的字串很長, 也會讓程式出現錯誤.

main() {
    int x = 0;
    char s1[5];
    int y = 0;
    printf("Please input a string with it's length smaller than 5:");
    scanf("%s", s1);
    printf("x = %d, s1 = %s, y = %d\n", x, s1, y);
}
解決此問題的方法是告訴scanf可以輸入的上限
main() {
    int x = 0;
    char[5] s1;
    int y = 0;
    printf("Please input a string with it's length smaller than 5:");
    scanf("%4s", s1);
    printf("x = %d, s1 = %s, y = %d\n", x, s1, y);
}