字符串
1、字符:
在计算机中字符是以整数形式存储的,当需要显示时根据ASCII表中的对应关
系显示出相应的符号或图案
'\0' 0
'0' 48
'A' 65
'a' 97
2、串:
是一种数据结构,是由一组连续的相同类型的若干个数据组成,末尾有一个结
束 标志对这种数据结构进行处理都是批量处理,从开头位置到结束标志为止
3、字符串:
由字符组成的串型结构,它的结束标志是'\0'
一、字符串的输入
1、
scanf %c
scanf %s 地址
注意:不能接收空格
2、
char* gets(char *s); //get(str)
功能:输入字符串到s中,可以接收空格
返回值:链式调用(把一个函数的返回值,作为另一个函数的输入)
3、
char* fget(char *s,int size,stdin);
功能:可以设置输入的字符串的长度为size-1,超出长度时会在末尾给'\0'
预留位置,超出部分不接收
注意:如果长度不足size-1,则会接收最后输入的'\n'
二、字符串的输出:
1、printf %s 地址
2、int puts(const char *s);
功能:输出一个字符串,会在末尾自动打印一个'\n',自动添加换行
返回值:成功输出的字符个数
三、输出缓冲区
程序要输出的数据并没有立即写入到“文件”,而是先存储到输出缓冲区。
当满足一定条件时2才会写入到文件中
1、遇到换行符\n
2、遇到输入语句
3、程序结束
4、缓冲区满4k
5、手动刷新 fflush(stdout)
缓冲区机制可以提高数据的读写速度,并且可以让低速的输入输出设备与
高速的CPU能够协调工作
四、输入缓冲区
在终端输入的数据先由终端保管,当按下回车键后从缓冲区中读取数据到scanf中的
变量
1、当想要输入的是整型、浮点型数据,而缓冲区中的数据是字母或字符型时,此时
从缓冲区中读取数据失败,此时并不会从缓冲区中拿走字母或字符,导致接下来的
数据读取都有问题
解决方法:根据scanf的返回值,判断变量是否从缓冲区中读取成功,如果失败则
先清空缓冲区再重新输入
(1) stdin->_IO_read_ptr = stdin->_IO_read_end;
( 只能在linux系统上使用,把缓冲区的当前位置指针移动到缓冲区末尾,相当
于清理缓冲区)
(2)
scanf("%*[^\n]");//读取一个数据并丢弃,如果该数据不是\n则一直丢弃,直
到读到\n为止
scanf("%*c");//从缓冲区读取一个字符并丢弃
2、使用fget读取字符串时,如果输入的字符超过了size-1个,超出的部分就会
残留在输入缓冲区中,会影响接下来的数据读取
解决方法:判断fget读取到的字符串最后一个字符是否是\n,如果不是,则说明
缓冲区中有残留数据,才需要清理
scanf("%*[^\n]");
scanf("%*c");
3、当先输入整型、浮点型数据,紧接着输入字符、字符串时,前一次的输入可能
残留一个\n,会影响接下来的字符、字符串的输入
解决方法:
输入字符时:
scanf(" %c");//空格
输入字符串时:
scanf("%*c");//丢掉一个字符
gets(str);
五、字符串的存在形式:
1、字符数组:
char str[10] = {'a','b','c',...};
由char类型组成的数组,一定要为'\0'预留位置
赋值麻烦
使用的是栈内存,数据是可以修改的
2、字符串字面值:
"由双引号包含的若干个字符""hello world"
在末尾隐藏了一个'\0'
字符串字面值就是以地址形式存在的,存储在代码段,
不能修改,如果修改会产生段错误
char *str = "hello world";
sizeof(str) 结果 = 4/8
sizeof("hello world") 结果 = 字符个数+1(末尾有\n)
strlen("hello world") 结果 = 字符个数
char str[5] = "hello";
sizeof(str); 结果 = 数组的总字节数5
char str[] = "hello";
sizeof(str); 结果 = 字符个数+1(末尾有\n)
两个一模一样的字符串字面值在代码段中只会存在一份
3、常用方式:
字符数组[] = "字符串字面值";
会自动给'\0'预留位置
赋值完成后字符串会存有两份,一份存储在代码段,另一份存储在栈内存
(可以修改)
六、字符串的常用操作:
计算字符串长度
1、size_t strlen(const char *s);
功能:计算字符串长度,结果不包括’\0’ 对比sizeof
字符串拷贝
2、char *strcpy(char *dest, const char *src);
功能:把src拷贝到dest,相当于给dest赋值 dest = src
返回值:dest的首地址,链式调用
char *strncpy(char *dest, const char *src, size_t n);
功能:只拷贝前n个字符
字符串追加
3、char *strcat(char *dest, const char *src);
功能:把src追加到dest的末尾,相当于 +=
返回值:dest的首地址,链式调用
char *strncat(char *dest, const char *src, size_t n);
功能:只追加前n个字符
字符串比较
4、int strcmp(const char *s1, const char *s2);
功能:比较s1与s2两个字符串的大小,按照字典序,谁在前谁小,比较出结果立即返回
返回值:
s1 > s2 正数
s1 = s2 0
s1 < s2 负数
int strncmp(const char *s1, const char *s2, size_t n);
功能:只比较前n个字符
其他字符串处理常用函数
字符串转其他类型
#include <stdlib.h>
int atoi(const char *nptr);
功能:字符串转int类型
long atol(const char *nptr);
功能:字符串转long类型
long long atoll(const char *nptr);
功能:字符串转long long类型
double atof(const char *nptr);
功能:字符串转double类型
字符查找
#include <string.h>
char *strstr(const char *haystack, const char *needle);
功能:查找haystack中是否存在needle
返回值:如果存在,则返回needle第一次在haystack中出现的位置,
找不到返回NULL
char *strchr(const char *s, int c);
功能:查找字符串s中是否存在字符c
返回值:返回第一次出现的位置,不存在则返回NULL
其他常用的重要函数
int sprintf(char *str, const char *format, ...);
功能:把各种类型的数据输入到str中
返回值:字符串str的长度
int sscanf(const char *str, const char *format, ...);
功能:从str中解析出各种类型数据
返回值:成功读取到的变量个数
void *memcpy(void *dest, const void *src, size_t n);
功能:从src拷贝n个字节到dest中
int memcmp(const void *s1, const void *s2, size_t n);
功能:比较两个内存块,按字节比较
返回值:
s1 > s2 正数
s1 = s2 0
s1 < s2 负数
七、实现strlen、strcpy、strcat、strcmp是个常用的字符串处理函数
实现:strlen函数
size_t str_len(const char *str)
{
int len = 0;
while(str[len]) len++;
return len;
}
实现:strcpy函数
char *str_cpy(char *dest, const char *src)
{
char *tmp = dest;
while(*tmp++ = *src++);
return dest;
}
实现:strcat函数
char *str_cat(char *dest, const char *src)
{
char* tmp = dest;
while(*tmp) tmp++;
while(*tmp++ = *src++);
return dest;
}
实现:strcmp函数
int str_cmp(const char *s1, const char *s2)
{
while(*s1 && *s1 == *s2) s1++,s2++;
return *s1 - *s2;
}