2024-09-17|閱讀時間 ‧ 約 15 分鐘

C 語言字串 | ASCII 表應用 | Command Line Argument

在上一篇文章中,我們介紹了「陣列」的基本使用方式。本篇將帶你深入探討 C 語言中字串的運作原理,了解如何以陣列形式儲存字串。此外,我們還會介紹如何將英文字母透過 ASCII 表轉換成數值,並說明其在電腦中的實際應用。最後,我們將解析 Command Line Argument(命令列引數)的使用方法,並探討程式結束時的 Exit Status(退出狀態)。讓我們一起揭開這些概念的神秘面紗,往電腦科學靠近!

字串與陣列

「HI! 」在 C 語言中其實是以字元陣列的方式被儲存,每一個字母在 C 語言的資料型別是 char

#include <stdio.h>

int main(void)
{
char c1 = 'H';
char c2 = 'I';
char c3 = '!';
printf("%c%c%c\n", c1, c2, c3);
}

成功輸出 HI! 但如果改成以整數輸出,會有什麼結果呢?

#include <stdio.h>

int main(void)
{
char c1 = 'H';
char c2 = 'I';
char c3 = '!';
printf("%i%i%i\n", c1, c2, c3);//改成輸出int資料型別
}

輸出727333

這些 727333 是對照 ASCII Table 所產生的對應數字,之後再轉成 0 和 1 的方式存在電腦。

圖片來源:https://www.geeksforgeeks.org/ascii-table/

實際上不須要一個一個給字母資料型態,在 CS50 的環境中,加入 <cs50.h> 就會有string 表示字串。這個資料型別背後的原理是「陣列」,陣列是連續的資料儲存格式,就跟實際上的字串寫法一樣。以下示範用字元陣列的概念輸出字串,方便你了解儲存方式,但平常只需要打 %s 就可以輸出字串了。

#include <stdio.h>
#include <cs50.h>

int main(void)
{
string s = "HI!";
printf("%c%c%c\n", s[0],s[1],s[2]);
}

如果改成整數,並多顯示一格會發生什麼事呢?

#include <stdio.h>
#include <cs50.h>

int main(void)
{
string s = "HI!";
printf("%i%i%i%i\n", s[0],s[1],s[2],s[3]);
}

居然在最後出現0

在 ASCII Table 中,輸出 0 代表 NULL 空值,這裡沒有值的意思,並不是使用者輸入 0 這個數字。補充說明,字元陣列的結束會用 NUL 代表字串結束,在電腦中會用 \0 多留一個空間,不過使用者並不會看到。

一張圖說明 0 和 NULL 的差別。0 是沒有衛生紙,但 NULL 是連紙捲都沒有。圖片來源:網路。









既然字串是以陣列的形式表示,也可以用陣列的方式計算字串的長度。背後的概念是讀陣列的索引值,如果讀到\0 就代表已經結束。

#include <cs50.h>
#include <stdio.h>

int string_length(string s);
int main(void)
{
string name = get_string("Name: ");
int length = string_length(name);
printf("%i\n", length);
}

int string_length(string s) // 寫一個長度的功能餵字串進去
{
int n = 0;
while (s[n] != '\0')
{
n++;
}
return n;
}

不過,C 語言裡有已經寫好的標頭檔,加入 <string.h>,可以直接使用 strlen 即可,不需要再寫迴圈一個一個讀值。

密碼學入門:凱薩密碼

綜合前面提到的 ASCII 表與陣列的概念,我們來實作凱薩密碼。凱薩密碼是經典的加密方法,由 Julius Caesar 提出,雖然現今這種方法很容易被破解,但仍是密碼學的入門經典題型。凱薩密碼主要概念是讓英文字母往後位移特定的數值,例如:

位移量 3,加密訊息為 "HELLO":

  • H -> K
  • E -> H
  • L -> O
  • L -> O
  • O -> R

因此,"HELLO" 經過凱薩密碼加密後就會變成 "KHOOR"。

#include <cs50.h>
#include <ctype.h> //注意有<ctype.h>,後面的islower從這裡來
#include <stdio.h>
#include <string.h>

