文章目录
一、字符串
1.字符串介绍
- 以 整数0 或者 ‘\0’ 结尾的一串字符。
- string.h里面有很多处理字符串的函数。
- 0标志字符串的结束,但它不是字符串的一部分,即计算字符串长度不包含这个0,
- 但是如果以’\0’结束,它是属于字符串的一部分。
- 字符串是以数组的形式存在:
- 以数组或指针的形式访问; 通过数组的方式可以遍历字符串;
- 不能用运算符对字符串做运算;
- 字符串会自动将两个相邻的字符串合并:
- printf(“hello, i am first line.”
“Here is the second line of automatic connection.”)
- printf(“hello, i am first line.”
- 唯一特殊的地方是字符串字面量可以用来初始化字符数组。
2.字符串变量
char *str = "hello"; 有一个指针指向hello
char word[] = "hello";
char line[10] = "hello";
"hello"会被编译器变成一个字符数组放在某处,这个数组的长度是6,
结尾还有表示结束的0。
3.字符串常量
char* s = "hello world";
- s是一个指针,初始化为指向一个字符串常量。
- 由于这个常量所在的地方是只读的,所以实际上s是const char* s;
- 但是由于历史原因,编译器接受不带const的写法;
- 但是试图对s所指的字符串做写入会导致严重的后果。
- 如果需要修改字符串应该使用数组:
char s[] = "hello world";
4.指针还是数组?
- char *str = “hello”;
- char word[] = “hello”;
- 数组: 这个字符串在这里
- 作为本地变量,空间自动被回收。
- 指针: 这个字符串不知道在哪里
- 用于处理参数。
- 用在动态分配空间的时候。
5.char*是字符串?
- 字符串可以表达为char*的形式。
- char*不一定都是字符串。
- 本意是指向字符的指针,可能指向的是字符数组(像int*一样)。
- 只有它所指的字符数组有结尾的0时,才能说是字符串。
6.字符串的赋值?(改变指针)
char *t = "title";
char *s;
s = t;
并没有产生新的字符串,只是将指针s指向了t所指的字符串,
对s的任何操作就是对t做的。真正的赋值需使用字符串函数。
7.字符串的输入输出
char string[9];
scanf("%s", string);
printf("%s", string);
- scanf读入一个单词(到空格、tab或回车为止)
- scnaf是不安全的,因为不知道要读入的内容的长度。
- 使用
scnaf("%7s",str)
表示最多读入7个元素。
8.常见错误
8.1 未初始化
char *string;
scanf("%s", string);
以为char*是字符串类型,定义了一个字符串类型的变量string就可以直接使用啦,
由于没有对string初始化为0,所以不一定每次运行都出错。
8.2 空字符串
char buffer[100] = "";
这是一个空的字符串,buffer[0] == '\0'。
char buffer[] = "";
这个数组的长度是1,且内容为0。
9.字符串数组
char **a
a是一个指针,指向另一个指针,那个指针指向一个字符(串)。
char a[][10]
每一个a[0]都被分为10个字符,里面写着hello,即10个位置没用完。
char *a[]
这种情况下a[0]相当于char*,a[0]是个指针,指向外面写着hello的某处。
10.程序参数
int main(int argc, char const *argv[])
argv[0]是命令本身,当使用Unix的符号链接时,反映符号链接的名字。
二、字符串函数
1.单字符的输入输出
putchar
int putchar(int c);
向标准输出写一个字符
返回写了几个字符,EOF(-1)表示写失败
getchar
int getchar(void);
从标准输入读入一个字符
返回类型是int,是为了返回EOF(-1)
Windows->Ctrl-Z Unix->Ctrl-D
int main(int argc, char const *argv[])
{
int ch;
while((ch = getchar()) != EOF){
putchar(ch);
}
printf("EOF\n");
return 0;
}
2.函数strlen
size_t strlen(const char *s);
返回s的字符串长度(不包括结尾的0)
char line[] = "hello";
printf("strlen=%lu\n", strlen(line)); //5 长度
printf("sizeof=%lu\n", sizeof(line)); //6 包括字符串特定的结尾0
3.函数strcmp
用来比较字符串,是区分大小写的。字符串大小按照ASCII码表上的顺序决定。
两个字符串相等时返回0;不相等时返回相减的差值。
char s1[] = "abc";
char s2[] = "abc";
char s3[] = "bbc";
printf("%d\n", s1==s2); //数组这样比较永远都是false
printf("%d\n", strcmp(s1,s2)); //相同大小时返回0
printf("%d\n", strcmp(s1,s3)); //不同时返回s1-s3的差值
4.函数strcpy
char* strcpy(char *restrict dst, const char *restrict src);
把src的字符串拷贝到dst,restrict表明src和dst不重叠(C99)。
会返回dst。(结果不需要赋值)
#include <stdlib.h>
char *dst = (char)malloc(strlen(src)+1);
//+1不要忘记,否则字符串最后的'\0'就没有空间存放啦
strcpy(dst,src);
5.函数strcat
char* strcat(char *restirct s1, const char *restrict s2);
把s2拷贝到s1的后面,拼接成一个长的字符串。
会返回s1。(结果不需要赋值) s1必须就有足够的空间。
char s1[] = "hello";
char s2[] = "world";
strcat(s1, s2);
printf("res = %s\n", s1);
6.安全问题
strcpy和strcat都可能出现安全问题,即如果目的地没有足够的空间怎末办?
安全版本:
> 参数 size_t n 即告诉你最多可以放入几个元素。
char* strncpy(char *restrict dst, const char *restrict src, size_t n);
char* strncat(char *restrict s1, const char *restrict s2, size_t n);
> 参数 size_t n 即告诉你仅判断前n个字符是否相同。
int strncmp(const char *s1, const char *s2, size_t n);
7.字符串搜索函数
7.1 字符串中找字符
① char* strchr(const char *str, int c);
在str中从左往右查找c第一次出现的位置,返回指针;
② char* strrchr(const char *str, int c);
这个strrchr为从右往左查找;
③返回NULL表示没有找到。
④找到那个字符则返回它以及他后面的所有字符。
7.2 如何寻找第二个字符呢?
char s[] = "hello";
char *p = strchr(s, 'l'); //找到第一个'l'及其后的内容
p = strchr(p+1, 'l'); //找到第二个'l'及其后的内容
printf("%s\n", p);
7.3 将指定字符及其后内容复制到另外一个字符串里
char s[] = "hello_copy";
char *p = strchr(s, 'l'); //查找到第一个'l'
p = strchr(p+1, 'l'); //查找到第二个'l'
char *tmp = (char*)malloc(strlen(p)+1); //分配p那么多的空间,再加一个'\0'的空间
strcpy(tmp, p); //拷贝函数
printf("%s\n", tmp);
free(tmp); //释放空间
7.4 找到指定字符,但是返回其前面部分的内容
char s[] = "hello";
char *p = strchr(s, 'l');
char c = *p; //将指针位置存放,这样后面还可以复原s字符串
*p = '\0'; //将'l'的位置变为'\0',即将前面部分分割为一个新字符串
char *t = (char*)malloc(strlen(s)+1);
strcpy(t, s);
printf("t=%s, s=%s\n",t,s);
free(t);
*p = c;
printf("s=%s\n",s);
7.5 字符串中找字符串
① char* strstr(const char *s1, const char *s2);
这个是寻找字符串的。
② char* strcasestr(const char *s1, const char *s2);
在寻找过程中忽略大小写。