前言
本菜鸡开始了学习C语言的旅途。用这个来记录一下上课所学到的一些东西。仅作为自己的一个学习笔记。里面的内容也只是我对学到的东西的一些理解,可能有很多错误,大佬们勿喷。如果发现我理解的有哪些错误,欢迎评论区指出,希望大佬们不吝赐教。
字符串
1.字符串的定义
字符: ASCII码
字符串:是一串(0个 或者多个)字符
在c语言中,没有字符串这个类型。c语言中,字符串是通过char *(字符型指针)来实现。
c语言的字符串,是由“ ”引起来的一串字符来表示的,并且字符串后面会默认加一个字符\0 (’\0’:ascii码值 为0),这个’\0’我们称之为结束符
我们只需要保存字符串的首地址即可,我们可以通过这个地址一个一个的往下找,直到遇到’\0’停止,这期间的字符都是字符串的内容
“123456” 是一个字符串 “ ”是一个空串,有结束符。
字符串:连续的地址上依次保存每个字符
char *p = "12345"; //p接收了字符串的首地址
编译器在编译时,会把“12345”的首地址赋值给p
*p == '1'
在上述示例中,首地址就是字符1的地址
如何使指针指向字符2?
p+=1;
*p == '2';
这里的”12345“是一个字符串常量,不能被修改;但是可以改变p的指向。
char *p = "12345";
*p='2'; //会出现段错误
p="45678"; //可以修改p的指向
定义:
char *p=”hello“;
或
char p[]=“hello”;
2.字符串的输入/输出
输入:
char s[100] = {0};
scanf("%s", s); //获取终端的一串字符保存进s指向的空间中, 不接收空格和回车
gets(s); //获取终端的一串字符保存进s指向的空间中, 不接收回车,gets有一个巨大的隐患
可能会导致s指向的空间越界,假如s的空间有10个字节,输入十二个字符也是可以的
fgets(s, 5, stdin); //从标准输入(stdin、终端)中,获取4个字节的数据保存进s指向的空间,最后一个字节即第5个填充’\0’
输出:
printf("%s", s); //将s空间中的字符串输出到终端
puts(s); //将s空间中的字符串输出到终端
3. 求字符串长度函数 strlen
strlen ( 返回字符串长度 , 直到遇到结束符为止 )
头文件:
#include <string.h>
定义函数:
size_t strlen (const char *s);
参数分析:
s --> 需要计算的字符串
返回值:
返回字符串的长度 不包括’\0’
示例:
char p1[30]="hello";
char *p2="he\0llo";
printf("%d %d",strlen(p1),strlen(p2)); // 输出5 2
char *p3="he\01234";
char *p4="he\08234";
printf("%d %d",strlen(p3),strlen(p4)); //输出5 2,\012 --> 这个字符的ascii码值为八进制的012,但是\082不是八进制,因为八进制不能大于7,所以\082是'\0' '8' '2';
/* \ooo(一个/两个/三个八进制)格式的为八进制
\xhh(一个/两个十六进制)格式的为十六进制 */
4. 字符串拷贝函数 strcpy / strncpy
strcpy ( 拷贝字符串 )
头文件:
#include <string.h>
定义函数:
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
参数分析:
dest --> 拷贝到该地址中 (需要具有可写的权限)
src --> 需要拷贝的字符串
n --> 需要拷贝地字节数
返回值:
返回参数 dest 的字符串起始地址
strcpy的缺陷:
char *src = "12345";
char dest[2] = {0};
strcpy(dest, src); //dest指向的空间不够大会出现什么后果?
//导致dest[2]...被赋值,非法访问了你不该访问的空间,会导致数组越界--- 巨大的BUG
所以我们要使用strncpy,可以指定需要拷贝的字节数
char * strncpy(char *dest, const char *src, size_t n);
1):src中的字符没有n个,复制src中的所有字符,复制到的数量还没有n个
他会将dest中后面的字节( n - (strlen(src)+1) )填充额外的'\0'
2):src中的字符超过n个(strlen(src)>=n),只会拷贝src中的前n个,没有拷贝结束符
如果是第二种情况,那么dest指向的字符是没有结束符的,所以要添加
int main()
{
char *p = "123456";
char dest[10] = {0};
strncpy(dest, p, sizeof(dest)/sizeof(dest[0])-1);
printf("%s", dest);
return 0;
}
5.字符串比较函数 strcmp
strcmp (比较两个字符串)
头文件:
#include <string.h>
函数原型:
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
参数分析:
s1 --> 需要比较地字符串1
s2 --> 需要比较地字符串2
n --> 需要比较的前N 字符
返回值:
成功 返回0 表示两个字符串相等
失败 返回非0值 表示两个字符串之间的差值
小于零 表示 S1 的第一个差异字符比较小(ASCII值)
大于零 表示 S1 的第一个差异字符比较大(ASCII值)
int ret_val = 0 ; // 定义查值初始化为0
char * str1 = "Hello Even";
char * str2 = "Hello Jacy";
printf("str1:%p\t str2:%p \n" , str1 , str2 );
if (ret_val = strcmp(str1 , str2 )) // 比较完整的两个字符串
{
printf("两个字符串不相等!! 差值为:%d \n" , ret_val);
}
else
{
printf("两个字符串相等!! 差值为:%d \n" , ret_val);
}
if (ret_val = strncmp(str1 , str2 , 5 )) // 比较两个字符串的前5字节
{
printf("两个字符串前5字节不相等!! 差值为:%d \n" , ret_val);
}
else
{
printf("两个字符串前5字节相等!! 差值为:%d \n" , ret_val);
}
6.字符串拼接函数 strcat / strncat
strcat ( 连接两字符串 )
头文件:
#include <string.h>
定义函数:
char *strcat(char *dest, const char *src);
参数分析:
dest --> 需要拼接到该参数后面 , 该参数所指向的内存必须可以被修改
src --> 需要拼接的内容
返回值:
参数 dest 的字符串起始地址
strncat ( 连接两字符串, 安全版本 )
头文件:
#inclue <string.h>
定义函数:
char * strncat(char *dest, const char *src, size_t n);
参数分析:
dest --> 需要拼接到该参数后面 , 该参数所指向的内存必须可以被修改
src --> 需要拼接的内容
n --> 需要拷贝的字符长度
返回值:
参数 dest 的字符串起始地址.
示例:
#include<stdio.h>
#include<string.h>
int main()
{
char p1[100]="hello";
char *p2="2021";
printf("%s ",strcat(p1,p2));//输出hello2021
printf("%s ",strncat(p2,p1));//段错误,因为p2指向的字符串常量,不能修改
char p3[100]="1234";
char *p4="56789";
printf("%s ",strncat(p3,p4,2));//输出123456
return 0;
}