您的位置:首页 > 汽车 > 时评 > 企业推广普通话_贵州遵义疫情最新情况_谷歌商店官网_公司网站建设北京

企业推广普通话_贵州遵义疫情最新情况_谷歌商店官网_公司网站建设北京

2024/12/26 20:38:21 来源:https://blog.csdn.net/qq_55125921/article/details/142707163  浏览:    关键词:企业推广普通话_贵州遵义疫情最新情况_谷歌商店官网_公司网站建设北京
企业推广普通话_贵州遵义疫情最新情况_谷歌商店官网_公司网站建设北京

1.关键字

一、数据类型关键字

A基本数据类型(5个)

  • void:声明函数无返回值或无参数,声明无类型指针,显式丢弃运算结果
  • char:字符型类型数据,属于整型数据的一种
  • int:整型数据,通常为编译器指定的机器字长
  • float:单精度浮点型数据,属于浮点数据的一种
  • double:双精度浮点型数据,属于浮点数据的一种

B类型修饰关键字(4个)

  • short:修饰int,短整型数据,可省略被修饰的int。
  • long:修饰int,长整形数据,可省略被修饰的int。
  • signed:修饰整型数据,有符号数据类型
  • unsigned:修饰整型数据,无符号数据类型

C复杂类型关键字(5个)

  • struct:结构体声明
  • union:共用体声明
  • enum:枚举声明
  • typedef:声明类型别名
  • sizeof:得到特定类型或特定类型变量的大小

D存储级别关键字(6个)

  • auto:指定为自动变量,由编译器自动分配及释放。通常在栈上分配
  • static:指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部
  • register:指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数
  • extern:指定对应变量为外部变量,即在另外的目标文件中定义,可以认为是约定由另外文件声明的对象的一个“引用“
  • const:与volatile合称“cv特性”,指定变量不可被当前线程/进程改变(但有可能被系统或其他线程/进程改变)
  • volatile:与const合称“cv特性”,指定变量的值有可能会被系统或其他进程/线程改变,强制编译器每次从内存中取得该变量的值

二、流程控制关键字

A跳转结构(4个)

  • return:用在函数体中,返回特定值(或者是void值,即不返回值)
  • continue:结束当前循环,开始下一轮循环
  • break:跳出当前循环或switch结构
  • goto:无条件跳转语句

B分支结构(5个)

  • if:条件语句
  • else:条件语句否定分支(与if连用)
  • switch:开关语句(多重分支语句)
  • case:开关语句中的分支标记
  • default:开关语句中的“其他”分治,可选。

C循环结构(3个)

  • for:for循环结构,for(1;2;3)4;的执行顺序为1->2->4->3->2…循环,其中2为循环条件
  • do:do循环结构,do 1 while(2);的执行顺序是1->2->1…循环,2为循环条件
  • while:while循环结构,while(1) 2;的执行顺序是1->2->1…循环,1为循环条件

以上循环语句,当循环条件表达式为真则继续循环,为假则跳出循环。

关键字 typedef

typedef 顾名思义是类型定义,这里应该理解为类型重命名。比如:

