第十周:字符串

简介: 字符串是在每个语言中都高频出现的知识点

10.1-1字符数组

  1. char word[] = {'H','e','l','l','o','!'};

这(指1)不是C语言的字符串,因为不能用字符串的方式做计算

  1. char word[] = {'H','e','l','l','o','!','\0'};
word[0] H
word[1] e
word[2] l
word[3] l
word[4] o
word[5]
word[6] \0

字符串

  1. 以0(整数0)结尾的一串字符
  1. 0或者'\0'是一样的,但是和'0'不同
  1. 0标志字符串的结束,但它不是字符串的一部分
  1. 计算字符串长度的时候不包含这个0
  1. 字符串以数组的形式存在,以数组或者指针的形式访问
  1. 更多的是以指针的形式

string.h里有很多处理字符串的函数

  1. C语言的字符串是以字符数组的形态存在的
  1. 不能用运算符对字符串做运算
  2. 通过数组的方式可以遍历字符串
  1. 唯一特殊的地方是字符串字面量可以用来初始化字符数组
  2. 以及标准库提供了一系列字符串函数

10.1-2字符串变量

  1. char *str = "Hello";
  2. char word[] = "hello";
  3. char line[10] = "Hello";结尾编辑器会自动补0,多占据一个位置
  4. "Hello会被编译器变成一个字符数组放在某处,这个数组的长度是6,结尾还有表示结束的0"
  5. 两个相邻的字符串常量会被自动连接起来

字符串常量

char* s = "Hello,world";

  1. s是一个指针,初始化为指向一个字符串常量
  1. 由于这个常量所在的地方,所以实际上s是const char *s,但是由于历史的原因,编译器接受不带const的写法
  2. 但是试图对s所指的字符串做写入会导致严重的后果
  3. 如果有两处相同的地方,指针会同时指向同一处地方,所以指针必须是只读的
  1. 如果需要修改字符串,应该用数组:
  1. char s[] = "Hello,world!";
  2. 这个数组跟指针的区别就是,指针指向某一处地方,而数组则表示就在我这里
  3. 会将放在不可写的"Hello,world!"数组内容拷贝到你的s那里去

当我们需要一个字符串的时候,指针还是数组?

  1. char*str = "Hello";
  2. char word[] = "Hello";
  3. 数组:这个字符串在这里
  1. 作为本地变量空间自动被回收
  1. 指针:这个字符串不知道在哪里
  1. 处理参数
  2. 动态分配空间
  3. 用在只需要只读的,不打算去往里面写入东西的。表达函数的参数。
  1. 如果要构造一个字符串->数组
  2. 如果要处理一个字符串->指针

char*是字符串?

  1. 字符串可以表达为char*的形式
  2. char*不一定是字符串
  1. 本意是指向字符的指针,可能指向的是字符的数组(就像int*一样)
  2. 只有当char*所指向的字符数组有结尾的0,才能说它所指的是字符串

10.1-3字符串输入输出

  1. char*t = "title";
  2. char*s;
  3. s = t;
  4. 并没有产生新的字符串,只是让指针s指向了t所指的字符串,对s的任何操作就是对t做的
  5. char string[8];
  6. scanf("%s",string);
  7. printf("%s\n",string);
  8. scanf读入一个单词(到空格、tab或回车为止),但scanf这样是不安全的,因为不知道要读入内容的长度

安全的输入

  1. char string[8];
  2. scanf("%7s",string);
  3. 在%s中间可以加入数字来让编译器知道需要限制在多少字符范围内(或者说最多允许读入的字符数量),比如%7s,限制在7个字符范围(超出部分就不会读入了)

常见错误

  1. char*string;
  2. scanf("%s",string);
  3. 以为char("%s".string);
  4. 以为char*是字符串类型,定义了一个字符串类型的变量string就可以直接使用了
  1. 由于没有对string初始化为0,所以不一定每一次运行都出错(实际上这是错误的,指针用错了,没有指向一个确定的地方)

