深入理解C语言(2):字符、字符串与内存函数

标头风景图片


  • 文章主题:字符、字符串与内存函数🌏
  • 所属专栏:深入理解C语言📔
  • 作者简介:更新有关深入理解C语言知识的博主一枚,记录分享自己对C语言的深入解读。😆
  • 个人主页:[₽]的个人主页🏄🌊

前言

字符函数属于库文件ctype.h,而字符串与内存函数属于库文件string.h,那么它们分别具有什么样的功能呢?我们又能否在C语言中对其进行模拟呢?下面是我有关这些函数的介绍以及对其中的一些函数进行的模拟。

函数介绍

一. 字符函数

1. 字符分类函数

函数声明返回真的参数条件
int iscntrl ( int c );任何控制字符
int isspace ( int c );’ ‘(空白字符/空格), ‘\f’(换页), ‘\n’(换行), ‘\t’(制表符), ‘\v’(垂直制表符) , ‘\r’(回车)
int isdigit ( int c );十进制数字 ‘0’-‘9’
int isxdigit ( int c );十六进制数字,包括所有十进制数字,小写字母 ‘a’-‘f’,大写字母 ‘A’-‘F’
int islower ( int c );小写字母 ‘a’-‘z’
int isupper ( int c );大写字母 ‘A’-‘Z’
int isalpha ( int c );字母 ‘A’-‘Z’ ‘a’-‘z’
int isalnum ( int c );字母 ‘A’-‘Z’ ‘a’-‘z’ ‘0’-‘9’
int ispunct ( int c );标点符号,任何不属于数字或者字母的图形字符(可打印)
int isgraph ( int c );任何图形字符
int isprint ( int c );任何可打印字符,包括图形字符和空白字符

2. 字符转换函数

函数效果
int tolower ( int c );大写字母转成小写字母返回,小写字母仍以小写字母返回
int toupper ( int c );小写字母转成大写字母返回,大写字母仍以大写字母返回

二. 字符串函数

1. 求字符串长度