//将unsigned int 重命名为uint_32, 所以uint_32也是一个类型名
typedef unsigned int uint_32;
int main()
{//观察num1和num2,这两个变量的类型是一样的unsigned int num1 = 0;uint_32 num2 = 0;return 0; }

关键字static

在C语言中:
static是用来修饰变量和函数的

  1. 修饰局部变量-称为静态局部变量
  2. 修饰全局变量-称为静态全局变量
  3. 修饰函数-称为静态函数
1 修饰局部变量

对比代码1和代码2的效果理解static修饰局部变量的意义。

//代码1
#include <stdio.h>
void test()
{int i = 0;i++;printf("%d ", i);  //每次函数执行结束,i值都会被释放掉
}
int main()
{int i = 0;for(i=0; i<10; i++){test(); //每次有打印1}return 0; }
12345678910111213141516
//代码2
#include <stdio.h>
void test()
{//static修饰局部变量static int i = 0;  //test()执行结束后,保留i值i++;printf("%d ", i);
}
int main()
{int i = 0;for(i=0; i<10; i++){test(); //每次有打印1到10}return 0; }
1234567891011121314151617

结论:static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。

2 修饰全局变量

代码1正常,代码2在编译的时候会出现连接性错误。

//代码1
//add.c
int g_val = 2018;
//test.c
int main()
{printf("%d\n", g_val);return 0; }//代码2
//add.c   static 全局变量
static int g_val = 2018;
//test.c
int main()
{printf("%d\n", g_val);return 0; }
1234567891011121314151617

结论:一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。

3 修饰函数

代码1正常,代码2在编译的时候会出现连接性错误,和修饰全局变量一样。

//代码1
//add.c
int Add(int x, int y) {return x+y; }
//test.c
int main()
{printf("%d\n", Add(2, 3));return 0; }//代码2
//add.c   static 修饰函数
static int Add(int x, int y) {return c+y; }
//test.c
int main()
{printf("%d\n", Add(2, 3));return 0; }
12345678910111213141516171819

结论:一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。

2.基础数据类型 和 尺寸

char //字符数据类型short //短整型int //整形long //长整型long //更长的整形float //单精度浮点数double //双精度浮点数//C语言有没有字符串类型? 答案是没有。c语言中没有string类型,string是用char型数组来构造的。

每种数据类型占据的字节大小:

#include <stdio.h>  
int main()
{//以下是在win10的vs2017显示的结果printf("%d\n", sizeof(char));  // 1printf("%d\n", sizeof(short));  // 2printf("%d\n", sizeof(int));  // 4printf("%d\n", sizeof(long));  // 4printf("%d\n", sizeof(long long));  //8printf("%d\n", sizeof(float));  //4printf("%d\n", sizeof(double));  // 8printf("%d\n", sizeof(long double));  //8return 0; }
12345678910111213

存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。
类型的使用:

char ch = 'w';  //字符型
int weight = 120;  //整型
float salary = 20000.0f;  //单精度浮点型

3. 变量、常量

生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)
有些值是可变的(比如:年龄,体重,薪资)。
不变的值,C语言中用常量的概念来表示,变得值C语言中用变量来表示。

3.1 定义变量的方法

语法:变量类型 变量名称 = 初始值;

int age = 150;
float weight = 45.5f;
char ch = 'w';
123

3.2 变量的分类

1)局部变量
2)全局变量
#include <stdio.h>
int global = 2019;//全局变量
int main()
{int local = 2018;//局部变量//下面定义的global会不会有问题?没有问题int global = 2020;//局部变量,当局部变量和全局变量同名时,优先使用局部变量,这个人感觉和搜索路径相关!printf("global = %d\n", global);return 0; }

3.3 变量的使用(使用 scanf如何 接收数据)

#include <stdio.h>
int main()
{int num1 = 0;int num2 = 0;int sum = 0;printf("输入两个操作数:>");scanf("%d %d", &num1, &num2);  //int -- %d  float -- %f  double -- %lf  char -- %csum = num1 + num2;printf("sum = %d\n", sum);return 0; }

在C语言中,scanf函数可以用来输入longlong longshort类型的数据。下面是一些示例:

#include <stdio.h>int main() {long a;long long b;short c;printf("请输入一个long类型的数:");scanf("%ld", &a);printf("请输入一个long long类型的数:");scanf("%lld", &b);printf("请输入一个short类型的数:");scanf("%hd", &c);printf("你输入的long类型的数是:%ld\n", a);printf("你输入的long long类型的数是:%lld\n", b);printf("你输入的short类型的数是:%hd\n", c);return 0;
}

在这个代码中,%ld%lld%hd分别用于输入longlong longshort类型的数据。&符号是取地址运算符,它的作用是获取变量的内存地址。scanf函数需要这个地址来改变变量的值。注意,scanf函数的使用需要谨慎,因为它可能会导致缓冲区溢出等问题。在实际编程中,建议使用更安全的输入函数,如fgetssscanf


3.4 变量的作用域和生命周期

1)作用域:作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用
的。而限定这个名字的可用性的代码范围就是这个名字的作用域。
(1)局部变量的作用域是变量所在的局部范围。比如:{int a = 10;},{}内就是局部变量a的作用域。
(2)全局变量的作用域是整个工程。比如:int b =100;int main(){};,在main()函数{}之外也不在其他范围内的变量。

2)生命周期:变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
(1)局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。比如函数的形参。
(2)全局变量的生命周期是:整个程序的生命周期。程序结束,全局变量生命周期才结束。

3.5 常量

C语言中的常量和变量的定义的形式有所差异。

C语言中的常量分为以下以下几种:

1)字面常量

2)const 修饰的常变量 语法: const 变量类型

3)#define 定义的标识符常量 语法:#define 常量标识符 常量值

4)枚举常量 语法:enum 枚举常量名 {常量1, 常量2,…}; //这里记得加上分号!常量面前没有常量类型

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
//举例
enum Sex
{MALE,//MALE=2,  //可指定默认值,后面的值在2的基础上,递增+1FEMALE,SECRET
};  //这里要加上分号;
//括号中的MALE,FEMALE,SECRET是枚举常量int main()
{//字面常量演示3.14;//字面常量1000;//字面常量//const 修饰的常变量const float pai = 3.14f; //这里的pai是const修饰的 常变量//pai = 5.14;//是不能直接修改的!vs2017会提示表达式必须是可修改的左值//#define的标识符常量 演示#define MAX 100  //这里没有分号”;“printf("max = %d\n", MAX);  // 100//枚举常量演示printf("%d\n", MALE);  // 0printf("%d\n", FEMALE);  // 1printf("%d\n", SECRET);  // 2//注:枚举常量的默认是从0开始,依次向下递增1的return 0;
}

