C语言字符串+字符串函数

字符串

字符串

字符数组
char word[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’,‘!’};
字符串

char word[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’,‘!’,’ \0’};
  • 以0(整数0)结尾的⼀串字符
    • 0或’\0’是⼀样的,但是和’0’不同
  • 0标志字符串的结束,但它不是字符串的⼀部分
    • 计算字符串⻓度的时候不包含这个0
  • 字符串以数组的形式存在,以数组或指针的形式访问
    • 更多的是以指针的形式
  • string.h ⾥有很多处理字符串的函数

字符串变量

char *str = “Hello”; 
char word[] = “Hello”; 
char line[10] = “Hello”;
  • “Hello”

  • ″Hello″ 会被编译器变成⼀个字符数组放在某处,这个数组的⻓度是6,结尾还有表⽰结束的0

  • 两个相邻的字符串常量会被⾃动连接起来

  • ⾏末的\表⽰下⼀⾏还是这个字符串常量

  • C语⾔的字符串是以字符数组的形态存在的

    • 不能⽤运算符对字符串做运算
    • 通过数组的⽅式可以遍历字符串
  • 唯⼀特殊的地⽅是字符串字⾯量可以⽤来初始化字符数组

  • 以及标准库提供了⼀系列字符串函数

字符串常量
char* s = "Hello, world!";
  • s 是⼀个指针,初始化为指向⼀个字符串常量
    • 由于这个常量所在的地⽅,所以实际上s是 const char* s ,但是由于历史的原因,编译器接受不带 const的写法
    • 但是试图对s所指的字符串做写⼊会导致严重的后果
  • 如果需要修改字符串,应该⽤数组: char s[] = “Hello, world!”;
    什么时候用指针,什么时候用数组
    char * str = “Hello”;
    char word[] = “Hello”;
  • 数组:这个字符串在这⾥
    • 作为本地变量空间⾃动被回收
  • 指针:这个字符串不知道在哪⾥
    • 处理参数
    • 动态分配空间
      如果要构造⼀个字符串—>数组
      如果要处理⼀个字符串—>指针

      char*是字符串
      字符串可以表达为char的形式
      char
      不⼀定是字符串
      本意是指向字符的指针,可能指向的是字符的数组(就像int* ⼀样)
      只有它所指的字符数组有结尾的0,才能说它所指的是字符串
字符串的输入和输出

字符串赋值?

  • char * t = “title”;
  • char * s;
  • s = t;
  • 并没有产⽣新的字符串,只是让指针s指向了t所指的字符串,对s的任何操作就是对t做的
    字符串输⼊输出
char string[8]; 
scanf(“%s”, string); 
printf(“%s”, string);

scanf读⼊⼀个单词(到空格、tab或回⻋为⽌)
scanf是不安全的,因为不知道要读⼊的内容的⻓度
安全的输⼊
char string[8];
scanf(“%7s”, string);
在%和s之间的数字表⽰最多允许读⼊的字符的数量,这个数字应该⽐数组的⼤⼩⼩⼀
下⼀次scanf从哪⾥开始?
下一次scanf从上一个第八个开始
常⻅错误

  • char * string;
  • scanf(“%s”, string);
  • 以为char* 是字符串类型,定义了⼀个字符串类型的变量string就可以直接使⽤了
    • 由于没有对string初始化为0,所以不⼀定每次运⾏都出错
      空字符串
      char buffer[100]=””;
这是⼀个空的字符串,buffer[0] == ‘\0’

char buffer[] = “”;
这个数组的⻓度只有1!

字符串数组
• char **a 
• a是⼀个指针,指向另⼀个指针,那个指针指向⼀个字符(串) 
• char a[][] 
• a是⼀个⼆维数组,第⼆个维度的⼤⼩不知道,不能编译 
• char a[][10] 
• a是⼀个⼆维数组,a[x]是⼀个char[10] 
• char *a[] 
• a是⼀个⼀维数组,a[x]是⼀个char*

程序参数

  • int main(int argc, char const * argv[])
  • argv[0]是命令本⾝
  • 当使⽤Unix的符号链接时,反映符号链接的名字

字符串函数

单字符输入输出,用putchar和getchar

putchar

  • int putchar(int c);
  • 向标准输出写⼀个字符
  • 返回写了⼏个字符,EOF(-1)表⽰写失败