空字符串

  1. char buffer[100] = "";
  1. 这是一个空的字符串,buffer[0] == '\0'
  1. char buffer[] = "";
  1. 这个数组的长度只有1!所以后面放不下任何的字符串

10.1-4字符串数组以及程序参数

字符串数组

  1. char **a
  1. a是一个指针,指向另一个指针,那个指针指向一个字符(串)
  1. char a
  1. 一个错误的二维数组,因为没有说明几列,所以会报错
  2. 可以修改成char a[],本质上就相当于a[0]--->char

程序参数

  1. int main(int argc,char const*argv[])
  2. argv[0]是命令本身
  1. 当使用Unix的符号链接时,反应符号链接的名字

#include

intmain(intargc, charconst*argv[])

{

   inti;

   for( i=0; i<argc; i++){

       printf("%d:%s\n",i,argv[i]);

   }

   

   return0;

}

10.2-1单字符输入输出,用putchar和getchar

putchar

  1. int putchar(int c);
  2. 向标准输出写一个符号
  3. 返回写了几个字符,EOF(-1)表示写失败

getchar

  1. int getchar(void);
  2. 从标准输入读入一个字符(跟scanf的区别是scanf可以一次性读入多个字符)
  3. 返回类型是int是为了返回EOF(-1)
  1. window-->Ctrl-Z
  2. Unix-->Ctrl-D(返回EOF)
  3. Ctrl-C会将shell与实际上显示的的通道关闭掉了

#include

intmain(intargc,charconst*argv[])

{

   intch;

   

   while( (ch=getchar()) !=EOF ){

       putchar(ch);

   }

   printf("EOF\n");

   

   return0;

}

在我们输入的东西(在键盘上敲出来的东西被称为行编辑的工作)的时候,那些都会被暂时放在shell里(类似缓冲区域),当我们按下回车之后,才会发送到实际上显示的地方上

10.2-(2-6)字符串函数strlen

string.h

  1. strlen
  1. size_t strlen(const char *s);
  2. 返回s的字符串长度(不包括结尾的0)
  1. strcmp
  1. int strcmp(const char *s1,const char *s2);
  2. 比较两个字符串,返回:    0:s1==s2,1:s1>s2,-1:s1
  1. strcpy
  1. charstrcpy(charrestrict dst,const char *restrict src);
  2. 把src的字符串拷贝到dst
  1. restrict表明src跟dst不重合
  1. 返回dst
  1. 为了能链起代码
  1. 复制一个字符串
  1. chardst = (char)malloc(strlen(src)+1); //之所以加一是因为结尾会自带\0,所以需要多一个位置
  2. strcpy(dst,src);
  1. strcat
  1. char*strcat(char *restrict s1,const char *restrict s2);
  2. 把s2拷贝到s1的后面,接成一个长的字符串
  3. 返回s1
  4. s1必须具有足够的空间
  1. strchr
  1. 字符串中找字符
  2. char*strchr(const char *s,int c);表示从左边找过来
  3. charstrrchr(const chars,int c);表示从右边找过来
  4. 返回NULL则表示没有找到
  5. 如何寻找第二个?寻找第二个的方法:

p = strchr(p+1,'l');

printf("%s\n",p);

  1. strstr
  1. 在字符串中寻找单个字符的
  1. char* strstr(const char *s1,const char *s2);
  1. 在寻找的时候忽略大小写
  1. char*strcasestr(const char *s1,const char *s2);

#include

#include

size_tmylen(constchar*s)

{

   intcnt=0;

   intidx=0;

   while(s[idx] !='\0' ){

       idx++;

       cnt++;

   }

   returncnt;

}

intmain(intargc,charconst*argv[])

{

   charline[] ="Hello";

   printf("strlen=%lu\n",mylen(line));

   printf("sizeof=%lu\n",sizeof(line));

   

   return0;

}

#include

#include

intmycmp( constchar*s1, constchar*s2)

