第九章-字符串

简介

  1. 在第七章-数组与第八章-指针中都简单的讲了字符串
  2. 本章将着重讲解C语言的字符串
  3. 在各种编程语言中,字符串的地位都十分重要,C语言中并没有提供“字符串”这个特定类型,而是以特殊字符数组的形式来存储和处理字符串,这种字符数组必须以空字符’\0’结尾,因此,也将这种特定字符数组称为C风格字符串
  4. 本节讨论字符串和字符串的一些处理函数。 C风格字符串是字符数组的一种特例,这个“特”字体现在“以’\0’(空字符,null character)结尾”,如何声明创建一个C风格字符串,如何使用C风格字符串,这是本节要解决的问题

字符数组

  1. 字符数组的定义
    1. 形式为:
      1. char  数组名[ 常量表达式 ];
      2. 如:char a[100];
      3. 定义了一个字符数组,名字叫c;
      4. a数组的数据类型是char
      5. [100] 表示a中存储有100个字符元素;
      6. 这100个字符元素的名字分别是:[0],a[1],a[2], …… ,a[99]
  2. 字符数组的初始化
    1. 字符数组的常见初始化形式如下例:

       char c[5]={ ‘a’,’b’,’c’,’d’,’e’ };
      
      1. 如果初始化时初值个数大于数组长度,会报错。
      2. 如果初始化时初值个数小于数组长度,系统会为剩余元素自动赋值为’\0’ 。
    2. C语言允许用字符串常量来初始化字符数组:
      1. char c[100] ={"C Program"};
      2. 上面的例子也可以写成:char c[100] ="C Program";
    3. 两种初始化的区别:
      1. 字符串就是字符数组,字符数组不一定是字符串

         //字符串就是结尾带\0的字符数组,只是展示方式不同
         // "jack" == {'j','a','c','k','\0'}
        
      2. 字符串的一个初始化

         void test2()
         {
             // 都是字符串
             char name[8] = "it";
             char name2[8] = {'i', 't', '\0'};
             // \0的ASCII码值是0(相当于\0)
             char name3[8] = {'i', 't', 0};
             //元素不够,直接补零(相当于\0)
             char name4[8] = {'i', 't'};
             // 不算是一个字符串(只能说是一个字符数组)
             char name5[] = {'i', 't'};
         }
        
  3. 字符数组的输入输出
    1. 字符指针变量与字符数组
      1. char  *cp; 与 char str[20];
      2. str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址

         char  str[20];     
         str=“I love China!”;  //错误
         char   *cp; 
         cp=“I love China!”;   //正确
        
        1. str是地址常量;cp是地址变量
    2. cp接受键入字符串时,必须先开辟存储空间

       //正确
       char  str[10];
              scanf(“%s”,str); 
              //错误
              char  *cp;
              scanf(“%s”,  cp); 
                  
              //修改为
              char *cp,str[10];
              cp=str;
              scanf(“%s”,cp);     
      
    3. 字符指针输出字符

      void main( )
             {   char  *string=“I  love China!”;
                  printf(“%s\n”,string);
                  string+=7;
                  while(*string)
                   {      putchar(string[0]);
                           string++;
                    }
              } 
      
  4. 字符串与字符数组的关系
    1. 字符串用一维字符数组存放
    2. 字符数组具有一维数组的所有特点
      1. 数组名是指向数组首地址的地址常量
      2. 数组元素的引用方法可用指针法和下标法
      3. 数组名作函数参数是地址传递等
    3. 区别
      1. 存储格式:字符串结束标志
      2. 赋值方式与初始化
      3. 输入输出方式:%s  %c

(char *a  char a[])小结

用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不应混为一谈,主要有以下几点

  1. 字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第1个字符的地址),决不是将字符串放到字符指针变量中。
  2. 赋值方式。可以对字符指针变量赋值,但不能对数组名赋值。

     char *a; a=”I love China!”;  // 对
     char str[14];str[0]=’I’;  // 对
     char str[14]; str=”I love China!”; //错
    
  3. 初始化的含义

     char *a=”I love China!”; 与
     char *a; a=”I love China!”;等价
     char str[14]= ”I love China!”;与
     char str[14];  str[]=”I love China!”;    不等价
    
  4. 存储单元的内容
    1. 编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元存储地址

       char *a; scanf(“%s”,a);  // 错
       char *a,str[10];      
       a=str;                  
       scanf (“%s”,a);      //对 
      
  5. 指针变量的值是可以改变的,而数组名代表一个固定的值(数组首元素的地址),不能改变。

     int main()
     { char *a="I love China!";//不能改为char a[]=“I love China!”;
     //只有变量才能加,如果为a[],那么a就是常量了
        a=a+7;    
        printf(“%s\n”,a);   
        return 0;}
    
  6. 字符数组中各元素的值是可以改变的,但字符指针变量指向的字符串常量中的内容是不可以被取代的。

     char a[]=”House”,*b=” House”;
     a[2]=’r’;        对
     *(b+3) = 'x';    //错误,因为” House”在常量区是不能被修改的
    
  7. 引用数组元数
    1. 对字符数组可以用下标法和地址法引用数组元素(a[5],*(a+5))。如果字符指针变量p=a,则也可以用指针变量带下标的形式和地址法引用(p[5],*(p+5))。
    2. char *a=″I love China!″;
    3. 则a[5]的值是第6个字符,即字母’e’
  8. 用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串。

     char *format;
     format=”a=%d,b=%f\n”; 
     printf(format,a,b);
     相当于printf(“a=%d,b=%f\n”,a,b);
    

