天天看點

C語言學習筆記(六)字元串一、字元串二、字元串函數

C語言學習筆記(六)字元串

  • 一、字元串
    • (1)字元串
      • 1.1 字元數組
      • 1.2 字元串
      • 1.3 字元串變量
      • 1.4 字元串常量
      • 1.5 總結
    • (2)字元串變量
      • 2.1字元串常量
      • 2.2 指針還是數組?- char* str="Hello";
      • 2.3 char*是字元串?
    • (3)字元串輸入輸出
      • 3.1字元串指派?
      • 3.2安全的輸入
      • 3.3常見錯誤
    • (4)字元串數組以及程式參數
      • 4.1 字元串數組
      • 4.2 程式參數
  • 二、字元串函數
    • (1)單字元輸入輸出
      • 1.1 putchar
      • 1.2 getchar
      • 1.3 測試代碼
    • (2)字元串函數strlen
      • 2.1 函數原型
    • 2.2 測試代碼
    • (3)字元串函數strcmp
      • 3.1 函數原型
      • 3.2 測試代碼
    • (4)字元串函數strcpy
      • 4.1 函數原型
      • 4.2 測試代碼
    • (5)字元串函數strcat
      • 5.1 函數原型
      • 5.2 安全問題
    • (6)字元串搜尋函數

一、字元串

(1)字元串

1.1 字元數組

  • List item
  • char word[]={‘H’,‘e’,‘I’,‘I’,‘o’,’!’};

1.2 字元串

  • char word[]={‘H’,‘e’,‘I’,‘I’,‘o’,’!’,’\0’};
  • 以0(整數0)結尾的一串字元
  • 0或’\0]是一樣的,但是和’0’不同
  • 0标志字元串的結束,但它不是字元串的一部分
  • 計算字元串長度的時候不包含這個0
  • 字元以字元數組的形式存在,以數組或指針的形式通路
  • 更多的以指針形式
  • string.h裡有很多處理字元串的函數

1.3 字元串變量

  • char *str=“Hello”;
  • char word[]=“Hello”;
  • char line[10]=“Hello”;

1.4 字元串常量

  • “Hello”
  • "Hello"會被編譯器變成一個字元串數組放在某處,這個數組的長度是6,結尾還有表示結束的0
  • 兩個相鄰的字元串常量會被自動連接配接起來

1.5 總結

  • c語言的字元串是以字元數組的形态存在的
    • 不能用運算符對字元串做運算
    • 通過數組的方式可以周遊字元串
  • 唯一特殊的地方是字元串字面量可以用來初始化字元數組
  • 以及标準庫提供了一系列字元串函數

(2)字元串變量

2.1字元串常量

  • char *s = “Hello World”;
  • s是一個指針,初始化為指向一個字元串常量
    • 由于這個常量所在的地方,是以實際上s是const char* s,但是由于曆史的原因,編譯器接受不帶const的寫法
    • 但是試圖對s所指的字元串做寫入會導緻嚴重的後果
  • 如果需要修改字元串,應該用數組:
    • char s[] = “Hello,world!”;