{

   //int idx = 0;

   //while( s1[idx] == s2[idx] && s1[idx]!='\0' ){

//  idx ++;

//}

   while( *s1==*s2&&*s1!='\0'){

       s1++;

       s2++;

   }

   return*s1-*s2;

}

intmain(intargc, charconst*argv[])

{

   chars1[] ="abc";

   chars2[] ="abc";

   printf("%d\n",mycmp(s1,s2));

   printf("%d\n",'a','A');

   

   return0;

}

#include

#include

char*mycpy(char*dst, constchar*src)

{

   intidx=0;

   while(src[idx] !="\0"){

       dst[idx] ==src[idx];

       idx++;

   }

   dst[idx] ='\0';

//   char* ret = dst;  

//   方法1:while(*src != '\0'){

//       *dst++ = *src++;

//   }

   //方法2:while(*dst++ = *src++);   嗯,没了,就一行直接替换掉了方法1,还有比方法1代码还有更长的版本我没有记录

// *dst = '\0'; 这是指针的写法

   returndst;

}

intmain(intargc, charconst*argv[])

{

   chars1[] ="abc";

   chars2[] ="abc";

   strcpy(s1,s2);

   

   return0;

}

安全问题

  1. strcpy跟strcat都可能出现安全问题
  1. 如果目的地没有足够的空间?
  2. 建议是尽量不要去使用他
  1. 安全版本
  1. char* strncpy(charrestict dst, const char restrict src,size_t n);
  2. char* strncat(charrestict s1, const char restrict s2,size_t n);
  3. size_t n表示最多能够接受多少个n个字符,多了就直接掐掉
  4. int strncmp(const char *s1,const char *s2,size_t n);
  5. 这个则表示最多能够判断几个字符,超出则不判断

#include

#include

intmain(intargc, charconst*argv)

{

   chars[] ="hello";

   char*p=strchr(s,'l');

   

   printf("%s\n",p);  //结果为llo

   //寻找第二个的方法:

   //p = strchr(p+1,'l');

   //printf("%s\n",p);结果为lo

   

   return0;

}

---------------------------------------------------

  将起选取的内容拷贝到其他地方的方法

   intmain(intargc, charconst*argv)

{

   chars[] ="hello";

   char*p=strchr(s,'l');

   char*t= (char*)malloc(strlen(p)+1);

   strcpy(t,p);

   printf("%s\n",t);

   free(t); // 申请来的空间记得释放掉哦

   //这是将llo的字符拷贝走了

   return0;

}

-------------------------------------------------------

     将起选取的内容拷贝到其他地方的方法2版本

   intmain(intargc, charconst*argv)

{

   chars[] ="hello";

   char*p=strchr(s,'l');

   charc=*p;

   *p='\0';

   char*t= (char*)malloc(strlen(s)+1);

   strcpy(t,s);

   printf("%s\n",t);

   free(t); // 申请来的空间记得释放掉哦

   //这是将he的字符拷贝走了

   return0;

}

目录
相关文章
|
6月前
判断星期几
【6月更文挑战第10天】判断星期几。
42 2
|
6月前
|
Java
java8日期计算(偏移N周,返回指定星期的日期)
java8日期计算(偏移N周,返回指定星期的日期)
|
7月前
|
Java
自定义字符串转换为周几和指定日期格式
自定义字符串转换为周几和指定日期格式
46 0
|
7月前
日期字符串转化为年月日
日期字符串转化为年月日
47 0
|
7月前
日期工具,校验当年开始年份,结束年份,当月开始日期,结合素日期
日期工具,校验当年开始年份,结束年份,当月开始日期,结合素日期
判断月份天数
判断月份天数
56 0
|
安全 Java Unix
第七周:函数
C语言会是你敲开编程大门的第一个语言吗?
108 0
|
人工智能 编译器 程序员
第八周:数组
数组的魅力才刚刚开始,在其他地方你都能看到他
98 0
Base64编码 url编码 获取当月所有日期 获取当月第一天和最后一天
Base64编码 url编码 获取当月所有日期 获取当月第一天和最后一天