注(常变量):
上面例子上的 pai 被称为 const 修饰的常变量, const 修饰的常变量在C语言中只是在语法层面限制了变量 pai 不能直接被改变,但是 pai 本质上还是一个变量的,所以叫常变量。

4. 字符串+转义字符

4.1 字符串

"hello bit.\n"

这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。

#include <stdio.h>
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{char arr1[] = "bit";  char arr2[] = { 'b', 'i', 't' };char arr3[] = { 'b', 'i', 't', '\0' };  printf("%s\n", arr1);  //bit  默认包含了'\0'printf("%d\n", sizeof(arr1)/sizeof(char)); //4, 但是在计算长度的时候是包括的!!!printf("%s\n", arr2);  //bit烫烫烫烫蘠it 随机值//printf("%d\n", sizeof(arr2) / sizeof(char));printf("%s\n", arr3);  //bit 显示写出'\0'printf("%d\n", sizeof(arr3) / sizeof(char));  // 4  return 0;
}

4.2 转义字符

加入我们要在屏幕上打印一个目录: c:\code\test.c
我们该如何写代码?

#include <stdio.h>
int main()
{printf("c:\code\test.c\n");return 0; }
12345

实际上程序运行的结果是这样的:
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
这里就不得不提一下转义字符了。转义字符顾名思义就是转变意思。
下面看一些转义字符。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
int main()
{//问题1:在屏幕上打印一个单引号',怎么做?//问题2:在屏幕上打印一个字符串,字符串的内容是一个双引号“,怎么做?printf("%c\n", '\'');  //注意:单引号''括起来的对应%c,双引号括起来的对应%sprintf("%s\n", "\'"); printf("%s\n", "\"");printf("%c\n", '\"');return 0;
}
12345678910111213
//程序输出什么?
#include <stdio.h>
int main()
{//strlen()求字符串长度printf("%d\n", strlen("abcdef"));  // 6// \62被解析成一个转义字符printf("%d\n", strlen("c:\test\628\test.c"));  //14 = 11 + 3个转义字符printf("%c\n", '\62');  //2  ???return 0;
}

4.3字符指针和字符数组 和字符串的区别

在C语言中,字符指针、字符数组和字符串是三个不同的概念,虽然它们在许多情况下可以互换使用,但它们之间还是存在一些关键的区别123456。

字符指针是一个指针,它存储的是地址,而不是将字符串放到字符指针变量中123456。例如:

char *p = "Hello World!";

在这个例子中,p是一个字符指针,它指向的是字符串"Hello World!"的首地址123456。

字符数组是一个存储字符的数组,其长度是固定的,其中任何一个数组元素都可以为 null 字符。因此,字符数组不一定是字符串123456。例如:

char cArr[] = {'H', 'e', 'l', 'l', 'o'};

在这个例子中,cArr是一个字符数组,它包含5个字符,但并没有以null字符(‘\0’)结束,所以它不是一个字符串123456。

字符串,它必须以 null 字符结束,其后的字符不属于该字符串123456。字符串一定是字符数组,它是最后一个字符为 null 字符的字符数组123456。例如:

char sArr[] = "Hello";

在这个例子中,sArr是一个字符串,它包含5个字符和一个结束的null字符(‘\0’),所以它是一个字符串123456。

需要注意的是,字符串是一个只读型字符型数组,不能够通过指针更改字符串内部数据2。而字符数组可以修改其内部的数据123456。

总的来说,所有的字符串都是字符数组,但并非所有的字符数组都是字符串123456。这是因为字符串有一个额外的约束,即必须以null字符结束123456。这个约束使得字符串可以被一些特定的函数(如printfstrlen)用于特定的目的123456。

进阶

1 字符函数和字符串函数

**1.1 **strlen (重要)

函数用于获取字符串的长度:

size_t strlen ( const char * str );
1

字符串已 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(*不包含 ‘\0’* )。
参数指向的字符串必须要以 ‘\0’ 结束。
没有’\0’,的出来的结果就是随机值
注意函数的返回值为size_t,是无符号的( 易错 )
学会strlen函数的模拟实现