strlen
size_t strlen ( const void* str );
  • 字符串以'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0')。
  • 参数指向的字符串必须要以'\0'结束。
  • 注意函数的返回值为size_t,是无符号的。(易错
  • 学会strlen函数的模拟实现。
例:
/* strlen example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char szInput[256];
  printf ("Enter a sentence: ");
  gets (szInput);
  printf ("The sentence entered is %u characters long.\n",(unsigned)strlen(szInput));
  return 0;
}
输出:
Enter sentence: just testing
The sentence entered is 12 characters long.

2. 长度不受限制的字符串函数

strcpy
char* strlen ( char* destination, const char* source );
  • source指向的 C 字符串复制到destination指向的数组中,包括'\0'(并在该点处停止)。

  • 为避免溢出,destination指向的数组的大小应足够长,以包含与source相同的 C 字符串(包括'\0'),并且不应在内存中与source重叠。

例:
/* strcpy example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str1[]="Sample string";
  char str2[40];
  char str3[40];
  strcpy (str2,str1);
  strcpy (str3,"copy successful");
  printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
  return 0;
}
输出:
str1: Sample string
str2: Sample string
str3: copy successful

strcat
char* strcat ( char* destination, const char* source );
  • source字符串的内容衔接到destination字符串之后。destination 中的'\0'被 source 的第一个字符覆盖,并且'\0'会包含在由destination中两者的串联形成的新字符串的末尾。
例:
/* strcpy example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str1[]="Sample string";
  char str2[40];
  char str3[40];
  strcpy (str2,str1);
  strcpy (str3,"copy successful");
  printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
  return 0;
}
输出:
these strings are concatenated.

strcmp
int strcmp ( const char* str1, const char* str2 );
  • 将 C 字符串 str1 与 C 字符串 str2 进行比较。

  • 此函数开始相同位置对应比较每个字符串的字符。如果它们彼此相等,则继续往下比较,直到字符不同或达到'\0'为止。

例:
/* strcmp example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char key[] = "apple";
  char buffer[80];
  do {
     printf ("Guess my favorite fruit? ");
     fflush (stdout);
     scanf ("%79s",buffer);
  } while (strcmp (key,buffer) != 0);
  puts ("Correct answer!");
  return 0;
}
输出:
Guess my favourite fruit? orange
Guess my favourite fruit? apple
Correct answer!

3. 长度受限制的字符串函数

strncpy
char* strncpy ( char* destination, const char* source, size_t num );
  • source的前 num 个字符复制到destination。如果在复制 num 个字符之前找到source C 字符串的末尾(由'\0'表示),则destination将用0(即0所代表的'\0')填充,直到总共写入 num 个字符。

  • 如果source的长度大于 num,则不会在目标末尾隐式追加'\0'。因此,在这种情况下,destination不一定能被视为以'\0'结尾的 C 字符串(这样读取它会溢出)。

  • destinationsource不得重叠(重叠时更安全的替代方案为Memmove)。

例:
/* 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 

strncat
char* strncat ( char* destination, const char* source, size_t num );
  • source的前 num 个字符衔接到destination之后,外加一个'\0'

  • 如果source中 C 字符串的长度小于 num,则仅复制'\0'之前的内容。

例:
/* strncat example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str1[20];
  char str2[20];
  strcpy (str1,"To be ");
  strcpy (str2,"or not to be");
  strncat (str1, str2, 6);
  puts (str1);
  return 0;
}
输出:
To be or not

strncmp
int strncmp ( const char* str1, const char* str2, size_t num );
  • 将 C 字符串 str1 的字符数与 C 字符串 str2 的字符数进行比较。
  • 此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续往下比较,直到字符不同或达到'\0',或直到两个字符串中的num个字符相同。
例:
/* strncmp example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
  int n;
  puts ("Looking for R2 astromech droids...");
  for (n=0 ; n<3 ; n++)
    if (strncmp (str[n],"R2xx",2) == 0)
    {
      printf ("found %s\n",str[n]);
    }
  return 0;
}
输出:
Looking for R2 astromech droids...
found R2D2
found R2A6

4. 其他

strstr
const char* strstr ( const char* str1, const char* str2 );
  • 返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回一个NULL指针。

  • 匹配过程不包括'\0',但匹配会停止到此为止。

例:
/* strstr example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] ="This is a simple string";
  char * pch;
  pch = strstr (str,"simple");
  if (pch != NULL)
    strncpy (pch,"sample",6);
  puts (str);
  return 0;
}
输出:
This is a sample string

strtok
char* strtok ( char* str, const char* delimiters );
  • 对此函数的一系列调用将 str 拆分为标记,这些标记是由分隔符中的任何字符分隔的连续字符序列。

  • 在第一次调用时,该函数需要一个 C 字符串作为 str 的参数,str 的第一个字符用作扫描delimiters的起始位置。在后续调用中,该函数需要一个NULL指针,并使用最后一个标记末尾之后的位置作为扫描的新起始位置。

  • 为了确定标记的开头和结尾,该函数首先从起始位置扫描delimiters中未包含的第一个字符(该字符成为标记的开头)。然后从标记的开头开始扫描分隔符中包含的第一个字符,该字符成为标记的末尾。如果找到'\0',扫描也会停止。

  • delimiters的这一末尾会自动替换为'\0',并且delimiters的开头由函数返回。

  • 在对 strtok 的调用中找到 str 的'\0'后,对此函数的所有后续调用(以NULL指针作为第一个参数)将返回 null 指针。

  • 找到最后一个delimiters的点由要在下一次调用中使用的函数在内部保存(不需要特定的库实现来避免数据争用)。

例:
/* 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

strerror
char* strerror ( int errnum );
  • 解释 errnum 的值,生成一个字符串,其中包含一条描述错误条件的消息,就像由库的函数设置为 errno 一样。

  • 返回的指针指向静态分配的字符串,程序不得修改该字符串。对此函数的进一步调用可能会覆盖其内容(不需要特定的库实现来避免数据争用)。

  • strerror 生成的错误字符串可能特定于每个系统和库实现。

例:
/* 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));
  return 0;
}
输出:
Error opening file unexist.ent: No such file or directory

perror(与字符串函数strerror效果相似的打印函数,属于<stdio.h>(标准输入输出库))
void perror ( const char* str );
  • 将 errno 的值解释为错误消息,并将其打印到 stderr(标准错误输出流,通常是控制台),可以选择在其前面加上 str 中指定的自定义消息。

  • errno 是一个整数变量,其值描述调用库函数生成的错误条件或诊断信息(C 标准库的任何函数都可以为 errno 设置值,即使此引用中未明确指定,即使没有发生错误),有关详细信息,请参阅 errno。

  • perror 生成的错误消息与平台相关。

  • 如果参数 str 不是 null 指针,则打印 str,后跟冒号 : 和空格。然后,无论 str 是否为 null 指针,都会打印生成的错误说明,后跟换行符 '\n'

  • perror 应该在产生错误后立即调用,否则可能会被调用其他函数覆盖。

例:
/* perror example */
#include <stdio.h>

int main ()
{
  FILE * pFile;
  pFile=fopen ("unexist.ent","rb");
  if (pFile==NULL)
    perror ("The following error occurred");
  else
    fclose (pFile);
  return 0;
}
输出:
The following error occurred: No such file or directory

三. 内存函数

memcpy

void* memcpy ( void* destination, const void* source, size_t num );
  • 将 num 字节的值从source指向的位置直接复制到destination指向的内存块。

  • source指针和destination指针指向的对象的基础类型与此函数无关;结果是数据的二进制副本。

  • 该函数不检查source中的任何'\0'——它始终准确复制 num 个字节。

  • 为避免溢出,destination参数和source参数指向的数组的大小应至少为 num 个字节,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)

