第九章 字串 (String).

Slides:



Advertisements
Similar presentations
◎ 標準函數 標準函數庫中,提供了許多不同功能的函數,而這些函數 的原型宣告以及使用函數相關的定義,依照相關函數的分 類,分別定義在不同的標頭檔之中。 標準函數庫中,提供了許多不同功能的函數,而這些函數 的原型宣告以及使用函數相關的定義,依照相關函數的分 類,分別定義在不同的標頭檔之中。 本來呼叫使用標準函數庫裡的函數,也就是使用模組裡的.
Advertisements

C语言程序设计 主讲教师 :张群燕 电话:
电子成绩单项目实现.
“八皇后”问题 崔萌萌 吕金华.
補充: Input from a text file
第8章 字元與字串處理 8-1 C語言的字元檢查函數 8-2 C語言的字串 8-3 字串的輸入與輸出 8-4 指標與字串
第一章 程序设计入门.
第六章 数 组 主讲教师 贾月乐 联系电话:
高级语言程序设计 主讲人:陈玉华.
主讲教师:吴琼 微信群:C语言2016 QQ群: 密码scu2016 昵称:“真名+学号”
程序设计II 第三讲 字符串处理.
函數 授課:ANT 日期:2011/3/28.
C 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
第十一章 文件 文件概述 文件操作 文件操作实例 本章小结 作业: 练习:
Introduction to the C Programming Language
Introduction to the C Programming Language
目录 第八章 数组 1 简单学生成绩管理系统的开发 2 一维数组 3 多维数组 4 字符数组 5 数组作函数参数.
C++ 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
STRUCTURE 授課:ANT 日期:2010/5/12.
计算概论 第十八讲 C语言高级编程 结构与习题课 北京大学信息学院.
Introduction to the C Programming Language
Function.
第4章 字串及資料的輸入/輸出格式.
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
第四章 C 语言中的输入和输出.
C语言 程序设计基础与试验 刘新国、2012年秋.
字符串和字符数组 字符串的输入和输出 字符串的基本操作
第八章 使用指针.
第十章 指针.
第3章 顺序结构程序设计 为了让计算机处理各种数据,首先就应该把源数据输入到计算机中;计算机处理结束后,再将目标数据信息以人能够识别的方式输出。C语言中的输入输出操作,是由C语言编译系统提供的库函数来实现。 3.1 格式化输出——printf()函数 3.2 格式化输入——scanf()函数.
第三章 数据类型、运算符与表达式.
2.1 C语言的数据类型 2.2 常量与变量 2.3 变量赋初值 2.4 各类数值型数据间的混合运算 2.5 C语言的运算符和表达式
数组 梁春燕 华电信息管理教研室.
Struct結構 迴圈
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C++ 程式設計 基礎篇 張啟中 Chang Chi-Chung.
C语言概述 第一章.
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
第 二 章 数据类型、运算符与表达式.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
函式庫補充資料.
第八章 指標 (Pointer).
C语言的特点 1. C程序由许多函数组成 2. C程序必须有且只有一个主函数main( ) 3. 函数用“{”和“}”表示起点和终点
輸出與輸入(I/O).
C语言程序设计 李祥 QQ:
C程序设计.
项目1 C程序设计起步 学习目标: 通过该项目你可以知道: C语言的用途。 C语言的基本符号和关键字。 C语言程序的结构及特点。
第2章 数据类型、运算符与表达式 本章要点: 基本数据类型 常量和变量 算术运算符和算术表达式 关系运算符和关系表达式
第二章 类型、对象、运算符和表达式.
第二章 基本数据类型 ——数据的表示.
第三章 基本的輸出與輸入函數 (Basic Output & Input Function)
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
第4章 顺序结构程序设计 为了让计算机处理各种数据,首先就应该把源数据输入到计算机中;计算机处理结束后,再将目标数据信息以人能够识别的方式输出。C语言中的输入输出操作,是由C语言编译系统提供的库函数来实现。 4.1 格式化输出——printf()函数 4.2 格式化输入——scanf()函数.
第3章 最简单的C程序设计 3.1 顺序程序设计举例 3.2 数据的表现形式及其运算 3.3 C语句 3.4 数据的输入输出.
Introduction to the C Programming Language
1.4WIN32中的宽字符.
C/C++基礎程式設計班 字元與字串 講師:林業峻 CSIE, NTU 3/14, 2015.
第二章 数据类型、运算符和表达式 §2.1 数据与数据类型 §2.2 常量、变量和标准函数 §2.3 基本运算符及其表达式 目 录 上一章
Introduction to the C Programming Language
C/C++基礎程式設計班 C語言入門、變數、基本處理與輸入輸出 講師:林業峻 CSIE, NTU 3/7, 2015.
基本資料型態 變數與常數 運算子 基本的資料處理 授課:ANT 日期:2014/03/03.
C 程式設計— 字元與字串 台大資訊工程學系 資訊系統訓練班.
字串 第10章 part I 8/30/2019.
第9章 C++程序设计初步 9.1 C++的特点 9.2 最简单的C++程序 9.3 C++的输入输出 9.4 函数的重载
變數與資料型態  綠園.
第11章 字符和内存处理 一、字符数组、指针和字符串的初始化作用 二、strlen函数确定字符串有效长度 三、strcpy函数拷贝字符串.
台大資訊工程學系 資料系統訓練班 第119期 吳晉賢
Introduction to the C Programming Language
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