#include <stdio.h>int main()
{const char*str1 = "abcdef";const char*str2 = "bbb";if(strlen(str2)-strlen(str1)>0)  // 返回无符号的,就一直是>0{printf("str2>str1\n");} else{printf("srt1>str2\n");}return 0; 
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这段代码中的问题在于 strlen 函数返回的是 size_t 类型,这是一个无符号整数类型。当你从一个较大的无符号数中减去一个较小的无符号数时,结果仍然是一个无符号数。在你的例子中,strlen(str2) 是3,strlen(str1) 是6,所以 strlen(str2) - strlen(str1) 的结果是一个非常大的无符号数,而不是一个负数。这就是为什么 if(strlen(str2)-strlen(str1)>0) 总是为真的原因。

为了避免这个问题,你可以先将 strlen 的结果存储在 int 类型的变量中,然后再进行比较,就像你在第二段代码中所做的那样。这样,b - a 的结果就会是一个有符号的整数,可以正确地表示负数。这就是为什么第二段代码能够正确地比较两个字符串的长度。希望这个解释对你有所帮助!


#include <stdio.h>int main()
{const char*str1 = "abcdef";const char*str2 = "bbb";printf("%d\n", strlen(str1));  // 6printf("%d\n", strlen(str2));  // 3int a = strlen(str1);int b = strlen(str2);int c = b - a;if (c > 0){printf("str2>str1\n");}else{printf("srt1>str2\n");}return 0;
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.2 strcpy

函数用于复制字符串:

char * strcpy ( char * destination, const char * source );
1

Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
源字符串必须以 ‘\0’ 结束。
会将源字符串中的 ‘\0’ 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。

#include <stdio.h>
#include <string.h>int main() {char src[40];char dest[12];memset(dest, '\0', sizeof(dest));strcpy(src, "This is tutorialspoint.com");strcpy(dest, src);printf("Final copied string : %s\n", dest);return(0);
}
Final copied string : This is tutorialspoint.com
1.3 strcat

strcat是C语言中的一个库函数,用于将一个字符串追加到另一个字符串的末尾12345。其函数原型为:

char *strcat (char *dest, const char *src);

其中,dest是目标字符串,src是要追加的字符串4。

这个函数的工作原理是将src所指向的字符串追加到dest所指向的字符串的结尾13。因此,必须确保dest有足够的内存空间来容纳两个字符串,否则可能会导致溢出错误3。

以下是strcat函数的一个使用示例1:

#include <stdio.h>
#include <string.h>int main () {char src[50], dest[50];strcpy(src, "This is source");strcpy(dest, "This is destination");strcat(dest, src);printf("Final destination string: |%s|", dest);return(0);
}

在这个示例中,src字符串被追加到dest字符串的末尾,然后打印出最终的dest字符串。这将产生以下结果:

Final destination string: |This is destinationThis is source|

需要注意的是,strcat函数不会覆盖目标字符串1。而且,srcdest字符串中都必须包含字符’\0’,并且src字符串必须以’\0’结尾,否则追加过程无法顺利实现2。此外,目标字符串空间必须足够大(足够容纳追加字符串src的内容),并且目标空间必须可修改(前面不能加const并且不能说常量字符串)2。

字符串自己给自己追加,如何?会报错

/* strcat example */
#include <stdio.h>
#include <string.h>int main ()
{char str[80];strcpy(str,"these ");strcat(str,"strings ");strcat(str,"are ");strcat(str,"concatenated.");puts (str);return 0;
}
these strings are concatenated.
1.4 strcmp

strcmp 函数可以用来比较两个 C 字符串。在 C 语言中,字符串通常表示为字符数组,并以空字符 ‘\0’ 结尾。所以,如果你有两个字符数组,并且它们都以 ‘\0’ 结尾,那么你可以使用 strcmp 来比较它们。

但是,需要注意的是,strcmp 函数并不会比较两个数组的所有元素,它只会比较到遇到第一个 ‘\0’ 字符为止。所以,如果你的数组中包含 ‘\0’ 字符,或者你想比较的是非字符类型的数组,那么 strcmp 可能就不适用了。

在这种情况下,你可能需要使用其他函数,如 memcmp,它可以比较任意类型的数组,只需要指定要比较的字节数。希望这个解释对你有所帮助!

比较字符数组

当然可以。以下是一个使用 strcmp 来比较两个字符数组的例子:

#include <stdio.h>
#include <string.h>int main() {char str1[] = "Hello, world!";char str2[] = "Hello, world!";if (strcmp(str1, str2) == 0) {printf("The two strings are equal.\n");} else {printf("The two strings are not equal.\n");}return 0;
}

在这个例子中,我们定义了两个字符数组 str1str2,然后使用 strcmp 来比较这两个数组是否相等。如果 strcmp 返回 0,那么这两个字符串就是相等的。否则,它们就不相等。希望这个例子对你有所帮助!

The two strings are equal.
比较字符串

函数用于比较两个字符串:

int strcmp ( const char * str1, const char * str2 );
1

This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.

标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
那么如何判断两个字符串?

