char, char*, char[], int的区别、互转及字符串操作 - C语言笔记

char, char*, char[], int的区别、互转及字符串操作 - C语言笔记

类型转换一直是 C 语言编程中的难点和痛点,本文将介绍 C 语言中 char, char *, char [], int 之间的区别、互转以及一些常见的字符串操作。

一、char 与 int 互转: 直接赋值char和int可以直接互转,但是需要注意的是,char的范围是 0~255 或 -128~127,而int的范围是-2147483648~2147483647。

char c1 = 'a';

int i = c1;

char c2 = i;

二、char* 与 int 互转2.1 int 转 char*: sprintf()方法一:itoa(int value, char* str, int base)函数可以将整数value以base进制的形式转换为字符串,并存储到str所指的字符数组中。

方法二:char* itoa(int value, NULL, int base)函数可以将整数value以base进制的形式转换为字符串,并返回一个指向该字符串的指针。

方法三(推荐):sprintf(char* str, "%d", value)格式化字符串函数可以将整数value以十进制的形式转换为字符串,并存储到str所指的字符数组中。

int value = 123;

char *str;

sprintf(str, "%d", value);

printf("%s\n", str); // 123

提示

理论上itoa()位于头文件中。 但itoa()可能不被编译器支持。

2.2 char* 转 int: atoi(), strtol()方法一:int atoi(char* str)函数可将字符串str转换为整数(仅支持的最大整数值为INT_MAX)。

方法二(推荐):int strtol(char* str, char** endptr, int base)函数可将字符串str逐位转换为整数直到遇到非数字字符或字符串结束,返回转换后的整数值(仅支持的最大整数值为INT_MAX),并将遇到的非数字字符的地址存储到endptr所指的指针中。 可通过判断*endptr是否为NULL(即endptr是否指向空指针)来判断整个字符串是否都转换成功。

例如:

char str[] = "123abc";

char *endptr;

int num = strtol(str, &endptr, 10);

printf("%d\n", num); // 123

printf("%p\n", endptr); // 0xff114514

printf("%c\n", *endptr); // a

提示

atoi(), strtol()都位于头文件中。

三、char* 字符串操作3.1 获取字符串长度 strlen()strlen(const char* str)函数可以获取字符串str的长度。

原理就是遍历字符串直到遇到'\0'结束,并返回遍历的次数。

因此并不一定等于实际分配的内存大小。

char str[] = "hello";

int len = strlen(str);

printf("%d\n", len); // 5

3.2 获取字符串已分配空间 sizeof()sizeof(char str*)或sizeof(char str[]):获取str指向的字符串所占的字节数。

注意

由于普通字符串char为 1 个字节,故sizeof(char)可直接与字符串长度相对应而无需转换。 但由于字符串末尾的'\0'字符也占用 1 个字节,故在未指定字符串长度时,sizeof()获取的结果比实际字符串长度多 1。

char str[64] = "hello";

int size = sizeof(str);

printf("%d\n", size); // 64

3.3 字符串拼接 strcat()/strncat()strcat(char* dest, const char* src)将src指向的字符串拼接到dest指向的字符串的尾部。

strncat(char* dest, const char* src, size_t n)将src指向的字符串的前n个字符拼接到dest指向的字符串的尾部。

char str1[64] = "hello, ";

char str2 = "world";

strcat(str1, str2);

printf("%s\n", str1); // hello, world

char str1[64] = "hello, ";

char str2 = "world";

strncat(str1, str2, 2);

printf("%s\n", str1); // hello, wo

注意 (仅 C 语言)

如果dest是直接赋值的指针类型(char *str = "...")而不是数组类型(char str[]),执行strcat()可能会导致访问未分配的空间而出现段错误。 (Segmentation fault (core dumped))

然而,如果是数组类型(char str[]),虽然不会报错,但是可能导致内存溢出从而修改其它变量的值!

例如:

char *str1 = "hello, ";

char str2[] = "world";

strcat(str1, str2); // 错误,未分配足够的空间容纳str2字符串

改为数组类型后:

char str1[] = "hello, "; // 栈高位地址

char str2[] = "world"; // 栈低位地址

strcat(str1, str2); // 正确,不会报错

printf("%s\n", str1); //hello, world

printf("%s\n", str2); //world

char str2[] = "world"; // 栈高位地址

char str1[] = "hello, "; // 栈低位地址

strcat(str1, str2); // 正确,不会报错,但覆盖了高位的数据

printf("%s\n", str1); //hello, world

printf("%s\n", str2); //olld

strcat前后的栈内存布局(strcat行为比较迷惑)改为指向数组类型的指针是同样的结果:

char str[] = "hello, ";

