拿捏住C字符串,这个烦人程度不亚于指针的小东西
文章目录
[*]
[*]字符串处理能力能够反映出一个程序员的技术功底
[*]基础扫盲篇
[*]
[*]字符串字面量
[*]
[*]难度指数:2 | 细节指数:3 | 重要指数:3
[*]字符串初始化
[*]
[*]难度指数:2 | 细节指数:3 | 重要指数:4
[*]君不见 size_t 哪里来?
[*]strlen 与 sizeof的不同
[*]
[*]难度指数:2 | 细节指数:4 | 重要指数:3
[*]memset函数
[*]
[*]难度指数:2 | 细节指数:2 | 重要指数:3
[*]基本操作函数篇
[*]
[*]strcmp:比较字符串
[*]strcpy:复制字符串
[*]strcat:拼接字符串
字符串处理能力能够反映出一个程序员的技术功底
曾几何时,看到过这么一句话:字符串处理能力能够反映出一个程序员的技术功底。
这句话我一直在理解,每到一个阶段,都会有不同的理解。
时至今日,我的理解还是比较浅薄的,在算法题中,字符串的重要程度跟指针等绝对是不能同日而语的。
但是在开发中,IO过程就是核心了。
作为IO过程的组成部分,字符串处理就是这个核心中的核心了、
基础扫盲篇
字符串字面量
难度指数:2 | 细节指数:3 | 重要指数:3
字符串字面量一般分配在只读内存中,所以是不可变的。
字符串字面量在哪里使用,是否全局、静态、局部,都无所谓的。
大部分编译器会将字符串字面量看做常量,无法修改字符串,不过有些编译器会不一样,碧如GCC。
#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
要说的话都在注释里了:
#include<stdio.h>
#include<stdlib.h>
int main() {
char test = "asdfghjkl";//记住,这里的位置要留一个给'\0'
//能这样做,说明什么?说明test也是个const?
test = 'g';
//显然不是的
//那么上面那个赋值语句是什么意思呢?
//可以理解为,将字符串字面量取出遍历,一个一个的放进字符数组中
char test;
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 的值,从而有可能让程序导致意想不到的结果,如下面的示例代码所示:
/*判断一*/
if(strlen(x)>= strlen(y))
{
}
/*判断二*/
if(strlen(x)- strlen(y)>= 0)
{
}
从表面上看,上面的两个判断表达式完全相等,但实际情况并非如此。其中,判断表达式一没什么问题,程序也能够完全按照预想的那样工作;但判断表达式二的结果就不一样了,它将永远是真:
原因很简单,因为函数 strlen 的返回结果是 size_t 类型(即无符号整型),而 size_t 类型绝不可能是负的。
同样,就算表达式中同时包含了有符号整数和无符号整数,还是有可能产生意想不到的结果:
/*判断一*/
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:比较字符串
int strcmp(const char* str1,const char* str2);
//str1>str2,返回正数
//str1<str2,返回负数
//否则,返回0
//可以自己动手写一个,简单的很
strcpy:复制字符串
char* strcpy(char* str1,const char* str2);
//其实就是两个指针引用同一个字符串
strcat:拼接字符串
char* strcat(char* s1,const char* s2);
//第一个参数的地址必须足够长,不然越界了,就是会有未知的风险了
//注意,这些函数的参数类型、和返回值类型,别搞错了
后期写完C++会补上关于C++字符串的操作,所以各位如果觉得缺了点啥,可以发在评论区,我们一起看看
文档来源:51CTO技术博客https://blog.51cto.com/u_15197573/3032596
页:
[1]