#include <stdio.h>
int main()
{const char*str1 = "abcdef";const char*str2 = "abcfed";printf("%d\n", strlen(str1));  // 6printf("%d\n", strlen(str2));  // 3int a = strcmp(str2, str1);printf("%d\n", a);return 0;
}
6
6
1
#include <stdio.h>
#include <string.h>int main() {char str1[15];char str2[15];int ret;strcpy(str1, "abcdef");strcpy(str2, "ABCDEF");ret = strcmp(str1, str2);if(ret < 0) {printf("str1 is less than str2\n");} else if(ret > 0) {printf("str2 is less than str1\n");} else {printf("str1 is equal to str2\n");}return(0);
}
str2 is less than str1
1.5 strncpy

函数用于复制指定数量的字符:

strncpy 是 C 语言中的一个内置函数,用于将一个字符串的前 n 个字符复制到另一个字符串1。它的声明如下:

char *strncpy(char *dest, const char *src, size_t n);

这里的参数是:

  • dest:我们想要复制到的目标字符串1。
  • src:我们要复制的源字符串1。
  • n:要复制的字符的最大数量1。

strncpy 函数的返回值是指向结果字符串 dest 的指针1。

如果 src 的长度小于 n,那么 dest 的剩余部分将用空字符 ‘\0’ 填充1。

以下是一个 strncpy 函数的使用示例:

#include <stdio.h>
#include <string.h>int main() {char src[40];char dest[12];memset(dest, '\0', sizeof(dest));strcpy(src, "This is tutorialspoint.com");strncpy(dest, src, 10);printf("Final copied string : %s\n", dest);return 0;
}

在这个例子中,我们将 src 字符串的前 10 个字符复制到 dest 字符串1。

Final copied string : This is tu
/* strncpy example */
#include <stdio.h>
#include <string.h>int main ()
{char str1[]= "To be or not to be";char str2[40];char str3[40];/* copy to sized buffer (overflow safe): */strncpy( str2, str1, sizeof(str2) );/* partial copy (only 5 chars): */strncpy( str3, str2, 5 );str3[5] = '\0';   /* null character manually added */puts (str1);puts (str2);puts (str3);return 0;
}
To be or not to be
To be or not to be
To be
1.6 strncat (连接)

strncat 是 C 语言中的一个内置函数,用于将一个字符串的前 n 个字符追加到另一个字符串的末尾1。它的声明如下:

char *strncat(char *dest, const char *src, size_t n);

这里的参数是:

  • dest:我们想要追加的字符串1。
  • src:我们要追加的 ‘n’ 个字符的字符串1。
  • n:要追加的字符的最大数量1。

strncat 函数的返回值是指向结果字符串 dest 的指针1。

以下是一个 strncat 函数的使用示例:

#include <stdio.h>
#include <string.h>int main() {char src[50], dest[50];strcpy(src,  "This is source");strcpy(dest, "This is destination");strncat(dest, src, 15);printf("Final destination string : |%s|\n", dest);return 0;
}

在这个例子中,我们将 src 字符串的前 15 个字符追加到 dest 字符串的末尾1。希望这个解释对你有所帮助!

Final destination string : |This is destinationThis is source|
1.7 strncmp (比较)

strncmp 是 C 语言中的一个内置函数,用于比较两个字符串的前 n 个字符1。它的声明如下:

int strncmp(const char *str1, const char *str2, size_t n);

这里的参数是:

  • str1:要比较的第一个字符串1。
  • str2:要比较的第二个字符串1。
  • n:要比较的字符的最大数量1。

strncmp 函数的返回值取决于比较的结果1:

  • 如果 str1 小于 str2,则返回值小于 01。
  • 如果 str1 大于 str2,则返回值大于 01。
  • 如果 str1 等于 str2,则返回值等于 01。

这里的 “大于” 和 “小于” 是指在比较字符串时,按照字符的 ASCII 值进行比较1。

以下是一个 strncmp 函数的使用示例:

#include <stdio.h>
#include <string.h>int main() {char str1[15];char str2[15];int ret;strcpy(str1, "abcdef");strcpy(str2, "ABCDEF");ret = strncmp(str1, str2, 4);if(ret < 0) {printf("str1 is less than str2\n");} else if(ret > 0) {printf("str2 is less than str1\n");} else {printf("str1 is equal to str2\n");}return 0;
}

在这个例子中,我们比较了 str1str2 的前 4 个字符。如果 str1 小于 str2,我们就打印 “str1 is less than str2”,如果 str1 大于 str2,我们就打印 “str2 is less than str1”,否则我们就打印 "str1 is equal to str2"1。

str2 is less than str1
1.8 strstr (查找)

函数用于在一个字符串中查找另一个字符串:

const char * strstr ( const char * str1, const char * str2 );char * strstr (       char * str1, const char * str2 );
12

Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.