字符串的操作:

  1. 字符串的初始

     char a[100] = "I Love China";
     char b[] = "I Love China";
     char *c = "I Love China";
     char d[6] = { 'c', 'h', 'i', 'n', 'a', '\0' };
     printf("%s\n", a);
     printf("%s\n", b);
     printf("%s\n", c);
     printf("%s\n", d);
    
  2. 相关输入输出函数处理字符串
    1. scanf和printf

       char ch[100];
       scanf(“%s”,ch);/*空格、制表符、换行为分隔符*/
      
       printf(“%s”,ch);/*输出后不会自动换行*/
      
    2. gets和puts

       char ch[100];
       gets(ch);/*回车为分隔符*/
      
       puts(ch); /*输出后会自动换行*/
      
  3. 字符串复制函数strcpy

     #include <stdio.h> 
     #include <string.h>
     void main(void)  /*主函数*/
     {
     char str1[256]={'\0'};  /*开辟一字符数组str1*/
     char str2[256]={'\0'};  /*开辟一字符数组str2*/
     printf ("请输入第1个字符串: \n");  /*提示用户输入第1个字符串*/
     gets (str1);  /*使用gets函数读取一行输入*/
     strcpy(str2,str1);  /*将第1个字符串复制给第2个字符串*/
     printf("第2个字符串为:\n%s",str2);  /*输出第2个字符串*/
     getchar();    /*等待,按任意键继续*/
     }
    
  4. 字符串的拼接
    1. sprintf函数:把格式化的数据写入某个字符串缓冲区。
    2. 形式:int sprintf( char *buffer, const char *format, [ argument] … );
      1. buffer:char型指针,指向将要写入的字符串的缓冲区。
      2. format:格式化字符串。
      3. [argument]…:可选参数,可以是任何类型的数据。
      4. 返回值:字符串长度(strlen)
    3. 代码示例:

       //字符串拼接
       void test3(){
       	//调用window系统的cmd命令连续打开5个计算器
       	//char a[100] = "for /l %i in (1,1,5) do calc";
       	//system(a);
       	//格式化一个字符串把他打印出来
       	//printf("for /l %%i in (1,1,%d) do %s", 5, "calc");
              
       	//printf:是往屏幕里面输出
       	//sprintf:是往字符串里面输出
       	char a[100] = { 0 };
       	int num = 0;
       	char op[30] = { 0 };
       	//通过屏幕输入
       	scanf("%d%s", &num, op);
       	//拼接新的字符串,此时的a已经是新的字符串了
       	sprintf(a, "for /l %%i in (1,1,%d) do %s", num, op);
       	//调用新的字符串
       	system(a);
       }
      
  5. 字符串的分离:
    1. 形式 int sscanf( string str, string fmt, mixed var1, mixed var2 ... );
    2. sscanf与scanf类似,都是用于输入的,只是后者以键盘(stdin)为输入源,前者以固定字符串为输入源。
    3. 代码举例:

       //字符串分离
       void test4(){
       	//scanf 是屏幕输入
       	//sscanf 是字符串输入
       	//提取出1000,要输入的字符串
       	char a[100] = "我有1000元";
       	//要分离出的数据
       	int num;
       	//字符串输入分离
       	sscanf(a, "我有%d元", &num);
       	//打印为1000
       	printf("%d", num);
       }
      
  6. 字符串的查找
    1. 函数:strstr()
    2. strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。
    3. 找到所搜索的字符串,则该函数返回第一次匹配的字符串的地址;如果未找到所搜索的字符串,则返回NULL。
    4. 函数名: strstr
    5. 函数原型:extern char *strstr(const char *str1, const char *str2);
    6. 语法:* strstr(str1,str2)
    7. str1: 被查找目标 string expression to search.
    8. str2: 要查找对象 The string expression to find.
    9. 返回值:若str2是str1的子串,则先确定str2在str1的第一次出现的位置,并返回此位置到str1末尾的所有字符;如果str2不是str1的子串,则返回NULL。(注:若想返回str2在str1第一次出现的位置,不是这个函数)
    10. 代码举例:

      int main(){
      	char str[100] = "my name is cheng";
      	char str2[20] = "chen";
      	char *p = strstr(str, str2);
      	if (p == NULL){
      		printf("没有找到");
      	}
      	else
      	{
      		printf("找到");
      	}
      	getchar();
      	return 0;
      }
      
  7. 字符串的比较
    1. strcmp函数:
    2. C/C++函数,比较两个字符串。设这两个字符串为str1,str2,若str1==str2,则返回零;若str1>str2,则返回正数;若str1<str2,则返回负数。
    3. 原型:extern int strcmp(const char *s1,const char * s2);
    4. 所在头文件:string.h
    5. 功能:比较字符串s1和s2。
    6. 一般形式:strcmp(字符串1,字符串2)
    7. 说明:
      1. 当s1<s2时,返回为负数
      2. 当s1=s2时,返回值= 0
      3. 当s1>s2时,返回正数
    8. 即:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。如: A"<"B" "a">"A" "computer">"compare"
    9. 特别注意:strcmp(const char *s1,const char * s2)这里面只能比较字符串,不能比较数字等其他形式的参数。
  8. 字符串前n字母比较函数
    1. 函数名:strncmp
    2. 功能:比较字符串的前N个字节
    3. 用法:比较字符串str1和str2的大小,如果str1小于str2,返回值就<0,如果相等就=0;len指的是str与str2比较的字符数。
    4. 比较2个字符串的前7个字节:strncmp(str1,str2,7);
  9. 字符串处理函数strchr
    1. 功能: 查找字符串str中首次出现字符c的位置
    2. 说明:返回首次出现c的位置指针,如果str中不存在c,则返回NULL;
    3. char *p = strchr(str,'c');
  10. 字符串连接函数strcat
    1. 字符串连接函数的原型为:char* strcat(字符串1,字符串2);
    2. 所在头文件:string.h
    3. 功能:
      1. 把字符串2的前n个字符添加到字符串1结尾处(覆盖字符1结尾处的\0),并添加\0。
    4. 说明:字符串1、字符串2所指向内存区域不能重叠,字符串1必须有足够的空间,来容纳字符串2
    5. 返回指向字符串1.
    6. 示例:strcat("333", "ddd", 2);
  11. 字符串处理函数atoi
    1. 函数名:atoi
    2. 功能:将字符串转换成整形数
    3. 示例

       char a[18] = "e8848";
       int num = atoi(a);
       //转化的时候,传递字符串的地址,地址不要求是首地址,
       //字符串的任何地址都可以,num起到接受赋值作用,
       //转化成功就是整数,失败就是0,出现非数字字符就会转化失败
      
  12. strset
    1. 函数名:strset
    2. 功能:将一个串中的所有字符都设为指定字符
    3. 示例:

       char str[20] = "eee888";
       _strset(str,‘8’);
       //str就全部是:”888888“
      
  13. strrev
    1. 功能:串倒转
    2. 示例

       char *str =  strrev("123");
         //"321"
      
  14. 字符大小写转换函数
    1. 函数名:strlwr
    2. 功能:大小写转换
    3. 程序例:

       //大写转小写
       char *str =  strlwr("ABC");
      
    4. Strupr字符串全部转大写
      1. 在某些场合,要求输入一个字符串,如果是大小写无关的,问题就来了,比如,在大小写无关意义下,“AB”、“ab”、“aB”、“Ab”都是等价的,这仅仅是两个字母的情况,如果字母更多,情况更复杂,在程序中去一一判断也很不现实,为此,C标准库提供了字符串处理函数strupr,用于将字符串中所有的字母都转换成大写形式,其原型为;
      2. char* strupr(字符串);
  15. 常用内存函数
    1. memset
      1. 在头文件memory.h中 头文件memory.h为内存操作函数头文件
      2. 第一个参数是内存的首地址,第二个参数是要设置的字符,第三个参数是正数,从首地址开始设置多少个字节为第二个参数
      3. 多用于清空字符串,用法 memset(str,’\0’,strlen(str));
      4. 示例:

         //内存替换
         char str[100] = "falksjaldjladsjfjkl";
         memset(str, 'A', 10);
         printf("%s\n", str);
        
    2. memcpy
      1. memcpy 是字符串覆盖函数,在头文件memory.h中
      2. memcpy 的三个参数 第一个参数是被覆盖的字符串,第二个参数是覆盖到的字符串,第三个参数是覆盖的字符串的位数
      3. 下面代码为 从字符串str1中复制5位字符覆盖掉str的前5位。

         char str[100] = "falksjaldjladsjfjkl";
         char str1[100] = "11111111";
         memcpy(str, str1, 5);
         printf("%s\n", str);
        
Table of Contents