参考引用
- UNIX 环境高级编程 (第3版)
- 嵌入式Linux C应用编程-正点原子
#include
// s:需要进行输出的字符串
// 返回值:成功返回一个非负数;失败将返回 EOF,EOF 其实就是 -1
int puts(const char *s);
#include
#include
int main(void) {
char str[50] = "Linux app puts test";
puts("Hello World!");
puts(str);
exit(0);
}
$ gcc test.c -o test
$ ./test
Hello World!
Linux app puts test # 自动换行
#include
// c:需要进行输出的字符
// 返回值:出错将返回 EOF
int putchar(int c);
putchar('A');
#include
// c:需要进行输出的字符
// stream:文件指针
// 返回值:成功时返回输出的字符;出错将返回 EOF
int fputc(int c, FILE *stream);
// 1. 使用 fputc 函数将字符输出到标准输出设备
fputc('A', stdout);
// 2. 使用 fputc 函数将字符输出到一个普通文件
/* 创建一个文件 */
fp = fopen("./new_file", "a");
/* 输入字符到文件 */
fputc('A', fp);
/* 关闭文件 */
fclose(fp);
#include
// s:需要输出的字符串
// stream:文件指针
// 返回值:成功返回非负数;失败将返回 EOF
int fputs(const char *s, FILE *stream);
// 1. 使用 fputs 输出字符串到标注输出设备
fputs("Hello World! 1\n", stdout);
// 2. 使用 fputs 输出字符串到一个普通文件
/* 创建一个文件 */
fp = fopen("./new_file", "a");
/* 输入字符到文件 */
fputs("Hello World! 1\n", fp);
/* 关闭文件 */
fclose(fp);
#include
// s:指向字符数组的指针,用于存储字符串。
// 返回值:如果成功,该函数返回指向 s 的指针;如果发生错误或者到达末尾时还未读取任何字符,则返回 NULL
char *gets(char *s);
程序中使用 gets() 函数是非常不安全的,可能会出现 bug、出现不可靠性,可以使用 fgets() 代替
fgets() 与 gets() 一样用于获取输入的字符串,但比 gets() 安全
#include
// s:指向字符数组的指针,用于存储字符串
// size:这是要读取的最大字符数
// stream:文件指针
char *fgets(char *s, int size, FILE *stream);
fgets() 与 gets() 的区别
fgets 从标准输入设备获取字符串
#include
#include
int main(void) {
char str[100] = {0};
printf("请输入字符串: ");
fgets(str, sizeof(str), stdin);
printf("%s", str);
exit(0);
}
fgets 从普通文件中输入字符串
#include
#include
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
// 返回值:该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF
int getchar(void);
#include
#include
int main(void) {
int ch;
ch = getchar();
printf("ch: %c\n", ch);
exit(0);
}
$ gcc test.c -o test
$ ./test
123
ch: 1 # 只从输入缓冲区中读取一个字符
#include
// stream:文件指针
// 返回值:该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF
int fgetc(FILE *stream);
// 1. fgetc 从标准输入设备中输入字符
int ch;
ch = fgetc(stdin);
// 2. fgetc 从普通文件中输入字符
/* 打开文件 */
fp = fopen("./test_file", "r");
/* 从文件中输入一个字符 */
ch = fgetc(fp);
/* 关闭文件 */
fclose(fp);
#include
// s:需要进行长度计算的字符串,字符串必须包含结束字符 '\0'
// 返回值:返回字符串长度(以字节为单位),字符串结束字符 '\0' 不计算在内
size_t strlen(const char *s);
sizeof 和 strlen 的区别
- sizeof 是 C 语言内置的操作符关键字,而 strlen 是 C 语言库函数
- sizeof 仅用于计算数据类型的大小或者变量的大小,而 strlen 只能以结尾为 ‘\0’ 的字符串作为参数
- 编译器在编译时就计算出了 sizeof 的结果,而 strlen 必须在运行时才能计算出来
- sizeof 计算数据类型或变量会占用内存的大小,strlen 计算字符串实际长度
#include
#include
#include
int main(void) {
char str[50] = "Linux app strlen test!";
char *ptr = str;
printf("sizeof: %ld\n", sizeof(str));
printf("strlen: %ld\n", strlen(str));
puts("~~~~~~~~~~");
printf("sizeof: %ld\n", sizeof(ptr));
printf("strlen: %ld\n", strlen(ptr));
exit(0);
}
$ gcc test.c -o test
$ ./test
sizeof: 50 # 数组变量 str 的大小
strlen: 22 # strlen 始终计算的都是字符串的长度
~~~~~~~~~~
sizeof: 8 # 指针变量 ptr 的大小
strlen: 22 # strlen 始终计算的都是字符串的长度
#include
// dest:目标字符串
// src:源字符串
// 返回值:返回指向目标字符串 dest 的指针
char *strcat(char *dest, const char *src);
#include
#include
#include
int main(void) {
char str1[100] = "Linux app strcat test, ";
char str2[] = "Hello World!";
strcat(str1, str2);
puts(str1);
exit(0);
}
#include
// dest:目标字符串
// src:源字符串
// n:要追加的最大字符数
// 返回值:返回指向目标字符串 dest 的指针
char *strncat(char *dest, const char *src, size_t n);
#include
#include
#include
int main(void) {
char str1[100] = "Linux app strcat test, ";
char str2[] = "Hello World!";
strncat(str1, str2, 5);
puts(str1);
exit(0);
}
#include
// dest:目标字符串
// src:源字符串
// 返回值:返回指向目标字符串 dest 的指针
char *strcpy(char *dest, const char *src);
#include
#include
#include
int main(void) {
char str1[100] = {0};
char str2[] = "Hello World!";
strcpy(str1, str2);
puts(str1);
exit(0);
}
#include
// dest:目标字符串
// src:源字符串
// n:从 src 中复制的最大字符数
// 返回值:返回指向目标字符串 dest 的指针
char *strncpy(char *dest, const char *src, size_t n);
#include
#include
#include
int main(void) {
char str1[100] = "AAAAAAAAAAAAAAAAAAAAAAAA";
char str2[] = "Hello World!";
strncpy(str1, str2, 5);
puts(str1);
puts("~~~~~~~~~~~~~~~");
strncpy(str1, str2, 20);
puts(str1);
exit(0);
}
除了 strcpy() 和 strncpy() 之外,还可以使用 memcpy()、memmove() 以及 bcopy() 这些库函数实现拷贝操作,字符串拷贝本质上也只是内存数据的拷贝,所以这些库函数同样也是适用的
memset() 函数用于将某一块内存的数据全部设置为指定的值
#include
// s:需要进行数据填充的内存空间起始地址
// c:要被设置的值,该值以 int 类型传递
// n:填充的字节数
// 返回值:返回指向内存空间 s 的指针
void *memset(void *s, int c, size_t n);
参数 c 虽然是以 int 类型传递,但 memset() 函数在填充内存块时是使用该值的无符号字符形式,也就是函数内部会将该值转换为 unsigned char 类型的数据,以字节为单位进行数据填充
示例
#include
#include
#include
int main(void) {
char str[100];
memset(str, 0x0, sizeof(str)); // 对数组 str 进行初始化操作,将其存储的数据全部设置为 0
exit(0);
}
#include
// s:内存空间的起始地址
// n:填充的字节数
void bzero(void *s, size_t n);
#include
#include
#include
int main(void) {
char str[100];
bzero(str, sizeof(str));
exit(0);
}
strcmp 进行字符串比较,主要是通过比较字符串中字符对应的 ASCII 码值,根据 ASCII 编码依次比较 str1 和 str2 的每一个字符,直到出现了不同的字符,或者某一字符串已经到达末尾(遇见了字符串结束字符 ‘\0’)
#include
// s1:进行比较的字符串 1
// s2:进行比较的字符串 2
/* 返回值
小于 0,则表示 str1 小于 str2
大于 0,则表示 str1 大于 str2
等于 0,则表示字符串 str1 等于字符串 str2
*/
int strcmp(const char *s1, const char *s2);
测试
#include
#include
#include
int main(void) {
printf("%d\n", strcmp("ABC", "ABC"));
printf("%d\n", strcmp("ABC", "a"));
printf("%d\n", strcmp("a", "ABC"));
exit(0);
}
#include
// s1:参与比较的第一个字符串
// s2:参与比较的第二个字符串
// n:最多比较前 n 个字符
// 返回值:返回值含义与 strcmp() 函数相同
int strncmp(const char *s1, const char *s2, size_t n);
#include
#include
#include
int main(void) {
printf("%d\n", strncmp("ABC", "ABC", 3));
printf("%d\n", strncmp("ABC", "ABCD", 3));
printf("%d\n", strncmp("ABC", "ABCD", 4));
exit(0);
}
#include
// s:给定的目标字符串
// c:需要查找的字符
// 返回值:返回字符 c 第一次在字符串 s 中出现的位置,如果未找到字符 c,则返回 NULL
char *strchr(const char *s, int c);
#include
#include
#include
int main(void) {
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);
}
exit(0);
}
#include
char *strrchr(const char *s, int c);
#include
#include
#include
int main(void) {
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);
exit(0);
}
#include
// haystack:目标字符串
// needle:需要查找的子字符串
// 返回值:如果 haystack 中包含 needle,则返回该字符串首次出现的位置;如果未能找到 needle,则返回 NULL
char *strstr(const char *haystack, const char *needle);
#include
#include
#include
int main(void) {
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);
}
exit(0);
}
#include
// nptr:需要进行转换的字符串
// 返回值:分别返回转换之后得到的 int 类型数据、long int 类型数据以及 long long 类型数据
int atoi(const char *nptr);
long atol(const char *nptr);
long long atoll(const char *nptr);
#include
// nptr:需要进行转换的目标字符串。
/* endptr
char **类型的指针,如果 endptr 不为 NULL,则会将字符串中第一个无效字符的地址存储在*endptr 中
如果根本没有数字,strtol() 或 strtoll()会将 nptr 的原始值存储在 *endptr 中(并返回 0)
也可将参数 endptr 设置为 NULL,表示不接收相应信息
*/
// base:数字基数,参数 base 必须介于 2 和 36(包含)之间,或者是特殊值 0
long int strtol(const char *nptr, char **endptr, int base);
long long int strtoll(const char *nptr, char **endptr, int base);
#include
unsigned long int strtoul(const char *nptr, char **endptr, int base);
unsigned long long int strtoull(const char *nptr, char **endptr, int base);
#include
double atof(const char *nptr);
#include
#include
#include
int main(void) {
printf("atof: %lf\n", atof("0.123"));
printf("atof: %lf\n", atof("-1.1185"));
printf("atof: %lf\n", atof("100.0123"));
exit(0);
}
#include
double strtod(const char *nptr, char **endptr);
float strtof(const char *nptr, char **endptr);
long double strtold(const char *nptr, char **endptr);
#include
#include
#include
int main(void) {
printf("strtof: %f\n", strtof("0.123", NULL));
printf("strtod: %lf\n", strtod("-1.1185", NULL));
printf("strtold: %Lf\n", strtold("100.0123", NULL));
exit(0);
}
#include
#include
#include
int main(void) {
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);
exit(0);
}
open 打开的文件路径是固定的,如果需要打开另一个文件则需要修改代码、修改文件路径,然后再重新编译、运行,非常麻烦、不够灵活。可将这些可变信息通过参数形式传递给应用程序,如:当执行应用程序的时候,把需要打开的文件路径作为参数传递给应用程序,就可在不重新编译源码的情况下,通过传递不同的参数打开不同的文件
int main(int argc, char *argv[]) {
/* 代码 */
}
测试
#include
#include
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);
}
$ gcc test.c -o test
$ ./test 0 1 2
Number of parameters: 4
./test
0
1
2
$ ./test a b c
Number of parameters: 4
./test
a
b
c
对于这些需求,只需要通过一个正则表达式就可以实现
data.dat
data1.dat
data2.dat
datax.dat
dataN.dat
^((ht|f)tps?)://[-A-Za-z0-9_]+(\.[-A-Za-z0-9_]+)+([-A-Za-z0-9_.,@?^=%&:/~+#]*[-A-Za-z0-9_@?^=%&/~+#])?$
#include
#include
#include
#include
#include
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 \n" , argv[0]);
exit(0);
}
/* 1、编译正则表达式 */
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]); //获取最大匹配数
/* 2、匹配正则表达式 */
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;
}
}
/* 3、释放正则表达式 */
out:
regfree(®);
exit(0);
}