学习记录:第三周day02笔记
一、字符串
字符:人能看懂的符号或图案,在内存中以整数形式存储,根据ASCII码表中的对应关系显示相应的符号或图案
'\0' 0 空字符
'0' 48
'A' 65
'a' 97
串:是一种数据结构,存储类型相同的若干个数据;对于串型结构的处理是批量性的,会从头开始直到遇到结束标志
void show_arr(int arr[])
{
for(i=0;~0!=arr[i];i++)
{
printf("%d ",arr[i]);
}
}
int main()
{
int arr[]={1,4,5,6,7,32,~0};
}
字符串:有字符组成的串型结构,结束标志是'\0'
二、字符串的存在形式
字符数组:
char str[5]={'a','b','c','d','\0'}
char str[5]={'a','b','c','d'}//剩下一位自动补零
由char组成的数组,注意要为'\0'预留位置,初始化麻烦
使用的栈数据,数据可以修改
字符串字面值:
"由双引号包含的若干个字符"
末尾会隐藏一个'\0',定义也方便
字符串字面值以地址形式存在,是常量,数据存储在代码段中,不能修改,否则会段错误
注意:相同内容的多份字符串字面值,在代码段中只会存在一份
注意:sizeof("xxxx") 字符数+1
常用方式:
字符数组[]="字符串字面值";
会自动为'\0'预留位置
注意:上述赋值完成后,该字符串在内存中有两份,一份在代码段,另一份在栈内存(可修改)
三、字符串的输入和输出
输入:
scanf %s 地址
缺点:不能输入空格
char str[100]={};
scanf("%s",str);
char *gets(char *s);
功能:输入字符串到s中,能够输入空格
返回值:s 链式调用
缺点:有警告,输入的长度不受限制,有危险
printf("%s",gets(str));
char *fgets(char *s, int size, FILE *stream);
功能:输入长度最多为size-1个字符串,会自动为'\0'预留位置,超出部分不接收;能够输入空格,但不足时,最后的换行符'\n'也会一起接收
返回值:s 链式调用
printf("%s",fgets(str,10,stdin));
输出:
printf %s 地址
int puts(const char *s);
功能:输出一个字符串,并且会自动在末尾加上一个'\n';(printf不会加)
返回值:成功输出的字符个数
练习1:实现一个函数,判断一个字符串是否是回文串
四、输出缓冲区
缓存区的机制可以提高数据的读写速度,还可以让低速的设备与高速的CPU之间系统工作
程序要显示的数据不会立即显示到屏幕上,而是先存储到输出缓冲区中,当满足一定条件时才会从输出缓冲区显示到屏幕上
一定条件:
1、遇到'\n'
2、遇到输入语句
3、当缓冲区满的时(4KB)
4、程序正常结束时
5、fflush(stdout); 刷新输出缓冲区
五、输入缓冲区
程序中输入的数据并不会立即从键盘接收到变量中,而是当按下回车后先存储到输入缓冲区中,然后再从缓冲区中读取到变量内存中
情况1:scanf中需要输入的是整型、浮点型时,而缓冲区中的数据是字符型或符号时(即类型不匹配时),此时读取会失败,并且该数据会继续残留在输入缓冲区中,会继续影响剩下的输入
解决:根据scanf的返回值判断输入是否有问题,如果读取失败,则先清理缓冲区后重新输入,直到读取成功为止
情况2:fgets可以指定读取size-1个字符,但是如果输入超过size-1那么字符会残留在输入缓冲区中,继续影响接下来的输入
scanf("%*[ ^\n ]"); //从缓冲区中读取任意类型数据并丢弃,直到'\n'停止
scanf("%*c"); //从缓冲区中读取任意字符类型数据并丢弃
如果没超的话,'\n'就被读入字符数组中而缓冲区中没有'\n',会等着你输入'\n';所以需要先判断'\n'在不在字符数组中
方法1:
int len=0;
while(str[len]) len++;
if('\n'!=str[len-1])
{
scanf("%*[^\n]");
scanf("%*c");
}
方法2:
stdin->_IO_read_ptr=stdin-> _IO_read_end;(相当于直接让输入缓冲区满了,其中未被读入的数据直接被清除)
情况3:scanf当先输入整型或浮点型,再输入字符型时,输入完整型或浮点型后按下回车或空格,会残留在输入缓冲区,刚好被后面的字符型接收
字符:
scanf(" %c");
字符串:
//scanf("%*c",&num);
scanf("%d ",&num);
gets(str);
六、字符串相关函数
#include<string.h>
size_t strlen(const char *s);
功能:计算字符串长度,不包括'\n'(其他有效字符都算)
char *strcpy(char *dest, const char *src);
功能:把src拷贝给dest,相当于=
返回值:dest首地址,链式调用
注意:C语言中无法利用赋值语句将字符串字面值赋给字符串数组,只能借助strcpy函数
char *strcat(char *dest, const char *src);
功能:把src追加到dest的末尾,相当于+=
int strcmp(const char *s1, const char *s2);
功能:比较两个字符串,根据字典序,谁出现早谁小,一旦比较出结果就立即返回
返回值:
s1>s2 正数
s1==s2 0
s1<s2 负数
int atoi(const char *nptr);
功能:把字符串转换成int类型
double atof(const char *nptr);
功能:把字符串转换成double类型
char *strstr(const char *haystack, const char *needle);
功能:在haystack中查找是否存在子串needle
返回值:needle在haystack中第一次出现的位置,如果找不到返回NULL
重量级:
int sprintf(char *str, const char *format, ...);
功能:把各种类型的数据转换成字符串并输入到str中
int sscanf(const char *str, const char *format, ...);
功能:从字符串中解析出各种类型的数据,并存储到对应的变量中
void *memcpy(void *dest, const void *src, size_t n);
功能:把src内存的数据拷贝n个字节到dest中(存在重叠时,行为不确定)
void *memmove(void *dest, const void *src, size_t n);
功能:同上,但存在重叠时,功能仍然正常
int memcmp(const void *s1, const void *s2, size_t n);
功能:按字节比较s1前n个字节
练习:自己实现strlen\strcpy\strcat\strcmp四个函数
size_t str_len(const char *str)
{
assert(NULL!=str);
const char *temp=str;
while(*temp) temp++;
return temp-str;
/*
size_t len=0;
while(s[len]) len++;
return len;
*/
}
char *str_cpy(char *dest,const char *src)
{
if(NULL==dest||NULL==src) return NULL;
char *temp=dest;
while(*temp++=*src++);
return dest;
}
char *str_cat(char *dest,const char *src)
{
if(NULL==dest||NULL==src) return NULL;
char *temp=dest;
while(*temp) p1++;
while(*temp++=*src++);
return dest;
}
int str_cmp(const char *s1,const char *s2)
{
while(*s1&&*s1==*s2) s1++,s2++;
return *s1-*s2;
/*
const char *p1=s1,*p2=s2;
for(;'\0'!=*p1&&'\0'!=*p2;p1++,p2++)
{
if(*p1==*p2) continue;
else return *p1>*p2;
}
if(*p1==*p2) return 0;
else return *p1>*p2;
*/
}
作业1:定义一个函数,把一个由数字字符组成的字符串转换成整数
作业2:定义一个函数,把一个字符串逆序;