/* strstr example */
#include <stdio.h>
#include <string.h>int main ()
{char str[] ="This is a simple string";char * pch;pch = strstr (str, "simple");strncpy (pch, "sample", 6);puts (str);return 0;
}
This is a sample string
#include <stdio.h>
#include <string.h>int main() {const char haystack[20] = "TutorialsPoint";const char needle[10] = "Point";char *ret;ret = strstr(haystack, needle);printf("The substring is: %s\n", ret);return(0);
}
The substring is: Point
1.9 strtok (分割)

函数用于分割字符串

char * strtok ( char * str, const char * sep );
1

sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针。

/* strtok example */
#include <stdio.h>
#include <string.h>int main ()
{char str[] ="- This, a sample string.";char * pch;printf ("Splitting string \"%s\" into tokens:\n",str);pch = strtok (str," ,.-");while (pch != NULL){printf ("%s\n",pch);pch = strtok (NULL, " ,.-");}return 0; 
}
Splitting string "- This, a sample string." into tokens:
This
a
sample
string

#include <stdio.h>
#include<cstring>
int main()
{const char *p = "zhangpengwei@bitedu.tech";const char* sep = ".@";char arr[30];char *str = NULL;strcpy(arr, p);//将数据拷贝一份,处理arr数组的内容for(str=strtok(arr, sep); str != NULL; str=strtok(NULL, sep)){printf("%s\n", str);}
}
zhangpengwei
bitedu
tech
#include <string.h>
#include <stdio.h>int main() {char str[80] = "This is - www.tutorialspoint.com - website";const char s[2] = "-";char *token;/* 获取第一个子字符串 */token = strtok(str, s);/* 继续获取其他的子字符串 */while( token != NULL ) {printf( " %s\n", token );token = strtok(NULL, s);}return(0);
}
 This iswww.tutorialspoint.comwebsite
1.10 strerror
char * strerror ( int errnum );
1

返回错误码,所对应的错误信息。

/* strerror example : error list */
#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件int main ()
{FILE * pFile;pFile = fopen ("unexist.ent","r");if (pFile == NULL)printf ("Error opening file unexist.ent: %s\n",strerror(errno));//errno: Last error numberreturn 0; 
}
Error opening file unexist.ent: No such file or directory
字符分类函数:

函数 如果他的参数符合下列条件就返回真
iscntrl 任何控制字符
isspace 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
isdigit 十进制数字 0~9
isxdigit 十六进制数字,包括所有十进制数字,小写字母af,大写字母AF
islower 小写字母a~z
isupper 大写字母A~Z
isalpha 字母az或AZ
isalnum 字母或者数字,az,AZ,0~9
ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph 任何图形字符
isprint 任何可打印字符,包括图形字符和空白字符

字符转换:
int tolower ( int c );
int toupper ( int c );/* isupper example */
#include <stdio.h>
#include <ctype.h>
int main ()
{int i=0;char str[]="Test String.\n";char c;while (str[i]){c=str[i];if (isupper(c)) c=tolower(c);putchar (c);i++;}return 0;
}
test string.

在C语言中,字符串是由字符组成的数组,以空字符(‘\0’)结束。while(str[i]) 这个循环会一直执行,直到遇到字符串 str 的结束标志 ‘\0’。在ASCII编码中,‘\0’ 对应的整数值是0,所以当 str[i] 是 ‘\0’ 时,while(str[i]) 的条件就不满足,循环就会结束。这就是 while(str[i]) 的含义。希望这个解释对你有所帮助!

1.11 memcpy
void * memcpy ( void * destination, const void * source, size_t num );
1

函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
这个函数在遇到 ‘\0’ 的时候并不会停下来。

memcpy 拷贝字符串和数组
/* memcpy example */
#include <stdio.h>
#include <string.h>struct {char name[40];int age;
} person, person_copy;int main ()
{char myname[] = "Pierre de Fermat";/* using memcpy to copy string: */memcpy ( person.name, myname, strlen(myname)+1 );person.age = 46;/* using memcpy to copy structure: */memcpy ( &person_copy, &person, sizeof(person) );printf ("person_copy: %s, %d \n", person_copy.name, person_copy.age );return 0; 
}
注意事项
不适用于重叠复制

如果source和destination有任何的重叠,复制的结果都是未定义的

#include <stdio.h>
#include <string.h>int main() {char str[] = "Hello, world!";// 尝试将 str 的前 5 个字符复制到 str 的第 3 个字符开始的位置memcpy(&str[2], str, 5);printf("%s\n", str);return 0;
}

在这个例子中,我们尝试将 str 的前 5 个字符(“Hello”)复制到 str 的第 3 个字符开始的位置。由于源地址和目标地址有重叠,所以复制的结果可能会出现错误。

当你运行这段代码时,可能会发现输出的字符串并不是你期望的 “HeHello, world!”,而是 “HeHeHo, world!”。这就是因为在复制过程中,源地址和目标地址的重叠部分被提前覆盖了。