例:
/* 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;
}
输出:
person_copy: Pierre de Fermat, 46

memmove

void* memmove ( void* destination, const void* source, size_t num );
  • 将 num 字节的值从source指向的位置复制到destination指向的内存块。复制就像使用中间缓冲区一样进行,允许destinationsource重叠。

  • source指针和destination指针所指向的对象的基础类型与此函数无关;结果是数据的二进制副本。

  • 该函数不检查source中的任何'\0'——它始终准确复制 num 个字节。

  • 为避免溢出,destination参数和source参数所指向的数组的大小应至少为 num 个字节。

例:
/* memmove example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] = "memmove can be very useful......";
  memmove (str+20,str+15,11);
  puts (str);
  return 0;
}
输出:
memmove can be very very useful.

memcmp

int memcmp ( const void* ptr1, const void* ptr2, size_t num );
  • 将 ptr1 指向的内存块的第一个字节与 ptr2 指向的第一个 num 字节进行比较,如果它们都匹配,则返回零,或者返回一个不同于零的值,如果它们不匹配,则表示哪个值更大。 请注意,与 strcmp 不同,该函数在找到 null 字符后不会停止比较。
例:
/* 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;
}
输出:
'DWgaOtP12df0' is greater than 'DWGAOTP12DF0'.

函数模拟实现

字符串函数

my_strlen

#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char* str)
{
	assert(str);
	int i = 0;
	while (str[i])//计数器,到'\0'时退出循环,停止计数
		i++;
	return i;
}
int main()
{
	char str[100] = { 0 };
	scanf("%s", str);
	printf("lens: %zd", my_strlen(str));
	return 0;
}

my_strcpy

#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);
	int i = 0;
	while (dest[i] = src[i++])//复制到'\0'时,条件判断为0,跳出while循环,复制动作停止
		;
	return dest;
}
int main()
{
	char str1[100] = { 0 }, str2[100] = { 0 };
	scanf("%s%s", str1, str2);
	printf("cpyed: %s", my_strcpy(str1, str2));
	return 0;
}

my_strcmp

#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	int i = 0;
	while (str1[i] || str2[i])//c1=c2且不是均为'\0'时进入循环
	{
		if (str1[i] - str2[i])//如果对应字符不相同的话,则返回它们的差值
		                      //(可保证c1>c2时返回>0;c1<c2时返回<0)
			return str1[i] - str2[i];
		i++;
	}
	return 0;//c1=c2且均为'\0'则终止循环,两字符串相同返回0
}
int main()
{
	char str1[100] = { 0 }, str2[100] = { 0 };
	scanf("%s%s", str1, str2);
	printf("%d", my_strcmp(str1, str2));
	return 0;
}

my_strcat

#include <stdio.h>
#include <string.h>
#include <assert.h>
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* cat = dest + strlen(dest), i = 0;//定义及赋值衔接处的地址变量
	while (cat[i] = src[i++])//如果没到'\0'就会继续赋值
		;
	return dest;//返回赋值后的字符串地址
}
int main()
{
	char str[20] = { 0 };
	strcpy(str, "Hello ");
	my_strcat(str, "bit!");
	puts(str);
	return 0;
}

my_strstr

#include <stdio.h>
#include <assert.h>
const char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	if (str2[0] == '\0')
		return str1;
	const char* cp = str1;//记录原字符串中的子字符串比较位置
	const char* s1;//str1单位字符比较指针
	const char* s2;//str2单位字符比较指针
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1&&*s2&&*s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return cp;
		cp++;
	}
	return NULL;
}
int main()
{
	char str1[] = "abbbcdef", str2[] = "bcd";
	if (my_strstr(str1, str2) == NULL)
		printf("NULL");
	else
		printf("%s", my_strstr(str1, str2));
	return 0;
}

my_strncpy

#include <stdio.h>
#include <string.h>
#include <assert.h>
char* strncpy(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	int lens = strlen(src);
	for (int i = 0; i < num; i++)
	{
		if (i < lens)
			dest[i] = src[i];
		else//num大于lens时,在dest中填充0
			dest[i] = 0;
	}
	return dest;
}
int main()
{
	char str1[] = "abcdefghijk", str2[] = "Wang";
	printf("%s", strncpy(str1, str2, 7));
	return 0;
}

my_strncat

#include <stdio.h>
#include <assert.h>
char* my_strncat(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	int lens = strlen(dest);
	char* pc = dest + lens;
	int i = 0;
	for (i = 0; i < num; i++)
	{
		if (i == lens)//检测到赋值到'\0'时, 立马停止赋值
			break;
		pc[i] = src[i];
	}
	pc[i] = '\0';//衔接完之后的字符串追加一个'\0'作为字符串的结尾
	return dest;
}
int main()
{
	char str1[10] = "abc", str2[] = "zzzzz";
	printf("%s", my_strncat(str1, str2, 4));
	return 0;
}

内存函数

my_memmove

#include <stdio.h>
#include <assert.h>
void* memmove(void* dest, const void* src, size_t num)
{
	if (dest < src)//前->后赋值
	{
		for (int i = 0; i < num; i++)
			((char*)dest)[i] = ((const char*)src)[i];
	}
	else//后->前赋值
	{
		for (int i = num - 1; i >= 0; i--)
			((char*)dest)[i] = ((const char*)src)[i];
	}
	return dest;
}
int main()
{
	char str[] = "abcdef";
	printf("%s", memmove(str, str + 3, 3));
	return 0;
}

my_memcpy

#include <stdio.h>
#include <assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	char* cp = dest;
	for (int i = 0; i < num; i++)
		*(cp + i) = *(((const char*)src)+i);//通过强转为char类型来进行以字节为单位的循环复制内存结构
	return dest;
}
struct
{
	char name[15];
	int age;
}person, person_copy;
int main()
{
	char myname[] = "Petter";
	person.age = 19;
	my_memcpy(person.name, myname, sizeof(myname));
	my_memcpy(&person_copy, &person, sizeof(person));
	printf("person_copy: %s, %d\n", person_copy.name, person_copy.age);
	return 0;
}

结语

以上就是我对字符、字符串与内存函数的介绍以及对其中一些的函数模拟,希望你能够对这些函数有更加深刻的理解。设计逻辑上有所不足的欢迎评论区积极进行指正,让我们共同成长,一起进步!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/340461.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jdk17新特性——Switch表达式增强

目录 一、Switch表达式增强示例一1.1、传统的方式 case中变量赋值示例1.2、jdk17 case中变量赋值示例 二、Switch表达式增强示例二2.1、传统的方式 case中值匹配多个示例2.2、jdk17 case中值匹配多个示例 三、Switch表达式增强示例三3.1、传统的方式 case中需要多行业务代码示例…

React-Native项目矢量图标库(react-native-vector-icons)

系列文章目录 React-Native环境搭建&#xff08;IOS&#xff09;React-Native项目 — 关于IOS知识储备React-Native项目工程搭建&#xff08;开发模板搭建&#xff09;React-Native项目矢量图标库&#xff08;react-native-vector-icons&#xff09; 目录 系列文章目录前言一、…

斐波那契查找

斐波那契查找 概述步骤代码示例输出结果 概述 斐波那契查找是一种基于斐波那契数列的查找算法&#xff0c;用于在有序数组中查找目标元素的位置。与二分查找类似&#xff0c;斐波那契查找也是一种分治算法&#xff0c;它通过比较目标值与数组的中间元素来确定下一步的查找范围…

C++版QT:鼠标事件

鼠标常用的事件可以说有一下几种&#xff1a;鼠标按下、鼠标移动、鼠标移动、鼠标双击和鼠标滚轮事件。 当你想使用他们&#xff0c;需要包含头文件&#xff1a;#include <QMouseEvent> 需要对鼠标事件进行处理时&#xff0c;通常要重新实现以下几个鼠标事件处理函数&a…

设备对象(DEVICE_OBJECT)

设备对象(DEVICE_OBJECT) 每个驱动程序会创建一个或多个设备对象&#xff0c;用DEVICE_OBJECT数据结构表示。每个设备对象都会有一个指针指向下一个设备对象&#xff0c;因此就形成一个设备链。设备对象链的第一个设备是由DRIVER_OBJECT结构体中指明的。设备对象保存设…

UI自动化中的option选项配置

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

《WebKit 技术内幕》学习之七(2): 渲染基础

2 网页层次和RenderLayer树 2.1 层次和RenderLayer对象 前面章节介绍了网页的层次结构&#xff0c;也就是说网页是可以分层的&#xff0c;这有两点原因&#xff0c;一是为了方便网页开发者开发网页并设置网页的层次&#xff0c;二是为了WebKit处理上的便利&#xff0c;也就是…

C++中命名空间、缺省参数、函数重载

目录 1.命名空间 2.缺省参数 3.函数重载 1.命名空间 在C中定义命名空间我们需要用到namespace关键字&#xff0c;后面跟上命名空间的名字&#xff0c;结构框架有点类似结构体&#xff08;如图所示&#xff09; 上面的代码我一一进行讲解&#xff1a; 1.我们先来说第三行和main函…

开源堡垒机JumpServer本地安装并配置公网访问地址

文章目录 前言1. 安装Jump server2. 本地访问jump server3. 安装 cpolar内网穿透软件4. 配置Jump server公网访问地址5. 公网远程访问Jump server6. 固定Jump server公网地址 前言 JumpServer 是广受欢迎的开源堡垒机&#xff0c;是符合 4A 规范的专业运维安全审计系统。JumpS…

基于CLIP4Clip的DRL的WTI模块实现

关于DRL的WTI模块&#xff1a; Weighted Token-wise Interaction&#xff1a; 直觉上&#xff0c;并非所有的单词和视频帧都同等重要。我们提供一种自适应方法&#xff0c;来调整每个标记的权重大小&#xff1a; 注&#xff1a;其中两个f函数都是MLP和softmax构成。 WTI的算…

使用STM32的SPI接口实现与外部传感器的数据交互

一、引言 外部传感器是嵌入式系统中常用的外设&#xff0c;用于检测环境参数、采集数据等。通过STM32微控制器的SPI接口&#xff0c;可以与外部传感器进行数据交互&#xff0c;从而实现数据的采集和控制。本文将介绍如何使用STM32的SPI接口实现与外部传感器的数据交互&#xff…

云计算任务调度仿真05

今天再分享一个新的调度框架deeprm 本项目基于hongzimao/deeprm&#xff0c;原作者还著有论文Resource Management with Deep Reinforcement Learning 。 这个框架研究的也蛮多的&#xff0c;我在一篇博士论文中也看到了基于此的研究工作&#xff0c;但是论文题目忘记了。 运…

【C++】入门(一)

前言&#xff1a; 本篇博客将带大家认识C&#xff0c;熟悉基本语法 文章目录 认识CC的诞生与发展C 在行业中的运用 一、命名空间1.1 命名空间的定义1.2 命名空间的使用1.3 命名空间的访问 二、C输入&输出输出操作符 <<输入操作符 >>换行符和刷新输出缓冲区关键…

如何在CentOS8使用宝塔面板本地部署Typecho个人网站并实现公网访问【内网穿透】

文章目录 前言1. 安装环境2. 下载Typecho3. 创建站点4. 访问Typecho5. 安装cpolar6. 远程访问Typecho7. 固定远程访问地址8. 配置typecho 前言 Typecho是由type和echo两个词合成的&#xff0c;来自于开发团队的头脑风暴。Typecho基于PHP5开发&#xff0c;支持多种数据库&#…

vmware 安装Rocky-9.3系统

安装系统截图 安装完成&#xff0c;启动 查看版本和内核 开启远程登陆授权 1、编辑配置文件 #提升权限&#xff0c;输入su,并输入密码 su #编辑ssh文件开启root远程登陆 vi /etc/ssh/sshd_config找到以下内容&#xff1a;#PermitRootLogin prohibit-password 添加&#xff1a…

C#winform上位机开发学习笔记5-串口助手的定时发送功能添加

1.功能描述 选择自动发送功能后&#xff0c;按照设定的发送时间发送发送框中的信息数据&#xff0c;设定时间可以手动输入&#xff0c;当手动输入信息无效&#xff08;非数字&#xff09;时&#xff0c;系统弹出错误提示&#xff0c;并将其设置为默认定时时间。 2.代码部分 步…

【MySQL进阶】视图_存储过程_存储函数_触发器

文章目录 视图基本介绍视图操作视图创建视图查询视图修改视图删除 存储过程基本介绍基本操作存储语法变量IF语句参数传递CASEWHILEREPEATLOOP游标 存储函数触发器基本介绍基本操作 总结 视图 基本介绍 视图概念&#xff1a;视图是一种虚拟存在的数据表&#xff0c;这个虚拟的表…

【Linux对磁盘进行清理、重建、配置文件系统和挂载,进行系统存储管理调整存储结构】

Linux 调整存储结构 前言一、查看磁盘和分区列表二、创建 ext4 文件系统&#xff0c;即&#xff1a;格式化分区为ext4文件系统。1.使用命令 mkfs.ext4 (make file system)报错如下&#xff1a;解决办法1&#xff1a;&#xff08;经测试&#xff0c;不采用&#xff09;X解决办法…

Docker-Jenkins编译android-app的两种方案

Docker-Jenkins编译android-app的两种方案 android开发使用jenkins编译&#xff0c;自动集成修改点/自动命名/自动备份&#xff0c;将修改的apk发布到测试服务器发布网盘&#xff0c;而不需要用通讯工具传来传去。 jenkins用在互联网开发编译比较常见&#xff0c;如果android开…

电力电子技术

文章目录 5 直流直流变流电路5.0 简介5.1 基本斩波电路5.1.1 降压斩波电路 Buck Chopper5.1.1.1 小纹波近似 5.1.2升压斩波电路 11 DC-DC 变换器数字控制11.1 基于单片机控制11.2 基于 DSP 控制11.3 基于 FPGA 控制 12 多相交错并联拓扑结构12.1 多相交错并联12.1 多相交错并联…