1.初始字符串
- 在C语言中,一串以“”(双引号)引起的以’ \n '(NULL)结尾的字符就是字符串。
- 如
char* s1 = “Hello”;(s1中的字符实际为’H’ ‘e’ ‘l’ ‘l’ ‘o’ ‘\n’)
char* s2 = “Sheena”;(s2中的字符实际为’S’ ‘h’ ‘e’ ‘e’ ‘n’ ‘a’ ‘\n’)
char* s3 = “string”;(s3中的字符实际为’s’ ‘t’ ‘r’ ‘i’ ‘n’ ‘g’ ‘\n’) - 字符串是一个常量,不可以更改。
- ""表示一个空字符串。
2.字符数组
-
在C语言之简单理解数组中我们有学习到字符数组--------就是数组中存的是字符。
-
故上述的s1、s2、s3用字符数组定义如下:
char s1[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\n’};
char s2[] = {‘S’, ‘h’, ‘e’, ‘e’, ‘n’, ‘a’, ‘\n’};
char s3[] = {‘s’, ‘t’, ‘r’, ‘i’, ‘n’, ‘g’, ‘\n’};
char s4 = “hello sheena!”;//也可以这样进行初始化 -
字符数组是一个数组,其中的值可以更改。
3.字符串函数
(1)strlen
- size_t strlen( const char* str);
- 该函数是用来求字符串的长度的函数。
- 字符串是以’ \0 ‘作为结束标志,故字符串长度是指不包含’ \0 '的字符的个数。
- 注意该函数返回值为size_t无符号类型的。
#include <stdio.h>
#include <string.h>
int main()
{
char* s = "hello sheena!";
size_t len = 0;
len = strlen( s );
printf("%d\n", len);//13
return 0;
}
(2)strcpy和strncpy
①strcpy
- 该函数为将一个字符串所有的值拷贝到另一个字符串中。
- char* strcpy( char* destination, const char* source );
- 源字符串必须以‘ \0 ’结束。
- 该函数拷贝的时候会将源字符串的’ \0 '也拷贝到目标字符串中。
#include <stdio.h>
#include <string.h>
int main()
{
char* d= "hello sheena!";
char* s = "hehehe";
char str1[30];
char str2[30];
strcpy(str1, d);
strcpy(str2, s);
printf("%s\n", str1);
printf("%s\n", str2);
return 0;
}
②strncpy
- 该函数是拷贝源字符串的num个字符到目标字符串中。
- char* strncpy( char* destination, const char* source, size_t num);
- 若源字符串的长度小于num,则拷贝完源字符串后,在目标字符串的后边追加0,直到长度为n为止。
- 拷贝时不会在后面自动添加’ \0 '。
#include <stdio.h>
#include <string.h>
int main()
{
char dst[10];
char *src = "hello sheena!";
strncpy(dst, src, 5);
//dst[5] = '\0';
printf("%s\n", dst);
return 0;
}
- 由上述代码与结果我们不难发现,若我们不手动在最终的目标字符串中加’ \0 ‘,它将会输出乱码,因为输出的时候是读到’ \0 ‘为止,而strncpy不会在字符串后面自动添加’ \0 '。
- 故我们需要在拷贝之后,若拷贝的源字符串的长度中不含’ \0 ',就需要我们手动添加,正确写法如下所示
#include <stdio.h>
#include <string.h>
int main()
{
char dst[10];
char *src = "hello sheena!";
strncpy(dst, src, 5);
dst[5] = '\0';
printf("%s\n", dst);
return 0;
}
(3)strcmp和strncmp
①strcmp
- 该函数是比较两个字符串的大小(按ASCII码值比较)
- int strcmp( consr char* str1, const char* str2);
- 返回值规则为:若第一个字符串大于第二个字符串,则返回大于0的数字。若第一个字符串等于第二个字符串,则返回0。若第一个字符串小于第二个字符串,则返回小于0的数字。
- 先比较两个字符串的第一个字符的ASCII码值,若相等则再比较两个字符串的第二个字符的ASCII码值,依次类推。
#include <stdio.h>
#include <string.h>
int main()
{
char* d= "hahehe";
char* s = "hehehe";
int res = 0;
res = strcmp(d, s);
if (res > 0)
printf("res的值为: %d, 字符串d大于字符串s\n", res);
else if(res == 0)
printf("res的值为: %d, 字符串d等于字符串s\n", res);
else
printf("res的值为: %d, 字符串d小于字符串s\n", res);
return 0;
}
②strncmp
- 该函数为比较字符串1与字符串2的指定长度的大小。(比较ASCII码值)
- int strncmp( const char* str1, const char* str2, size_t num);
- 返回值规则为:若第一个字符串大于第二个字符串,则返回大于0的数字。若第一个字符串等于第二个字符串,则返回0。若第一个字符串小于第二个字符串,则返回小于0的数字。
- 先比较两个字符串的第一个字符的ASCII码值,若相等则再比较两个字符串的第二个字符的ASCII码值,依次类推。
#include <stdio.h>
#include <string.h>
int main()
{
char* d= "hexehe";
char* s = "hehehe";
int res = 0;
res = strncmp(d, s, 3);
if (res > 0)
printf("res的值为: %d, 字符串d大于字符串s\n", res);
else if(res == 0)
printf("res的值为: %d, 字符串d等于字符串s\n", res);
else
printf("res的值为: %d, 字符串d小于字符串s\n", res);
return 0;
}
(4)strcat和strncat
① strcat
- 该函数是将源字符串拼接到目标字符串中。
- char* strcat ( char* destination, const char* source);
- 源字符串必须以’ \0 '结束
- 目标字符串的空间必须足够大,能容纳下源字符串的内容。
#include <stdio.h>
#include <string.h>
int main()
{
char d[100]= "hello ";
char* s = "sheena";
strcat(d, s);
printf("%s\n", d);
return 0;
}
②strncat
- 该函数是指将源字符串的长度为num的字符拼接到目标字符串。
- char* strncat ( char* destination, const char* source, size_t num);
- 拼接之后,该函数会自动将’ \0 '挪到最后。
#include <stdio.h>
#include <string.h>
int main()
{
char d[100]= "hello ";
char* s = "sheenahellojhhjdh";
strncat(d, s, 6);
printf("%s\n", d);
return 0;
}
(5)strstr
- 该函数是判断一个字符串是否为另一个字符串的子串。
- char* strstr ( const char* str1, const char* str2);
- 返回字符串str2第一次出现在字符串str2中的位置,若没有则返回NULL。
#include <stdio.h>
#include <string.h>
int main()
{
char* d1 = "hello";
char* s = "sheenahellojhhjdh";
char* d2 = "abcd";
char *res1;
res1 = strstr(s, d1);
char *res2;
res2 = strstr(s, d2);
printf("res1 = %s, res2 = %s\n", res1, res2);
return 0;
}
(6)strtok
- 该函数是根据一个分隔符将一个字符串分隔成几个部分,然后打印出来。
- char* strstr ( char* str, const char* sep);
- sep参数是个字符串,定义了用作分隔符的字符集合。
- 第一个参数是指一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用’ \0 '结尾,返回一个指向这个标记的指针。
- strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。
- strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,保存它在字符串中的位置。
- strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回NULL指针。
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "-this is a sample-hello sheena-hello world!";
char* res;
res = strtok(str, "-");
while (res)
{
printf("%s\n", res);
res = strtok(NULL, "-");
}
return 0;
}
(7)strerror
- 该函数是返回错误码对应的错误信息。
- char* strerror( int errnum );
- 必须包含头文件error.h
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
FILE * pFile;
pFile = fopen("unexist.ent", "r");
if (pFile == NULL)
printf("错误信息为: %s\n", strerror(errno));
return 0;
}
(8)tolower 和 toupper
①tolower
- 该函数字符转换的。将一个大写字符转换为小写字符。
- int tolower( int c );
- 头文件为ctype.h
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
char* str = "Hello Sheena, Hello World";
int i = 0;
char c;
while (str[i])
{
c = str[i];
if (c >= 'A' && c <= 'Z')
c = tolower(c);
putchar(c);
++i;
}
return 0;
}
②toupper
- 该函数字符转换的。将一个小写字符转换为大写字符。
- int toupper( int c );
- 头文件为ctype.h
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
char* str = "Hello Sheena, Hello World";
int i = 0;
char c;
while (str[i])
{
c = str[i];
if (c >= 'a' && c <= 'z')
c = toupper(c);
putchar(c);
++i;
}
return 0;
}
4.内存操作函数
(1)memcpy
- 该函数从source的位置开始向后拷贝num个字节的数据到destination的内存位置。
- void* memcpy( void* destination, const void* source, size_t num);
- 这个函数在遇到’ \0 '的时候并不会停下来。
- 若source和destination有任何的重叠,拷贝的结果都是未定义的。
#include <stdio.h>
#include <string.h>
int main()
{
int a1[10];
int a2[] = { 1, 2, 3, 4, 5 };
double a3[2];
double a4[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
memcpy(a1, a2, sizeof(a2) * sizeof(int));
memcpy(a3, a4, 16);
for (int i = 0; i < 5; ++i)
{
printf("%d ", a1[i]);
}
printf("\n");
for (int i = 0; i < sizeof(a3) / sizeof(double); ++i)
{
printf("%f ", a3[i]);
}
printf("\n");
return 0;
}
(2)memmove
- 该函数是memcpy作用差不多。
- void* memmove( void* destination, const void* source, size_t num);
- 和memcpy的差别就是memmove函数处理的source和destination是可以重叠的。
- 若source和destination出现重叠,就必须使用memmove函数处理。
#include <stdio.h>
#include <string.h>
int main()
{
int arr[10] = { 1, 2, 3, 4, 5 };
memcpy(arr , arr + 2, 12);
for (int i = 0; i < 5; ++i)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
(3)memcmp
- 比较ptr1和ptr2指针开始的num个字节的大小。
- int memcmp ( const void* ptr1, const void* ptr2, size_t num );
- 返回值和strcpy一样。
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1, 2, 3, 4, 5 };
int arr2[] = { 1, 2, 3, 5, 55 };
int res1 = 0, res2 = 0;
res1 = memcmp(arr1, arr2, 12);
if (res1 > 0)
printf("res1的值为:%d, arr1 > arr2\n", res1);
else if(res1 == 0)
printf("res1的值为:%d, arr1 = arr2\n", res1);
else
printf("res1的值为:%d, arr1 < arr2\n", res1);
res2 = memcmp(arr1, arr2, 20);
if (res2 > 0)
printf("res2的值为:%d, arr1 > arr2\n", res2);
else if (res2 == 0)
printf("res2的值为:%d, arr1 = arr2\n", res2);
else
printf("res2的值为:%d, arr1 < arr2\n", res2);
return 0;
}