第九章 字串 (String)

9-1 字串的基本語法 當我們需要處理姓名、地址等文字資料時,最常用的資料形態,就是字串了。 9-1 字串的基本語法 當我們需要處理姓名、地址等文字資料時,最常用的資料形態,就是字串了。 字串是指一串字元,一般的姓名、地址、物品名稱等等,任何由文字所構成的資料,都可以看成是字串資料。 字串可以看成是一種特殊的字元陣列,用一個 ASCII 碼值為 0 的特殊字元來做為字串結束的符號,在本章中我們把它簡稱為字串的結尾零。

9-1-1 字串宣告與字元陣列 宣告一個字元陣列 char name[4]={'W','a','n','g'}; 9-1-1 字串宣告與字元陣列 宣告一個字元陣列  char name[4]={'W','a','n','g'};  這是一個四個元素的字元陣列,但不是字串。它在記憶體中的內容如下:

例如: char sname[5]={'W','a','n','g','\0'};   注意字串的結尾零 '\0' 是一個字元,其 ASCII 碼值為 0,也就是第二章2-3節脫序字元所說的零值符號,它和數字符號 '0' 字元 (ASCII碼值為48)是不同的

可以用字串常數來設定初值:   char sname[5]="Wang";   字串常數就是用雙引號 " 框起來的文字,這個例子和上面的寫法效果一樣,但寫起來比較方便。但是要注意如果字串本身含有脫序字元如 " 等符號,應該寫成 \" 才對,所以 "The symbol \" means inch" 是表示 The symbol " means inch。 這個 sname 字串的長度是 4,我們可以叫用字串函數 strlen (sname) 來求出,但是實際上這個字串總共佔了 5 個位元組的記憶體空間。如果我們把它看成是字元陣列,那麼字元陣列的大小應該用 sizeof(sname) 來求出,也就是 5。

設定字串的初值,也常用字元指標的寫法,例如:   char *sname="Wang";   表示 sname 是一字元指標,指向一字串。這種寫法通常用於內容不會改變的訊息字串。 它在記憶體中的內容如下:

如果雙引號裡面沒有任何字串,就是所謂的空字串,或是稱為虛指標,也可以用 NULL 常數來代表。 例如:  char *sname="";   此 sname 為空字串,字串的長度為 0。 另外一點要注意的是,'A' 和 "A" 是不一樣的,前者是一個字元,佔一個位元組;後者是字串,佔兩個位元組。