char *str1 = str;

char str2[] = "world";

strcat(str1, str2); // 正确,不会报错

3.4 字符串复制 strcpy()/strncpy()strcpy(char* dest, const char* src)函数将src指向的字符串复制(覆盖)到dest指向的字符串中。

strncpy(char* dest, const char* src, size_t n)函数将src指向的字符串的前n个字符复制(覆盖)到dest指向的字符串中。

char str1[64] = "hello,";

char str2[] = "world";

strcpy(str1, str2);

printf("%s\n", str1); //world

char str1[64] = "hello,";

char str2[] = "world";

strncpy(str1, str2, 5);

printf("%s\n", str1); //world,

strncpy(str1, str2, 6); // 末尾的'\0'字符也会被复制

printf("%s\n", str1); //world

注意

与strcat()类似,如果dest是直接赋值的指针类型(char *str = "...")而不是数组类型(char str[]),执行strcpy()可能会导致访问未分配的空间而出现段错误。 (Segmentation fault (core dumped))

3.5 字符串比较 strcmp()int strcmp(const char* str1, const char* str2)函数可以比较str1和str2指向的字符串是否相等,并返回一个整数值。0 表示相等,负数表示str1小于str2,正数表示str1大于str2。

char str1[] = "hello, ";

char str2[] = "world";

int cmp = strcmp(str1, str2);

if (cmp == 0) {

printf("str1 == str2\n");

} else if (cmp < 0) {

printf("str1 < str2\n");

} else {

printf("str1 > str2\n");

}

3.6 字符串查找 strchr()char* strchr(const char* str, int c)函数可以查找字符串str中第一个出现字符c的位置,并返回一个指向该位置的指针。

char str[] = "hello, world";

char* p = strchr(str, 'l');

if (p) {

printf("%s\n", p); // llo, world

} else {

printf("not found\n");

}

3.7 字符串替换 strstr()char* strstr(const char* str1, const char* str2)函数可以查找字符串str1中第一次出现字符串str2的位置,并返回一个指向该位置的指针。

char str1[] = "hello, world";

char str2[] = "wo";

char* p = strstr(str1, str2);

if (p) {

printf("%s\n", p); // world

} else {

printf("not found\n");

}

3.8 字符串分割 strtok()char* strtok(char* str, const char* delimiters)函数可以将字符串str按照分隔符delimiters进行分割,并返回一个指向分割后的第一个字符串的指针。

char str[] = "hello, world, goodbye";

char* p = strtok(str, ", ");

while (p) {

printf("%s\n", p);

p = strtok(NULL, ", ");

}

// 输出:

// hello

// world

// goodbye

char str[] = "hello, world, goodbye";

for (char *p = strtok(str, ", "); p; p = strtok(NULL, ", "))

printf("%s\n", p);

// 输出:

// hello

// world

// goodbye

3.9 字符串格式化 sprintf()与printf()函数类似,sprintf()函数可以将格式化字符串format中的占位符替换为实际值,并将结果存储到str指向的字符串中。

具体详见 printf 与 scanf.md

提示

strcat(), strcpy(), strlen(), strcmp(), strchr(), strstr(), strtok(), sprintf()都位于头文件中。

C++注意

以下为 C++ 内容,C 语言没有string类型。 且C++中无法通过char *str = "..."的方式创建字符串指针 (ISO C++ forbids converting a string constant to ‘char\*’)

四、string 与 char[] 互转4.1 char[] 转 string: 直接赋值char str[] = "hello, world";

string s = str;

char str[] = "hello, world";

char *p = str;

string s = p;

4.2 string 转 char[]: string.c_str()const char* c_str(const string& str)函数可以将string类型转换为const char*类型。

例如:

string str = "hello, world";

const char *p = str.c_str(); //必须加上const,否则编译器会报错,const char* 无法转换为 char*

五、int 与 string 互转5.1 int/float/double 转 string: to_string()string to_string(int value)函数可以将整数value转换为string类型。

例如:

int value = 123;

string s = to_string(value);

cout << s << endl; // 123

5.2 string 转 int: stoi()int/float stoi(const string& str, nullptr_t* endptr, int base)函数可以将字符串str转换为整数,并返回转换后的整数值。

例如:

string s = "123.456";

int value = stoi(s);

cout << value << endl; // 123

5.3 string 转 float/double: stof()/stod()float/double stof(const string& str, nullptr_t* endptr)函数可以将字符串str转换为浮点数,并返回转换后的浮点数值。

例如:

string s = "123.456";

float value = stof(s);

cout << value << endl; // 123.456

提示

string类型, to_string(), stoi()都位于头文件中。

评论留言