//可以編譯,但不能執行
#include<stdio.h>
int main(void)
{
	char *s="Hello World";
	s[0]='B';
	printf("Here:s[0]=%c\n",s[0]);
	return 0;
//字元串探究
#include<stdio.h>
int main(void)
{
	int i;
	char *s="Hello World";
	char *s2="Hello World";
	char s3="Hello World";
	printf("i=%p\n",&i);
	printf("s=%p\n",s);
	printf("s2=%p\n",s2);
	printf("s3=%p\n",s3);
	s[3]=B;
	printf("Here:s[0]=%c\n",s[0]);
	printf("Here:s[3]=%c\n",s[3]);
	return 0;
           

2.2 指針還是數組?- char* str=“Hello”;

  • char word[]=“Hello”;
  • 數組:這個字元串在這裡

    作為本地變量空間自動被回收

  • 指針:這個字元串不知道在哪裡
    • 處理參數
    • 動态配置設定空間
  • 如果要構造一個字元串–>數組
  • 如果要處理一個字元串–>指針

2.3 char*是字元串?

  • 字元串可以表達為char*的形式
  • char*不一定是字元串
    • 本意是指向字元的指針,可能指向的是字元的數組(就像int*一樣)
    • 隻有它所指的字元數組有結尾的0,才能說它指的是字元串

(3)字元串輸入輸出

3.1字元串指派?

  • char *t=“title”;
  • char *s;
  • s=t
  • 并沒有産生新的字元串,隻是讓指針s指向了t所指的字元串,對s的任何操作就是對t做的
  • scanf讀入一個單詞(到空格、tab或回車為止)

3.2安全的輸入

  • char string[8];
  • scanf("%7s",string);
  • 在%和s之間的數字表示最多允許讀入的字元的數量,這個數字應該比數組的大小小一

    下一次scanf從哪裡開始?

3.3常見錯誤

  • char *string
  • scanf("%s",string);
  • 以為char*是字元串類型,定義了一個字元串類型的變量string就可以直接使用了
    • 由于沒有對string初始化為0,是以不一定每次運作都出錯
  • 空字元串
  • char buffer[100]="";
    • 這是一個空的字元串,buffer[0]==’\0’;
  • char buffer[]="";
    • 這個數組的長度隻有1!
#include<stdio.h>
int main(void)
{
	char word[8];
	scanf("%7s",word);	//防止數組越界
	printf("%7s\n",word);	//防止數組越界
	return 0;
           

(4)字元串數組以及程式參數

4.1 字元串數組

  • char **a
    • a是一個指針,指向另一個指針,那個指針指向一個字元(串)
  • char a[][10]
    • a是一個數組,數組中的每一個單元相當于b[10]
  • char *a[];
    • a是一個指針,每個元素都指向字元串

4.2 程式參數

  • int main(int argc,char const *argv[])
  • argv[0]是指令本身
    • 當使用Unix的符号連結時,反映符号連結的名字
#include<stdio.h>
int main(int argc,int const* argv[])
{
	int i;
	for(i=0;i<argc;i++){
		printf("%d:%s\n",i,argv[i]);
	}
	return 0;
}
           

二、字元串函數

(1)單字元輸入輸出

1.1 putchar

  • int putchar(int c);
  • 向标準輸出寫一個字元
  • 傳回寫了幾個字元,EOF(-1)表示寫失敗

1.2 getchar

  • int getchar(void)
  • 從标準輸入讀入一個字元
  • 傳回類型是int是為了傳回EOF(-1)
    • Windows–>Ctrl-Z
    • Unix–>Ctrl-D

1.3 測試代碼

#include<stdio.h>
int main(int argc,char const *argv[])
{
	int ch;
	while((ch = getchar())!=EOF){
		putchar(ch);
	}
	printf("EOF\n");
	return 0;
}
           

(2)字元串函數strlen

2.1 函數原型

  • size_t strlen(const char *s);
  • 傳回s的字元串長度(不包括結尾的0)

2.2 測試代碼

//測試一下strlen
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char const *argv[])
{
	char line[]="Hello";
	printf("strlen=%lu\n",strlen(line));
	printf("sizeof=%lu\n",sizeof(line));
	return 0;
}
//自己寫一個strlen吧
size_t myStrlen(const char *str)
{
	int count=0;
	while(str[count]!='\0'){
		count++;
	}
	return	count
}
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char const *argv[])
{
	char line[]="Hello";
	printf("strlen=%lu\n",myStrlen(line));
	printf("sizeof=%lu\n",sizeof(line));
	return 0;
}
           

(3)字元串函數strcmp

3.1 函數原型

  • int strcmp(const char *s1,const char *s2);
  • 比較兩個字元串,傳回:
    • 0:s1=s2
    • 1:s1>s2
    • -1:s1<s2

3.2 測試代碼

//測試一下strcmp()
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char const *argv[])
{
	char s1[]="abc";
	char s2[]="bbc";
	printf("%d\n",strcmp(s1,s2));
	return 0;
}
//自己寫一個MyStrcmp()
#include<stdio.h>
#include<stdlib.h>
int MyStrcmp(char const *str1,char const *str2)
{
	while(*str1 == *str2 && *str1!='\0'){
		str1++;
		str2++;
	}
	return *str1-*str2;
}	
int main(int argc,char const *argv[])
{
	char s1[]="abc";
	char s2[]="bbc";
	printf("%d\n",MyStrcmp(s1,s2));
	return 0;
}
           

(4)字元串函數strcpy

4.1 函數原型

  • char* strcpy(char *restrict dst,const cahr *restrict src);
  • 把src的字元串拷貝到dst
    • restrict表明src和dst不重疊(C99)
  • 傳回dst
    • 為了能鍊起代碼來

4.2 測試代碼

//複制一個字元串
char *dst=(char*)malloc(strlen(src)+1);	//注意要+1
strcpy(dst,src);
//測試一下strcpy
#include<stdio.h>
#include<string.h>
int main(int argc,char const *argv[])
{
	char s1[]="abc";
	char s2[]="abb";
	strcpy(s1,s2);
	return 0;
}
//自己寫一個MyStrcpy()
#include<stdio.h>
#include<string.h>
char* MyStrcpy(char *dst,const const char* src)
{
	char *ret=dst;
	while(*dst++=*src++)
	;
	*dst='\0';
	return ret;
}
int main(int argc,char const *argv[])
{
	char s1[]="abc";
	char s2[]="abb";
	MyStrcpy(s1,s2);
	return 0;
}
           

(5)字元串函數strcat

5.1 函數原型

  • char* strcat(char *restrict s1,const char *restrict s2)
  • 把s2拷貝到s1後面,接成一個長的字元串
  • 傳回s1
  • s1必須具有足夠的空間

5.2 安全問題

  • strcpy和strcat都可能出現安全問題
    • 如果目的地沒有足夠的空間?
  • 安全版本
    • char* strncpy(char *restrict dst,const cahr *restrict src,size_t n);
    • char* strncat(char *restrict s1,const char *restrict s2,size_t n)
    • int strncmp(const char *s1,const char *s2,size_t n);

(6)字元串搜尋函數

  • 字元串中尋找字元
    • char* strchar(const char *s,int c);
    • char *strrchr(const char *s,int c);
    • 傳回NULL表示沒有找到
  • 字元串中尋找字元串
    • char *strstr(const char *s1,const char **s2);
    • cahr *strcasestr(const char *s1,const char *s2);

繼續閱讀