为了避免这种情况,你可以使用 memmove 函数来代替 memcpymemmove 函数会正确处理源地址和目标地址的重叠,即使源地址和目标地址有重叠,它也能正确地复制数据。希望这个解释对你有所帮助!


为什么需要使用 memmove

“如果source和destination有任何的重叠,复制的结果都是未定义的”,这句话的意思是,如果你在使用 memcpy 函数时,源地址和目标地址有重叠的部分,那么复制的结果可能会出现错误。

这是因为 memcpy 在复制数据时,可能会先复制源地址的开始部分到目标地址,然后再复制源地址的结束部分。如果源地址和目标地址有重叠,那么在复制源地址的结束部分时,可能会覆盖已经复制到目标地址的数据,导致数据错误。

为了避免这种情况,你可以使用 memmove 函数来代替 memcpymemmove 函数会检查源地址和目标地址是否有重叠,如果有,它会从源地址的结束部分开始复制,这样就可以避免数据错误。希望这个解释对你有所帮助!


必须复制源字符串的 ‘\0’

需要注意的是,当使用 memcpy 复制字符串时,需要确保目标字符串有足够的空间来存储源字符串,并且在复制时要包括源字符串的结束符 ‘\0’。

在C语言中,字符串是由字符数组表示的,这个数组以特殊的字符 ‘\0’ 结束。‘\0’ 是一个空字符,用于标记字符串的结束。当我们使用字符串处理函数(如 printfstrcpy 等)时,这些函数会依赖 ‘\0’ 来确定字符串何时结束。

因此,当我们使用 memcpy 复制字符串时,我们需要包括源字符串的 ‘\0’ 结束符,以确保目标字符串也有一个正确的结束标记。如果不复制 ‘\0’,那么目标字符串可能就没有正确的结束标记,这可能会导致未定义的行为,比如打印字符串时打印出预期之外的字符,或者在处理字符串时访问到不应该访问的内存区域。

所以,为了确保字符串的正确处理,我们在复制字符串时通常会包括 ‘\0’ 结束符。希望这个解释对你有所帮助!

1.12 memmove

memmove是C语言中的一个库函数,用于在内存中移动数据1234。其函数原型为:

void *memmove (void *dest, const void *src, size_t n);

其中,dest是目标内存区域,src是源内存区域,n是要复制的字节数1234。

这个函数的工作原理是将src所指向的内存区域的n个字节复制到dest所指向的内存区域1234。如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中1234。复制后源区域的内容会被更改1。如果目标区域与源区域没有重叠,则和memcpy函数功能相同1。

以下是memmove函数的一个使用示例1:

#include <stdio.h>
#include <string.h>int main () {const char src[] = "newstring";char dest[] = "oldstring";printf("Before memmove dest = %s, src = %s\n", dest, src);memmove(dest, src, 9);printf("After memmove dest = %s, src = %s\n", dest, src);return 0;
}

在这个示例中,src字符串被复制到dest字符串的位置,然后打印出最终的dest字符串。这将产生以下结果:

Before memmove dest = oldstring, src = newstring
After memmove dest = newstring, src = newstring

需要注意的是,memmove函数不会覆盖目标字符串1。此外,目标字符串空间必须足够大(足够容纳追加字符串src的内容),并且目标空间必须可修改(前面不能加const并且不能说常量字符串)2。

和memcpy的差别 : 就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。

1.13 memcmp
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
1

比较从ptr1和ptr2指针开始的num个字节
返回值如下:
<0 the first byte that does not match in both memory blocks has a lower value in ptr1 than in ptr2 (if evaluated as unsigned char values)

0 the contents of both memory blocks are equal

0 the first byte that does not match in both memory blocks has a greater value in ptr1 than in ptr2 (if evaluated as unsigned char values)

/* memcmp example */
#include <stdio.h>
#include <string.h>int main()
{char buffer1[] = "DWgaOtP12df0";char buffer2[] = "DWGAOTP12DF0";int n;n = memcmp(buffer1, buffer2, sizeof(buffer1));if (n > 0) {printf("'%s' is greater than '%s'.\n", buffer1, buffer2);}else if (n < 0) {printf("'%s' is less than '%s'.\n", buffer1, buffer2);}else {printf("'%s' is the same as '%s'.\n", buffer1, buffer2);}return 0;
}
memcmp 比较数组
#include <stdio.h>
#include <string.h>int main() {int arr1[] = {1, 2, 3, 4, 5};int arr2[] = {1, 2, 3, 4, 5};if (memcmp(arr1, arr2, sizeof(arr1)) == 0) {printf("The two arrays are equal.\n");} else {printf("The two arrays are not equal.\n");}return 0;
}
memcmp 比较结构体
#include <stdio.h>
#include <string.h>typedef struct {int id;char name[50];
} Person;int main() {Person p1 = {123, "Alice"};Person p2 = {123, "Alice"};if (memcmp(&p1, &p2, sizeof(Person)) == 0) {printf("The two persons are equal.\n");} else {printf("The two persons are not equal.\n");}return 0;
}
strcmp 和 memcmp 的区别