getchar

  • int getchar(void);
  • 从标准输⼊读⼊⼀个字符
  • 返回类型是int是为了返回EOF(-1)
    • Windows—>Ctrl-Z
    • Unix—>Ctrl-D
标准库中的字符串函数string.h

strlen
size_t strlen(const char * s);
返回s的字符串⻓度(不包括结尾的0)

char line[]="Hello"
printf("strlen=%lu\n",strlen(line));
printf("sizeof=%lu\n",sizeof(line));
输出结果为:
strlen=5
sizeof=6

strcmp —compare

  • int strcmp(const char * s1, const char * s2);
  • ⽐较两个字符串,返回:
  • 0:s1== s2
  • 0:s1> s2

  • <0:s1< s2
int mycmp(const char *s1,const char *s2)
{
	int idx = 0;
	while (s1[idx] == s2[idx] && s1[idx] != 0)
	{
		idx++;
	}return s1[idx] - s2[idx];
}
等同于
int mycmp(const char *s1,const char *s2)
{
	while (*s1==*s2&&*s1!='\0')
	{
		s1++; s2++;
	}
	return *s1 - *s2;
}

strcpy —copy

char * strcpy(char *restrict dst, const char *restrict src);
  • 把src的字符串拷⻉到dst
    • restrict表明src和dst不重叠(C99)
  • 返回dst
    • 为了能链起代码来
      复制字符串
char *dst = (char*)malloc(strlen(src)+1);   //+1包括结尾最后的\0
strcpy(dst, src);

用函数等价

数组版本
char* mycpy(char*dst,const char* src)
{
int idx = 0;
while(src[idx]){
dst[idx]=src[idx];
idx++;
}
dst[idx]='\0';
return dst;
}
指针版本
char* mycpy(char*dst,const char* src)
{
char *ret=dst;
while( *dst++ = *src++ )
   ;
   *dst='\0';
   return ret;
}

strcat

char * strcat(char *restrict s1, const char *restrict s2);
  • 把s2拷⻉到s1的后⾯,接成⼀个⻓的字符串
  • 返回s1
  • s1必须具有⾜够的空间
char *mycat(char cat1[],const char cat2[]) //声明并实现我的猫字符指针函数。
{     int i = 0;     
       int j = strlen(cat1);         //猫1字符数组的最后一位下标j     while(i != strlen(cat2)){           //当猫2的下标为最后一位\0时跳出循环         cat1[j] = cat2[i];            //猫1最后一位为猫二的第一位字符       
         i++;       
         j++;     
    }     
    cat1[j] = '\0';           //猫1字符数组最后一位为0    
     return cat1;    //让我的猫字符指针指向猫1字符数组
}       

安全问题
strcpy和strcat都可能出现安全问题:如果那个dst或者要连接的地方没有足够的空间,不知道是否越界
安全版本

char * strncpy(char *restrict dst, const char *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);

在名字中间和参数表中多了一个n
n的意思是说你能拷过去多少个字符;多了的部分直接掐掉,不会越界。
对于cmp来说是比较前n个的大小

strchr
在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置。

#include <stdio.h>
#include <string.h>
int main ()
{
   const char str[] = "http://www.nowcoder.com";
   const char ch = '.';
   char *ret;
   ret = strchr(str, ch);
   printf("|%c| 之后的字符串是 - |%s|\n", ch, ret);
   return(0);
}
运行结果为
|.| 之后的字符串是 - |.nowcoder.com|

strrchr
在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。

#include <stdio.h>
#include <string.h>

int main ()
{
   int len;
   const char str[] = "https://www.nowcoder.com";
   const char ch = '.';
   char *ret;
   ret = strrchr(str, ch);
   printf("|%c| 之后的字符串是 - |%s|\n", ch, ret);
   return(0);
}
运行结果为
|.| 之后的字符串是 - |.com|

strstr()
在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 ‘\0’。
下面是 strstr() 函数的声明。
char *strstr(const char *haystack, const char *needle)

#include <stdio.h>

#include <string.h>

int main()

{
   const char haystack[20] = "NOWCODERABCD";    const char needle[10] = “CODER”;
   char *ret;
   ret = strstr(haystack, needle);
   printf("子字符串是: %s\n", ret);   return(0); }`
输出结果为
子字符串是: CODERABCD

memcpy

和strcpy类似,只不过它是拷贝字节

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tian Meng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值