計算機程式設計實訓記錄(5)
前面關於排序演算法的任務沒有完成,我...我實在不知道怎麼辦了QAQ
不管了,跳過這個寫後面的吧。
C-字串處理
字串處理簡介
字串是程式設計中常用的一種資料。然而 C 語言中的字串(常稱為 C-字串)的概念、操作卻涉
及到陣列、指標、函式等概念。也正是這個原因,使得有關 C-字串的練習成為理解和掌握陣列、指標、
函式操作的極佳素材。
C-字串按字元陣列的形式存放在計算記憶體中,並且以特殊字元'\0'作為串結束標誌。其中的字元數
組被稱為字串的 容器,一般陣列、動態陣列(即堆陣列)或常量陣列都可能成為 C-字串的容器。C-字
符串的容器常常需要程式設計師花額外的精力進行管理,特別是需要保證有“足夠大”的容量。
由於 C-字串在記憶體中連續存放,又有串結束標誌字元,並且認為其容器已經設定妥當且容量“足夠
大”,在這樣的前提下,在 C 語言程式中,常將 char或 const char型別理解為 C-字串(變數)及
C-字串常量。
字串處理反例
反例一
#include <stdio.h> void GETS(char *p) { printf("\nInput a string: "); scanf("%s", p); } int main() { char *p1, *p2="Hello world!"; GETS(p1); printf("%s\n", p1); GETS(p2); printf("%s\n", p2); return 0; }
這個程式是可以編譯通過的,但是我們不難發現,p1指向不明,而p2指向不可寫的常量區,當我們執行的時候就會無法輸入。
那該怎麼修改呢?
char p1[80], p2[80];
或者
char *p1, p2[80];
p1 = (char*)malloc(80);
// ……
free(p1);
反例二
#include <stdio.h> int main() { unsigned long x=1234567890; char p[5]; unsigned long y=4210356789; gets(p); // 輸入字串,可能破壞x x = 1234567890; //修改x的值可能影響超長的字串 return 0; }
這個程式同樣沒有錯誤,但是可靠性不高。
串長<5時,無事發生。
串長<28時,同樣無事發生。
串長=28時,不可思議的事情發生了,在修改了x的值後字串變化了。
串長>28時,不可思議的事情發生了,x和字串都遭到過破壞。
不過,我們同樣可以發現,無論x和str怎麼變化,y都不受影響。
我們可以用一張圖來解釋這一切:
可以看到,y作為後宣告的變數佔據了最外層的記憶體空間,str的大小和x的再賦值都影響不到y。
C-字串處理常見錯誤
- 關於容器:
- 沒有設定容器
- 容器位於常量區
- 容器的容量太小
- 關於串結束標誌:
- 沒有在適當的位置設定串結束標誌
- 串結束標誌被破壞
- 直接使用賦值運算子、關係運算符等
- 字串拷貝 (應該使用strcpy函式)
- 字串拼接 (應該使用strcat函式)
- 字串比較 (應該使用strcmp函式)
課程任務
自定義函式實現C-字串基本操作
C 語言中,對 C-字串的操作體現在若干標準函式,如 strlen、strcpy、strncpy、strcat、strcmp、
atoi、atof、gets、puts、sprintf, sscanf 等。
本部分練習要求實現如下 5 個函式,函式原型已經給定:
unsigned int StrLen(const char *str); // 計算字串的長度
char *StrCpy(char *dest, const char *source); // 字串複製(拷貝)
char *StrCat(char *dest, const char *source); // 字串拼接
int StrCmp(const char *str1, const char *str2); // 字串比較(按 ASCII 序)
int AtoI(const char *str); // 將字串轉換成整數
StrLen
遍歷一遍即可
unsigned int StrLen(const char *str)// 計算字串的長度
{
unsigned int i;
for(i=0;str[i];i++);
return i;
}
StrCpy
同樣遍歷一遍
char *StrCpy(char *dest, const char *source) // 字串複製(拷貝)
{
int i;
for(i=0;source[i];i++)
{
dest[i]=source[i];
}
dest[i+1]='\0';
return dest;
}
StrCat
這裡可以用到前面的StrLen
char *StrCat(char *dest, const char *source) // 字串拼接
{
int i;
unsigned int n;
n=StrLen(dest);
for(i=0;source[i];i++)
{
dest[n+i]=source[i];
}
return dest;
}
不過奇怪的是,我一開始使用dest[StrLen(dest)+i]=source[i];
卻無法實現,可能是型別轉換的問題?
StrCmp
首先我們要知道作為原型的strcmp()
是怎麼一回事。