标准C库提供的对字符串的处理函数,分为字符串的输入、输出、合并、修改、比较、转换、复制、搜索等几类(ps 越学越像java了)
字符串输入/输出
字符串输出(字符串专用)
常用的字符串输出函数有 putchar()、puts()、fputc()、fputs(),前面我们经常使用 printf()函数来输出字符串信息,而并没有使用到 putchar()、puts()、fputc()、fputs()这些函数,原因在于 printf()可以按照自己规定的格式输出字符串信息,一般称为格式化输出;而 putchar()、puts()、fputc()、fputs()这些函数只能输出字符串,不能进行格式转换。与 printf()一样,putchar()、puts()、fputc()、fputs()这些函数也是标准 I/O 函数,属于标准 C 库函数,所以需要包含头文件<stdio.h>,并且它们也使用 stdio 缓冲。
puts 函数(man 3 puts)
puts()函数用来向标准输出设备(屏幕、显示器)输出字符串并自行换行。把字符串输出到标准输出设备,将' \0 '转换为换行符' \n '。
#include <stdio.h>
int puts(const char *s);
s : 需要进行输出的字符串。返回值: 成功返回一个非负数;失败将返回 EOF , EOF 其实就是 -1 。
char str[50] = "Linux app puts test";
puts("Hello World!");
puts(str);
putchar 函数(man 3 putchar)
#include <stdio.h>int putchar(int c);c : 需要进行输出的字符。返回值: 出错将返回 EOF 。
putchar('A');
putchar('B');
putchar('C');
putchar('D');
putchar('\n');
fputc 函数
fputc()与 putchar()类似,也用于输出参数 c 指定的字符(一个无符号字符),与 putchar()区别在于, putchar()只能输出到标准输出设备,而 fputc()可把字符输出到指定的文件中,既可以是标准输出,也可以是一个普通文件。
#include <stdio.h>int fputc(int c, FILE *stream);c : 需要进行输出的字符。stream : 文件指针。返回值: 成功时返回输出的字符;出错将返回 EOF 。
//输出到标准输出设备
fputc('A', stdout);
fputc('B', stdout);
fputc('C', stdout);
fputc('D', stdout);
fputc('\n', stdout);
//输出到普通文件
fputc('A', fp);
fputc('B', fp);
fputc('C', fp);
fputc('D', fp);
fputc('\n', fp);
#include <stdio.h>int fputs(const char *s, FILE *stream);s : 需要输出的字符串。stream : 文件指针。返回值: 成功返回非负数;失败将返回 EOF 。
//输出到标准输出设备
fputs("Hello World! 1\n", stdout);
fputs("Hello World! 2\n", stdout);
//输出到普通文件
fputs("Hello World! 1\n", fp);
fputs("Hello World! 2\n", fp);
字符串输入
#include <stdio.h>char *gets(char *s);s : 指向字符数组的指针,用于存储字符串。返回值: 如果成功,该函数返回指向 s 的指针;如果发生错误或者到达末尾时还未读取任何字符,则返回 NULL 。
#include <stdio.h>int getchar(void);无需传参 。返回值: 该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF 。
#include <stdio.h>char *fgets(char *s, int size, FILE *stream);s : 指向字符数组的指针,用于存储字符串。size : 这是要读取的最大字符数。stream : 文件指针。
//从键盘输入
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char str[100] = {0};
printf("请输入字符串: ");
fgets(str, sizeof(str), stdin);
printf("%s", str);
exit(0);
}
//从文件输入
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char str[100] = {0};
FILE *fp = NULL;
/* 打开文件 */
fp = fopen("./test_file", "r");
if (NULL == fp) {
perror("fopen error");
exit(-1);
}
/* 从文件中输入字符串 */
fgets(str, sizeof(str), fp);
printf("%s", str);
/* 关闭文件 */
fclose(fp);
exit(0);
}
#include <stdio.h>int fgetc(FILE *stream);stream : 文件指针返回值: 该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF 。
字符串长度
#include <string.h>size_t strlen(const char *s);s : 需要进行长度计算的字符串,字符串必须包含结束字符 ' \0 ' 。返回值: 返回字符串长度(以字节为单位),字符串结束字符 ' \0 ' 不计算在内。
char str[] = "Linux app strlen test!";
printf("String: \"%s\"\n", str);
printf("Length: %ld\n", strlen(str));
=========================================================================
字符串拼接
#include <string.h>char *strcat(char *dest, const char *src);dest : 目标字符串。src : 源字符串。返回值: 返回指向目标字符串 dest 的指针。 strcat()函数会把 src 所指向的字符串追加到 dest 所指向的字符串末尾,所以必须要保证 dest 有足够的存储空间来容纳两个字符串,否则会导致溢出错误;dest 末尾的 ' \0 ' 结束字符会被覆盖, src 末尾的结束字符 ' \0 '会一起被复制过去,最终的字符串只有一个 ' \0 ' 。
char str1[100] = "Linux app strcat test, ";
char str2[] = "Hello World!";
strcat(str1, str2);
puts(str1);
#include <string.h>char *strncat(char *dest, const char *src, size_t n);dest : 目标字符串。src : 源字符串。n : 要追加的最大字符数。返回值: 返回指向目标字符串 dest 的指针。
char str1[100] = "Linux app strcat test, ";
char str2[] = "Hello World!";
strncat(str1, str2, 5);
puts(str1);
//输出:Linux app strcat test,Hello
=========================================================================
字符串拷贝
#include <string.h>char *strcpy(char *dest, const char *src);dest : 目标字符串。src : 源字符串。返回值: 返回指向目标字符串 dest 的指针。
char str1[100] = {0};
char str2[] = "Hello World!";
strcpy(str1, str2);
puts(str1);
#include <string.h>char *strncpy(char *dest, const char *src, size_t n);dest : 目标字符串。src : 源字符串。n : 从 src 中复制的最大字符数。返回值: 返回指向目标字符串 dest 的指针。
内存填充
#include <string.h>void *memset(void *s, int c, size_t n);s : 需要进行数据填充的内存空间起始地址。c : 要被设置的值,该值以 int 类型传递。n : 填充的字节数。返回值: 返回指向内存空间 s 的指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char str[100];
memset(str, 0x0, sizeof(str));
exit(0);
}
#include <strings.h>void bzero(void *s, size_t n);s : 内存空间的起始地址。n : 填充的字节数。返回值: 无返回值。
char str[100];
bzero(str, sizeof(str));
=========================================================================
字符串比较
strcmp()函数(字符串比较)
#include <string.h>int strcmp(const char *s1, const char *s2);s1 : 进行比较的字符串 1 。s2 : 进行比较的字符串 2 。返回值:⚫ 如果返回值小于 0 ,则表示 str1 小于 str2⚫ 如果返回值大于 0 ,则表示 str1 大于 str2⚫ 如果返回值等于 0 ,则表示字符串 str1 等于字符串 str2
printf("%d\n", strcmp("ABC", "ABC"));
printf("%d\n", strcmp("ABC", "a"));
printf("%d\n", strcmp("a", "ABC"));
strncmp 函数 (字符串比较)
strncmp()与 strcmp()函数一样,也用于对字符串进行比较操作,但最多比较前 n 个字符
#include <string.h>int strncmp(const char *s1, const char *s2, size_t n);s1 : 参与比较的第一个字符串。s2 : 参与比较的第二个字符串。n : 最多比较前 n 个字符。返回值: 返回值含义与 strcmp() 函数相同。
printf("%d\n", strncmp("ABC", "ABC", 3));
printf("%d\n", strncmp("ABC", "ABCD", 3));
printf("%d\n", strncmp("ABC", "ABCD", 4));
=========================================================================
字符串查找
#include <string.h>char *strchr(const char *s, int c);s : 给定的目标字符串。c : 需要查找的字符。返回值: 返回字符 c 第一次在字符串 s 中出现的位置,如果未找到字符 c ,则返回 NULL 。
char *ptr = NULL;
char str[] = "Hello World!";
ptr = strchr(str, 'W');
if (NULL != ptr) {
printf("Character: %c\n", *ptr);
printf("Offset: %ld\n", ptr - str);
}
//Character:W
//Offset:6
strrchr 函数
strrchr()与 strchr()函数一样,它同样表示在字符串中查找某一个字符,返回字符第一次在字符串中出现的位置,如果没找到该字符,则返回值 NULL,但两者唯一不同的是,strrchr()函数在字符串中是从后到前 (或者称为从右向左)查找字符,找到字符第一次出现的位置就返回,返回值指向这个位置
#include <string.h>char *strrchr(const char *s, int c);
char *ptr = NULL;
char str[] = "I love my home";
ptr = strchr(str, 'o');
if (NULL != ptr)
printf("strchr: %ld\n", ptr - str);
ptr = strrchr(str, 'o');
if (NULL != ptr)
printf("strrchr: %ld\n", ptr - str);
//strchr:3
//strrchr:11
strstr 函数 (查找字符串的位置)
与 strchr()函数不同的是,strstr()可在给定的字符串 haystack 中查找第一次出现子字符串 needle 的位置, 不包含结束字符' \0
#include <string.h>char *strstr(const char *haystack, const char *needle);haystack : 目标字符串。needle : 需要查找的子字符串。返回值: 如果目标字符串 haystack 中包含了子字符串 needle ,则返回该字符串首次出现的位置;如果未能找到子字符串 needle ,则返回 NULL 。
char *ptr = NULL;
char str[] = "I love my home";
ptr = strstr(str, "home");
if (NULL != ptr) {
printf("String: %s\n", ptr);
printf("Offset: %ld\n", ptr - str);
}
//String:home
//Offset:10
(写到这突然发现有个水平线功能)
字符串与数字互转
字符串转整形数据
#include <stdlib.h>
int atoi(const char *nptr);
long atol(const char *nptr);
long long atoll(const char *nptr);
printf("atoi: %d\n", atoi("500"));
printf("atol: %ld\n", atol("500"));
printf("atoll: %lld\n", atoll("500"));
#include <stdlib.h>long int strtol(const char *nptr, char **endptr, int base);long long int strtoll(const char *nptr, char **endptr, int base);nptr : 需要进行转换的目标字符串。endptr : char ** 类型的指针,如果 endptr 不为 NULL ,则 strtol() 或 strtoll() 会将字符串中第一个无效字符的地址存储在*endptr 中。如果根本没有数字, strtol() 或 strtoll() 会将 nptr 的原始值存储在 *endptr 中(并返回 0 )。也可将参数 endptr 设置为 NULL ,表示不接收相应信息。base : 数字基数,参数 base 必须介于 2 和 36 (包含)之间,或者是特殊值 0 。参数 base 决定了字符串转换为整数时合法字符的取值范围,譬如,当 base=2 时,合法字符为 ' 0 ' 、 ' 1 ' (表示是一个二进制表示的数字字符串);当 base=8 时,合法字符为 ' 0 ' 、 ' 1 ' 、 ' 2 ' 、 ' 3 '……' 7 ' (表示是一个八进制表示的数字字符串);当 base=16 时,合法字符为 ' 0 ' 、 ' 1 ' 、 ' 2 ' 、 ' 3 '……' 9 ' 、 ' a '……' f ' (表示是一个十六进制表示的数字字符串);当 base 大于 10 的时候, ' a ' 代表 10 、 ' b ' 代表 11 、 ' c ' 代表 12 ,依次类推, ' z ' 代表 35 (不区分大小写)。返回值: 分别返回转换之后得到的 long int 类型数据以及 long long int 类型数据。
printf("strtol: %ld\n", strtol("0x500", NULL, 16));
printf("strtol: %ld\n", strtol("0x500", NULL, 0));
printf("strtol: %ld\n", strtol("500", NULL, 16));
printf("strtol: %ld\n", strtol("0777", NULL, 8));
printf("strtol: %ld\n", strtol("0777", NULL, 0));
printf("strtol: %ld\n", strtol("1111", NULL, 2));
printf("strtol: %ld\n", strtol("-1111", NULL, 2));
#include <stdlib.h>unsigned long int strtoul(const char *nptr, char **endptr, int base);unsigned long long int strtoull(const char *nptr, char **endptr, int base);
printf("strtoul: %lu\n", strtoul("0x500", NULL, 16));
printf("strtoul: %lu\n", strtoul("0x500", NULL, 0));
printf("strtoul: %lu\n", strtoul("500", NULL, 16));
printf("strtoul: %lu\n", strtoul("0777", NULL, 8));
printf("strtoul: %lu\n", strtoul("0777", NULL, 0));
printf("strtoul: %lu\n", strtoul("1111", NULL, 2));
数字转字符串
char str[20] = {0};
sprintf(str, "%d", 500);
puts(str);
memset(str, 0x0, sizeof(str));
sprintf(str, "%f", 500.111);
puts(str);
memset(str, 0x0, sizeof(str));
sprintf(str, "%u", 500);
puts(str);
字符串转浮点型数据
#include <stdlib.h>double atof(const char *nptr);nptr : 需要进行转换的字符串。返回值: 返回转换得到的 double 类型数据。
printf("atof: %lf\n", atof("0.123"));
printf("atof: %lf\n", atof("-1.1185"));
printf("atof: %lf\n", atof("100.0123"));
/*
atof:0.123000
atof:-1.118500
atof:100.012300
*/
#include <stdlib.h>double strtod(const char *nptr, char **endptr);float strtof(const char *nptr, char **endptr);long double strtold(const char *nptr, char **endptr);nptr : 需要进行转换的目标字符串。endptr : char ** 类型的指针,如果 endptr 不为 NULL ,则 strtol() 或 strtoll() 会将字符串中第一个无效字符的地址存储在*endptr 中。如果根本没有数字, strtol() 或 strtoll() 会将 nptr 的原始值存储在 *endptr 中(并返回 0 )。也可将参数 endptr 设置为 NULL ,表示不接收相应信息。
printf("strtof: %f\n", strtof("0.123", NULL));
printf("strtod: %lf\n", strtod("-1.1185", NULL));
printf("strtold: %Lf\n", strtold("100.0123", NULL));
给应用程序传参
之前讲的都是硬传参,东西都写好在代码里面,比如要改变打开文件的路径,就只能修改程序,很麻烦,真正应用时是根据参入不同的参数实现不同的功能,譬如,当执行应用程序的时候,把需要打开的文件路径作为参数传递给应用程序,就可以在不重新编译源码的情况下,通过传递不同的参数打开不同的文件。
注:如果在执行应用程序时,需要向应用程序传递参数,则写法如下:
int main(int argc, char **argv) {
/* 代码 */
}
//或者写成如下形式:
int main(int argc, char *argv[])
{
/* 代码 */
}
//获取执行应用程序时,向应用程序传递的参数。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 0;
printf("Number of parameters: %d\n", argc);
for (i = 0; i < argc; i++)
printf(" %s\n", argv[i]);
exit(0);
}
/*
out
./testApp 0 1 2
Number of parameters:4
./testApp
0
1
2
*/
正则表达式(重要)(校验账户和密码是否合规)
^((ht|f)tps?)://[-A-Za-z0-9_]+(\.[-A-Za-z0-9_]+)+([-A-Za-z0-9_.,@?^=%&:/~+#]*[-A-Za-z0-9_@?^=%&/~+#])?$
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <regex.h>
#include <string.h>
int main(int argc, char *argv[])
{
regmatch_t pmatch = {0};
regex_t reg;
char errbuf[64];
int ret;
char *sptr;
int length;
int nmatch; //最多匹配出的结果
if (4 != argc) {
/**********************************
* 执行程序时需要传入两个参数:
* arg1: 正则表达式
* arg2: 待测试的字符串
* arg3: 最多匹配出多少个结果
**********************************/
fprintf(stderr, "usage: %s <regex> <string> <nmatch>\n", argv[0]);
exit(0);
}
/* 编译正则表达式 */
if(ret = regcomp(®, argv[1], REG_EXTENDED)) {
regerror(ret, ®, errbuf, sizeof(errbuf));
fprintf(stderr, "regcomp error: %s\n", errbuf);
exit(0);
}
/* 赋值操作 */
sptr = argv[2]; //待测试的字符串
length = strlen(argv[2]);//获取字符串长度
nmatch = atoi(argv[3]); //获取最大匹配数
/* 匹配正则表达式 */
for (int j = 0; j < nmatch; j++) {
char temp_str[100];
/* 调用 regexec 匹配正则表达式 */
if(ret = regexec(®, sptr, 1, &pmatch, 0)) {
regerror(ret, ®, errbuf, sizeof(errbuf));
fprintf(stderr, "regexec error: %s\n", errbuf);
goto out;
}
if(-1 != pmatch.rm_so) {
if (pmatch.rm_so == pmatch.rm_eo) {//空字符串
sptr += 1;
length -= 1;
printf("\n"); //打印出空字符串
if (0 >= length)//如果已经移动到字符串末尾、则退出
break;
continue; //从 for 循环开始执行
}
memset(temp_str, 0x00, sizeof(temp_str));//清零缓冲区
memcpy(temp_str, sptr + pmatch.rm_so,
pmatch.rm_eo - pmatch.rm_so);//将匹配出来的子字符串拷贝到缓冲区
printf("%s\n", temp_str); //打印字符串
sptr += pmatch.rm_eo;
length -= pmatch.rm_eo;
if (0 >= length)
break;
}
}
/* 释放正则表达式 */
out:
regfree(®);
exit(0);
}