strcmpmemcmp 是两个用于比较数据的 C 语言函数,但它们的用途和行为有所不同1。

  • strcmp 是用于比较两个以空字符 ‘\0’ 结束的 C 字符串1。它会从两个字符串的开始处开始比较,直到遇到不同的字符或者遇到空字符 '\0’1。如果两个字符串在遇到空字符 ‘\0’ 之前都相同,那么 strcmp 就会返回 0,表示两个字符串相等1。
  • memcmp 则是用于比较两个指定长度的字节序列1。它并不关心数据是否以空字符 ‘\0’ 结束,只会简单地比较指定数量的字节1。因此,memcmp 可以用于比较任何类型的数据,包括字符串、结构体、数组等1。

总的来说,strcmpmemcmp 的主要区别在于,strcmp 是用于比较字符串的,而 memcmp 是用于比较任意类型的数据的1。希望这个解释对你有所帮助!

2. 库函数的模拟实现 (暂略)

2.1 模拟实现strlen

方式1:

//计数器方式
int my_strlen(const char * str) 
{int count = 0;while(*str){count++;str++;}return count; 
}

方式2:

//不能创建临时变量计数器
int my_strlen(const char * str) 
{if(*str == '\0')return 0;elsereturn 1+my_strlen(str+1);//递归
}

方式3:

//指针-指针的方式
int my_strlen(char *s) 
{char *p = s;while(*p != ‘\0)p++;return p-s; 
}
2.2 模拟实现strcpy

参考代码:

//1.参数顺序
//2.函数的功能,停止条件
//3.assert
//4.const修饰指针
//5.函数返回值
//6.题目出自《高质量C/C++编程》书籍最后的试题部分char *my_strcpy(char *dest, const char*src)
{ char *ret = dest;//这里传进来的是字符串的首地址,即指针assert(dest != NULL);assert(src != NULL);while((*dest++ = *src++)){;}return ret; 
}
2.3 模拟实现strcat

参考代码:

char *my_strcat(char *dest, const char*src) 
{char *ret = dest;//同上,记住 不能返回局部变量的地址assert(dest != NULL);assert(src != NULL);while(*dest){dest++;}while((*dest++ = *src++)){;}return ret; 
}
2.4 模拟实现strstr
char *strstr (const char * str1, const char * str2) 
{char *cp = (char *) str1;char *s1, *s2;if ( !*str2 ){return((char *)str1);}while (*cp){s1 = cp;s2 = (char *) str2;while ( *s1 && *s2 && !(*s1-*s2) ){s1++, s2++;}if (!*s2)return(cp);cp++;}return(NULL);
}

/stackoverflow.com/questions/13095513/what-is-the-difference-between-memcmp-strcmp-and-strncmp-in-c)1。希望这个解释对你有所帮助!

2. 库函数的模拟实现 (暂略)

2.1 模拟实现strlen

方式1:

//计数器方式
int my_strlen(const char * str) 
{int count = 0;while(*str){count++;str++;}return count; 
}

方式2:

//不能创建临时变量计数器
int my_strlen(const char * str) 
{if(*str == '\0')return 0;elsereturn 1+my_strlen(str+1);//递归
}

方式3:

//指针-指针的方式
int my_strlen(char *s) 
{char *p = s;while(*p != ‘\0)p++;return p-s; 
}
2.2 模拟实现strcpy

参考代码:

//1.参数顺序
//2.函数的功能,停止条件
//3.assert
//4.const修饰指针
//5.函数返回值
//6.题目出自《高质量C/C++编程》书籍最后的试题部分char *my_strcpy(char *dest, const char*src)
{ char *ret = dest;//这里传进来的是字符串的首地址,即指针assert(dest != NULL);assert(src != NULL);while((*dest++ = *src++)){;}return ret; 
}
2.3 模拟实现strcat

参考代码:

char *my_strcat(char *dest, const char*src) 
{char *ret = dest;//同上,记住 不能返回局部变量的地址assert(dest != NULL);assert(src != NULL);while(*dest){dest++;}while((*dest++ = *src++)){;}return ret; 
}
2.4 模拟实现strstr
char *strstr (const char * str1, const char * str2) 
{char *cp = (char *) str1;char *s1, *s2;if ( !*str2 ){return((char *)str1);}while (*cp){s1 = cp;s2 = (char *) str2;while ( *s1 && *s2 && !(*s1-*s2) ){s1++, s2++;}if (!*s2)return(cp);cp++;}return(NULL);
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com