9-1-2 字串的初值設定 (1) char msg1[5]={'C','h','e','n','\0'}; 9-1-2 字串的初值設定 想要宣告字串順便設定初值,可以有幾種不同的做法: (1) char msg1[5]={'C','h','e','n','\0'}; (2) char msg2[5]="Chen"; (3) char msg3[ ]={'C','h','e','n','\0'}; (4) char msg4[ ]="Chen"; (5) char *msg5="Chen";

【語法練習 9-1-1】 (1)試用字元陣列宣告長度為10的字串s ______________________________   (1)試用字元陣列宣告長度為10的字串s ______________________________ (2)試宣告字串s,並設定初值為hello

9-1-3 字串的輸出 將字串輸出到螢幕,通常有以下幾種做法: (1) puts 例如 9-1-3 字串的輸出 將字串輸出到螢幕,通常有以下幾種做法: (1) puts 例如 puts("this is a demo string"); puts(msg1); 等等,只顯示字串的內容。   (2) printf 的 %s 格式 例如 printf("this is a demo string"); printf("Content of msg1 : %s",msg1);  等等,除了顯示字串的內容,還可附加其他文字,所以使用較方便。 (3) 逐一字元輸出

(3) 逐一字元輸出   如果想要將字串內部的字元逐一輸出,可以用 for (i=0; i<strlen(i); i++) putchar(msg1[i]);   或是 i=0; while (msg1[i] != '\0') putchar(msg1[i++]);

【語法練習 9-1-2】 (1)試將下列字串輸出到螢幕 char s1[]="test"; char *s2="test2";  (1)試將下列字串輸出到螢幕 char s1[]="test"; char *s2="test2"; ______________________________