int main()
{
string s = get_string("input: ");
int move = get_int("偏移值: ");
for (int i = 0, n = strlen(s); i < n; i++)
{
if (islower(s[i]))//判斷小寫
{
printf("%c", (s[i] + move - 'a') % 26 + 'a');
}
else
{
printf("%c", (s[i] + move - 'A') % 26 + 'A');
}
}
}

在 C 語言,可以使用 <ctype.h> 的函式庫,就有判斷小寫的函數。

英文大小寫轉換 (uppercase)

這裡也是要應用 ASCII 表的值,注意大小寫都固定相差 32 ,所以我可以利用這個特性,把所有的小寫變成大寫。

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

int main(void)
{
string s = get_string("Before: ");
printf("After: ");
for (int i = 0, n = strlen(s); i < n; i++)//起始值i與終點值n
{
if (s[i] >= 'a' && s[i] <= 'z') //
{
printf("%c", s[i] - 32);//每個字元都差32,用('a'-'A')也可以
}
else
{
printf("%c", s[i]);
}
}
printf("\n");
}

Multi-dimensional Array (多維陣列)

當字串本身就是一個陣列,而你想把多個字串組成一個陣列時,就會形成「大陣列包小陣列」的結構。

#include <stdio.h>
#include <cs50.h>

int main()
{
string words[2];

words[0]="HI!";
words[1]="BYE!";

printf("%c%c%c\n",words[0][0],words[0][1],words[0][2]);
printf("%s\n", words[1]);
}
  • words[0][0] 代表,陣列 words[0]HI!」的第 0 個字母 H 。

由此可知,陣列可以是多維陣列(Multi-dimensional Array),多維陣列通常用來表示像是表格、圖像或矩陣等資料結構。

#include <stdio.h>

int main()
{
// 定義一個 3x3 的二維陣列
int array[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

// 輸出陣列的所有元素
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d ", array[i][j]);
}
printf("\n"); // 換行,讓輸出看起來像一個表格
}
}

在這個例子中,array 是一個二維陣列,它包含三個子陣列,每個子陣列裡面有三個元素。我們可以用兩個索引來存取每個元素。例如:

  • array[0][0] 會得到 1(第 0 列第 0 行),0 是索引值,陣列的起點。
  • array[1][2] 會得到 6(第 1 列第 2 行)

Command Line Argument(命令列引數)

Command Line Argument(命令列引數),其實就是指你在終端機或命令列中執行一個程式時,可以額外輸入的值或訊息,這些值會被餵給程式,幫助程式運作。

以前我們要執行打招呼的程式,需要再請使用者輸入名字,才可以打招呼。

使用者可以直接在下指令時,輸入「bicky」 ,就會跑出「 hello, bicky」。原因是我已經預留一個陣列空間,表示程式運行時就要被餵入一個值。

但我如果輸入 bicky yang 只會跑出 bicky,因為我指定輸出 argv[1] 也就是第一個引數。

argc 是什麼?

  • argc 是一個整數,代表命令列引數的數量(arguments count),也就是當你執行這個程式時,總共傳入了幾個引數。
  • argc 的值至少會是 1,因為它會包含程式本身的名稱作為第一個引數。

argv[] 是什麼?

  • argv[] 是一個字串陣列(array of strings),它儲存了所有的命令列引數。每個引數都是以字串形式儲存的。
  • argv[0] 通常是執行的程式名稱,在這個程式 argv[0] ​表示 ./greetargv[1]argv[2] 等則是依次代表你在命令列中輸入的其他引數。

來點有趣的,如果你直接打 cowsay 加某個詞,就會出現一隻牛說出你輸入的詞。

Exit status 退出狀態

一般沒有問題的程式,程式碼會 return 0 表示成功,只是使用者在終端機看不到,如果顯示 return 其他數字就表示程式出現錯誤。return 其他數字可由軟體開發工程師自行定義,每個數字表示異常的代表。例如,工程師可以設定如果 return 127 表示command not found 。在 C 語言 的環境中,可以輸入 echo $? 查上一個命令的狀態。

顯示 127 找不到此命令


不過,網頁常出現的 404 not found 是 HTTP status,用以表示網頁伺服器超文字傳輸協定回應狀態的 3 位數字代碼,全世界統一,不能由工程師自行更改。

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.