一、字符串
(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[]="";
#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]
- char *a[];
4.2 程序参数
- int main(int argc,char const *argv[])
- argv[0]是命令本身
#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 测试代码
#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;
}
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);
- 比较两个字符串,返回:
3.2 测试代码
#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;
}
#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);
strcpy(dst,src);
#include<stdio.h>
#include<string.h>
int main(int argc,char const *argv[])
{
char s1[]="abc";
char s2[]="abb";
strcpy(s1,s2);
return 0;
}
#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);