9-1-4 字串的輸入 從鍵盤輸入字串,通常也有幾種方式: (1) gets 例如 char msg1[81],fname[13]; 9-1-4 字串的輸入 從鍵盤輸入字串,通常也有幾種方式:   (1) gets  例如 char msg1[81],fname[13];   gets(msg1); puts("input filename:); gets(fname); 用 gets 函數來讀取字串,只能用敲下 Enter 鍵(即'\n')做為結束。 因此以列為單位的資料,就可以用 gets 來讀取。

(2) scanf 的 %s 格式  例如 char msg1[81],fname[13];   scanf("%s",msg1); printf("input filename:"); scanf("%s",fname); 用 scanf 函數來讀取字串,只要遇到空白(' ')、Tab鍵('\t')、或 Enter 鍵('\n'),就視為資料結束。 因此以文字為單位的資料,例如英文的姓(first name)和名(last name)等單字,就可以用 scanf 來讀取。

(3) 逐一字元輸入   如果想要將字串的字元逐一輸入,可以用   char s[81]; int i;   i=0; while ((s[i]=getchar()) != '\n') i++; s[i]='\0'; printf("string=%s , length=%d",s,i); 請注意最後要加上結尾零 '\0',才能做為字串;而 i 值剛好是字串長度。

【語法練習 9-1-3】 (1)試用字元陣列宣告長度為 20 的字串 s ______________________________   (1)試用字元陣列宣告長度為 20 的字串 s ______________________________ (2)由鍵盤輸入字串給 s (3)輸出 s 字串

字串: 字元陣列與字元指標 (1)使用字元陣列: 宣告時可以直接設定初值,例如: char s[10]="Trouble95";   宣告時可以直接設定初值,例如: char s[10]="Trouble95"; 但是程式中不可以用 = 直接存入值,例如: char a[10]; a="chensam"; 這是錯誤的語法,因為 a 是陣列名稱,代表起始位址,是一個常數。 只能用 strcpy 函數將字串拷貝存入,例如: strcpy(a,"chensam"); 因此,宣告字元陣列時,就應預留足夠的元素個數來存字串,例如代表檔案名稱的字串,至少應留 13 個字元 (檔名 8 + 小數點 1 + 延伸檔名 3 + 字串結尾 1),如果代表螢幕的一列,就應至少留 81 個字元才夠。

(2)使用字元指標:   宣告時也可以直接設定初值,例如: char *s="Trouble95"; 系統自動計算出所需的字元長度,自動配置空間。也可以程式中用 = 直接將指標指向字串,例如: char *a; a="chensam"; 有時候我們常在字串初值宣告加上 const 的指定,例如: const char *msg="DEMO string"; 表示 msg 變數的值是固定不變的,如果程式中有所改變,系統會發出錯誤訊息來警告。 

但是如果沒有設初值,例如: char *a; 在進行字串處理的動作之前,應先安排 a 指標所指的記憶體空間,否則 strcpy(a,"chensam"); 或 *a='A"; 這些存入動作會產生不可預期的嚴重錯誤。

我們可以事先讓指標指向字元陣列,例如: char m[81]; char *a=m; 或是用第八章的動態記憶體位配置來預留空間,例如: char *a; a= (char *) malloc(81);   請記住!為指標安排所需的資料空間,是程式設計者的責任!

9-2 常用的字串函數 這一節我們介紹一些常用的字串函數,大部份有關字串的處理,都會運用到這些函數,我們先討論一些最常用的函數。 9-2 常用的字串函數 這一節我們介紹一些常用的字串函數,大部份有關字串的處理,都會運用到這些函數,我們先討論一些最常用的函數。 使用這些字串函數,應先加入一些標頭檔的宣告:   #include <string.h> 才能順利地呼叫成功。

9-2-1 字串長度 strlen 函數原型為: unsigned int strlen (char *str);   此函數用於求字串的長度,字串長度是指結尾零之前的字元個數,其一般用法如下例:   char name[]="sjsmit"; int len;   len = strlen(name); printf("the length of %s is %d",name,len); 傳入一個字串,傳回整數長度。本例的字串長度為 6。

9-2-2 字串拷貝 strcpy 函數原型為: char *strcpy (char *dest, char *source);   此函數用於將一字串拷貝給另一字串,其一般用法如下例:   char source[10]="DOS",dest[10]="Windows"; printf("before strcpy(): source=%s dest=%s\n“ ,source,dest); strcpy(dest,source); printf("after strcpy(): source=%s dest=%s\n“  傳入兩個字串,將 source 來源字串拷貝給 dest 目的字串,要注意參數的次序,目的字串在前,來源字串在後。

9-2-3 字串合併 strcat 函數原型為: char *strcat (char *dest, char *source); 此函數用於將一字串的拷貝加到另一字串的後面,得到合併的字串,其一般用法如下例:   char *s1="Chen",*s2="HongShan",*s3;   s3 = strcat(s1,s2); printf("s1=%s s2=%s s3=%s",s1,s2,s3);   將 s2 拷貝到 s1 的後面,使 s1 變成合併的字串,傳回值就是指向合併字串的指標。

9-2-4 字串比較 strcmp 函數原型為: int strcmp (char *s1, char *s2);   此函數用於比較兩字串的大小,傳回值為整數值:   若 s1 小於 s2 ,則傳回值 < 0 若 s1 等於 s2 ,則傳回值 ==0 若 s1 大於 s2 ,則傳回值 > 0  字串的大小是從頭個字元開始,依 ASCII 碼值的大小來比較,因此:   "abc" > "AAA" "abc" > "ABC" "abc" > "ab"

通常我們用 strcmp 函數來比較兩字串是否相同,其一般用法如下例:   char *answer="taipei",guess[40];   printf("the most famious city in Taiwan ?"); gets(guess); if (strcmp(guess,answer) == 0) printf("You got it !"); else printf("I am sorry !");

最後,我們把重要的字串函數整理如下:   #include <string.h>

9-3 字串的應用

9-3-1 字串陣列 例如用二維陣列來宣告字串陣列: char name[10][11]; 9-3-1 字串陣列 例如用二維陣列來宣告字串陣列:  char name[10][11];  安排了 10 個字串,每個字串最多 10 個字元,再加上一個結尾零的字元 也可以設定初始值: char name[10][11]= { "Peter", "Michale", "Sam", "Marry", "Tom", "Bob", "Kelly", "Ben", "Dongdong", "Monkey" }

可以改用指標陣列來做,處理資料也較快速。   char *name[10]= { "Peter", "Michale", "Sam", "Marry", "Tom", "Bob", "Kelly", "Ben", "Dongdong", "Monkey" };

【範例 9-3-1】字串陣列的初值設定 我們常使用字串陣列來儲存名單,將一些人名或物品名稱內建在程式裡。 4 #include <string.h> 5 6 char *country[10]= { "China", 7 "America", 8 "Japan", 9 "Taiwan", 10 NULL 11 };

17 i=0; 18 while (strcmp(country[i],NULL) != 0) 19 i++; 20 n=i; 21 printf("There are %d countries :\n",n); 22 for (i=0; i<n; i++) 23 printf("the %dth country is %s\n", i,country[i]);

【範例 9-3-2】 先輸入字串資料的個數,再依序輸入字串陣列的各項元素,印出字串個數及內容。 4 #include <string.h> 5 6 main () 7 { 8 static char name[10][21]; 9 int i,n;

11 printf("input N :"); 12 scanf("%d%*c",&n); /* use "%*c" to skip '\n' character */ 14 for (i=0; i<n; i++) { 15 printf("input %dth string: ",i); 16 gets(name[i]); 17 } 18 19 printf("=== total %d strings ===\n",n); 20 for (i=0; i<n; i++) 21 puts(name[i]);

【範例 9-3-3】 連續輸入一字串,存入字串陣列中,直接遇到 END 為止,印出有效字串個數及內容。 3 #include <string.h> 4 5 main () 6 { 7 static char name[10][21]; 8 int i,n;

10 printf("input strings end by END:\n"); 12 gets(name[i]); 13 while (strcmp(name[i],"END") != 0) { 14 i++; 15 gets(name[i]); 16 } 17 18 n=i; 19 printf("=== total %d strings ===\n",n); 20 for (i=0; i<n; i++) 21 puts(name[i]);

9-3-2 命令列引數 所謂的命令列(command line),就是我們下 DOS 命令時,DOS 提示符號(如 A:\> 或 C:\TC>)出現的那一列。有些命令會代入一些引數,例如: copy a:ttt.c b:xxx.c 這些名稱 copy 與 a:ttt.c 與 b:xxx.c,就是所謂的命令列引數,可以看成是字串來用。 到目前為止,我們自己寫的C程式會產生可執行檔,例如由原始程式 try.c 產生 try.exe,我們可以在 DOS 的命令列直接敲下 try 來執行它。 那麼,try 程式所附的引數如何傳入程式內呢?那就要修改 main 函數的宣告啦!

main () 是表示程式不帶任何命令列引數。 改成 main (int argc, char *argv[]) 或是 main (int argc, char **argv) 其中 argc 是引數個數,argv 則是字串陣列,其元素指向各引數字串。

例如在 DOS 命令列執行 ex9-3-4 aaa bbb (假設你的程式是 ex9-3-4.exe) 那麼程式執行時,DOS 傳給 main 的 argc 與 argv 值如下:  argc 為 3,表示共 3 個引數。 argv[0] 指向 "ex9-3-4" 字串,也就是程式名稱(其實會得到完整的路徑檔名)。 argv[1] 指向 "aaa" 字串。 argv[2] 指向 "bbb" 字串。

【範例 9-3-4】命令列引數的輸入 4 main (int argc, char *argv[]) 5 { 6 int i; 7 5 { 6 int i; 7 8 printf("arguments list:\n"); 9 for (i=0; i<argc; i++) 10 printf("%s\n",argv[i]); 11 }

9-3-3 字串與數值轉換 (1) atoi,itoa atoi 函數是將 ASCII 字串轉換成 int 整數 9-3-3 字串與數值轉換 (1) atoi,itoa   atoi 函數是將 ASCII 字串轉換成 int 整數 反過來,要將數值變成字串,就使用 itoa 函數 (2) atol,ltoa   atol 函數是將 ASCII 字串轉換成 long 長整數 ltoa 函數是將 long 長整數轉換成 ASCII 字串 (3) atof,fcvt   atof 函數是將 ASCII 字串轉換成浮點數 fcvt 函數是將浮點數轉換成 ASCII 字串

(4) 指定格式的字串輸出 sprintf   此函數用法類似 printf,其差異是 printf 輸出到螢幕,而 sprintf 將資料轉成指定格式後輸出到字串,傳回值為整數值但通常不使用

(1) atoi 函數是將 ASCII 字串轉換成 int 整數,其函數原型如下:   #include <stdlib.h> int atoi (const char *s ); 用法的範例如下: 若 int num; char *str="1234"; num=atoi(str);   則整數變數 num 的值就會是 1234 了。

要將數值變成字串,就使用 itoa 函數,其函數原型如下:   #include <stdlib.h> char *itoa (int value, char *str, int radix); 其中 value 是待轉換的數值,str 是轉換後的字串,radix 是數值的基底,傳回值和 str 一樣的指標。記得要替 str 預留空間來存結果字串。 用法的範例如下: int num=12345; char str[17]; itoa(num,str,10); 則 str 的值就會是字串 "12345" 了

(2) atol 函數是將 ASCII 字串轉換成 long 長整數,其函數原型如下:   #include <stdlib.h> long atol (const char *s );   用法的範例如下: long num; char *str="987654321"; num=atol(str);

ltoa 函數是將 long 長整數轉換成 ASCII 字串,其函數原型如下:   #include <stdlib.h> char *ltoa (long value,char *str,int radix); 用法的範例如下: long num; char str[33]; ltoa(num,str,10);

(3) atof 函數是將 ASCII 字串轉換成浮點數,其函數原型如下:   #include <stdlib.h> double atof (const char *s ); 用法的範例如下: float num; char *str="12345.67"; num=atof(str);

fcvt 函數是將浮點數轉換成 ASCII 字串,其函數原型如下: #include <stdlib.h> char *fcvt (double value,int ndigit, int *dec, int *sign); 其中 ndigit 是有效位數,*dec 表示小數點在結果字串的第幾個字元,*sign 表示是否為 >= 0 的結果。 用法的範例如下: double num; char *str; int dec,sign,ndigit=5; num=9.876; str=fcvt(num,ndigit,&dec,&sign); printf("string=%s decimal place=%d sign=%d",str,dec,sign);

(4) 指定格式的字串輸出 sprintf 此函數用法類似 printf,其差異是 printf 輸出到螢幕,而 sprintf 將資料轉成指定格式後輸出到字串,傳回值為整數值但通常不使用,其一般用法如下例:   #include <stdio.h> char buffer[256]; int i; float c; sprintf(buffer,"%d inch = %f cm",i,c); puts(buffer);

【範例 9-4-1】 設計一程式,將下列字串由小排到大後,逐一印出。 Ford,Nissan,Mitsubishi,Toyota,Honda,Benz,BMW 3 #include <string.h> 4 void print_all (char *[ ], int ); 6 main () 7 { 8 static char *company[]= {"Ford","Nissan","Mitsubishi","Toyota", 9 "Honda","Benz","BMW" 10 }; 11 int i,j,n; 12 char *tp;

14 n=sizeof(company)/sizeof(char *); 15 printf("Before sort:\n"); 16 print_all(company,n); 17 for (j=n-2; j>=0; j--) 18 for (i=0; i<=j; i++) 19 if (strcmp(company[i],company[i+1])>0) 20 { tp=company[i]; 21 company[i]=company[i+1]; 22 company[i+1]=tp; 23 } 24 printf("after sort:\n"); 25 print_all(company,n);

28 void print_all (char *s[], int n) 29 { 30 int i; 31 32 for (i=0; i<n; i++) 33 puts(s[i]); 34 }