前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >拿捏住C字符串,这个烦人程度不亚于指针的小东西

拿捏住C字符串,这个烦人程度不亚于指针的小东西

作者头像
看、未来
发布2021-09-18 11:21:44
2920
发布2021-09-18 11:21:44
举报
文章被收录于专栏:CSDN搜“看,未来”

文章目录

字符串处理能力能够反映出一个程序员的技术功底

曾几何时,看到过这么一句话:字符串处理能力能够反映出一个程序员的技术功底。 这句话我一直在理解,每到一个阶段,都会有不同的理解。

时至今日,我的理解还是比较浅薄的,在算法题中,字符串的重要程度跟指针等绝对是不能同日而语的。 但是在开发中,IO过程就是核心了。 作为IO过程的组成部分,字符串处理就是这个核心中的核心了、


基础扫盲篇

字符串字面量

难度指数:2 | 细节指数:3 | 重要指数:3

字符串字面量一般分配在只读内存中,所以是不可变的。 字符串字面量在哪里使用,是否全局、静态、局部,都无所谓的。

大部分编译器会将字符串字面量看做常量,无法修改字符串,不过有些编译器会不一样,碧如GCC。

代码语言:javascript
复制
#include<stdio.h>
#include<stdlib.h>

int main() {
	//char* test = "asdfg";	//直接报错:const char* 类型的值不能为char*类型的实体赋值 
	/*char* test = (char*)malloc(10);
	test = "qwr";*/	//依旧不行

	const char* test = "asdfg";	//将字符串初始化为常量可以解决一部分问题
	//还有一个不错的方法,叫做粘贴上去,后面会讲
	//也可以从键盘输入
}

字符串初始化

难度指数:2 | 细节指数:3 | 重要指数:4

要说的话都在注释里了:

代码语言:javascript
复制
#include<stdio.h>
#include<stdlib.h>

int main() {
	char test[10] = "asdfghjkl";	//记住,这里的位置要留一个给'\0'
	//能这样做,说明什么?说明test也是个const?

	test[3] = 'g';
	//显然不是的

	//那么上面那个赋值语句是什么意思呢?
	//可以理解为,将字符串字面量取出遍历,一个一个的放进字符数组中

	char test[10];
	test = "asdfghjkl";	//报错,表达式必须是可修改的左值
	//不能把字符串字面量的地址赋给数组名字

}

君不见 size_t 哪里来?

size_t 类型定义在cstddef头文件中,该文件是C标准库的头文件stddef.h的C++版。它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。

在C++中,设计size_t 就是为了适应多个平台的。size_t的引入增强了程序在不同平台上的可移植性。size_t是针对系统定制的一种数据类型,一般是整型,因为C/C++标准只定义最低的位数,而不是必需的固定位数。而且在内存里,对数的高位对齐存储还是低位对齐存储各系统都不一样。为了提高代码的可移植性,就有必要定义这样的数据类型。一般这种类型都会定义到它具体占几位内存等。当然,有些是编译器或系统已经给定义好的。经测试发现,在32位系统中size_t是4字节的,而在64位系统中,size_t是8字节的,这样利用该类型可以增强程序的可移植性。


strlen 与 sizeof的不同

难度指数:2 | 细节指数:4 | 重要指数:3

strlen 是一个函数,所以需要进行一次函数调用,它用来计算指定字符串 str 的长度,但不包括结束字符(即 null 字符)

关键字 sizeof 是一个单目运算符,而不是一个函数。与函数 strlen 不同,它的参数可以是数组、指针、类型、对象、函数等

这里需要特别注意的是,函数 strlen 返回的是一个类型为 size_t 的值,从而有可能让程序导致意想不到的结果,如下面的示例代码所示:

代码语言:javascript
复制
/*判断一*/
if(strlen(x)>= strlen(y))
{
}
/*判断二*/
if(strlen(x)- strlen(y)>= 0)
{
}

从表面上看,上面的两个判断表达式完全相等,但实际情况并非如此。其中,判断表达式一没什么问题,程序也能够完全按照预想的那样工作;但判断表达式二的结果就不一样了,它将永远是真:

原因很简单,因为函数 strlen 的返回结果是 size_t 类型(即无符号整型),而 size_t 类型绝不可能是负的。

同样,就算表达式中同时包含了有符号整数和无符号整数,还是有可能产生意想不到的结果:

代码语言:javascript
复制
/*判断一*/
if(strlen(x)>= 5)
{
}
/*判断二*/
if(strlen(x)- 5>=0)
{
}

原因同上、

sizeof 在编译时计算缓冲区的长度。也正是由于在编译时计算,因此 sizeof 不能用来返回动态分配的内存空间的大小。


memset函数

难度指数:2 | 细节指数:2 | 重要指数:3

本来这个不应该在这里讲的,但是前面讲漏了,所以这里补一下:

memset 函数的第三个参数 n 的值一般用 sizeof() 获取,这样比较专业。注意,如果是对指针变量所指向的内存单元进行清零初始化,那么一定要先对这个指针变量进行初始化,即一定要先让它指向某个有效的地址。而且用memset给指针变量如p所指向的内存单元进行初始化时,n 千万别写成 sizeof§,这是新手经常会犯的错误。因为 p 是指针变量,不管 p 指向什么类型的变量,sizeof§ 的值都是 4。


基本操作函数篇

strcmp:比较字符串

代码语言:javascript
复制
int strcmp(const char* str1,const char* str2);

//str1>str2,返回正数
//str1<str2,返回负数
//否则,返回0
//可以自己动手写一个,简单的很

strcpy:复制字符串

代码语言:javascript
复制
char* strcpy(char* str1,const char* str2);
//其实就是两个指针引用同一个字符串

strcat:拼接字符串

代码语言:javascript
复制
char* strcat(char* s1,const char* s2);

//第一个参数的地址必须足够长,不然越界了,就是会有未知的风险了
//注意,这些函数的参数类型、和返回值类型,别搞错了

后期写完C++会补上关于C++字符串的操作,所以各位如果觉得缺了点啥,可以发在评论区,我们一起看看

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/06/08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 字符串处理能力能够反映出一个程序员的技术功底
  • 基础扫盲篇
    • 字符串字面量
      • 难度指数:2 | 细节指数:3 | 重要指数:3
    • 字符串初始化
      • 难度指数:2 | 细节指数:3 | 重要指数:4
    • 君不见 size_t 哪里来?
      • strlen 与 sizeof的不同
        • 难度指数:2 | 细节指数:4 | 重要指数:3
      • memset函数
        • 难度指数:2 | 细节指数:2 | 重要指数:3
    • 基本操作函数篇
      • strcmp:比较字符串
        • strcpy:复制字符串
          • strcat:拼接字符串
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档