C++ 配置文件类(linux与window可跨平台使用)

log4cpp 编译与使用 一 引言 Log4cpp是个开源的日志跟踪项目,它是运行在c++环境下的。 由于Java的日志处理跟踪项目log4j的效果很好,所以把它移植到c++,并保持了API上的一致。其类似的支持库还包括C(log4c)、python(log4p)、c#(log4net)等。因为之前使用过log4net,相比之下,感觉log4cpp的使用还是复杂一些。 目前接触到的东西不多,主要使用Log4cpp 阅读详情

编写程序一直在用的配置文件类,感觉很好用,做一下总结:

.h

class inirw{
public:
	inirw(const char *filename){iniFileLoad(filename);};
	~inirw(){iniFileFree();};
	//加载ini文件至内存

	char gFilename[SIZE_FILENAME];
	char *gBuffer;
	int gBuflen;
	int iniFileLoad(const char *filename);
	//释放ini文件所占资源
	void iniFileFree();
	int FindSection(const char *section, char **sect1, char **sect2, char **cont1, char **cont2, char **nextsect);
	//获取字符串,不带引号
	int iniGetString(const char *section, const char *key, char *value, int size, const char *defvalue);
	//获取整数值
	int iniGetInt(const char *section, const char *key, int defvalue);
	//获取浮点数
	double iniGetDouble(const char *section, const char *key, double defvalue);
	int iniGetValue(const char *section, const char *key, char *value, int maxlen, const char *defvalue);
	//设置字符串:若value为NULL,则删除该key所在行,包括注释
	int iniSetString(const char *section, const char *key, const char *value);
	//设置整数值:base取值10、16、8,分别表示10、16、8进制,缺省为10进制
	int iniSetInt(const char *section, const char *key, int value, int base=10);
//	int iniGetIP(const char *section, const char *key, BasicHashTable *hashtable, int size, const char *defvalue);
};
#endif
.cpp
文中加注释的一部分是我当初用来获取字段相同配置的函数,当初要配置一个黑白名单IP列表而写的,因为牵扯到别的类,在此就加上注释
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "inirw.h"
//#include "strDup.hh"




#define fmin(x, y)		(x <= y) ? x : y


typedef enum _ELineType_ {
    LINE_IDLE,		//未处理行
	LINE_ERROR,		//错误行
	LINE_EMPTY,		//空白行或注释行
	LINE_SECTION,	//节定义行
	LINE_VALUE		//值定义行
} ELineType ;








//去除串首尾空格,原串被改写
 char *StrStrip(char *s)
{
	size_t size;
	char *p1, *p2;


	size = strlen(s);
	if (!size)
		return s;


	p2 = s + size - 1;


	while ((p2 >= s) && isspace(*p2))
		p2 --;
	*(p2 + 1) = '\0';


	p1 = s;
	while (*p1 && isspace(*p1))
		p1 ++;
	if (s != p1)
		memmove(s, p1, p2 - p1 + 2);
	return s;
}




//不区分大小写比较字符串
 int StriCmp(const char *s1, const char *s2)
{
	int ch1, ch2;
	do
	{
		ch1 = (unsigned char)*(s1++);
		if ((ch1 >= 'A') && (ch1 <= 'Z'))
			ch1 += 0x20;


		ch2 = (unsigned char)*(s2++);
		if ((ch2 >= 'A') && (ch2 <= 'Z'))
			ch2 += 0x20;
	} while ( ch1 && (ch1 == ch2) );
	return(ch1 - ch2);
}




//取一行
//输入:数据区(指针及长度)
//输出:行类型、有效内容串(去首尾空格)、注释首、注释尾、下一行首(行尾与下一行首间为换行符)
//      有效内容位置为[buf, rem1)
 int GetLine(char *buf, int buflen, char *content, char **rem1, char **rem2, char **nextline)
{
	char *cont1, *cont2;
	int cntblank, cntCR, cntLF;		//连续空格、换行符数量
	char isQuot1, isQuot2;			//引号
	int i;
	char *p;


	//首先断行断注释,支持如下换行符:\r、\n、\r\n、\n\r
	cntblank = 0;
	cntCR = cntLF = 0;
	isQuot1 = isQuot2 = 0;
	cont1 = *rem1 = 0;
	content[0] = 0;
	for (i = 0, p = buf; i < buflen; i ++, p ++)
	{
		if (*p == 0) {
			p ++;
			break;
		}
		//2个CR或LF,行结束
		if (cntCR == 2 || cntLF == 2) {
			p --;	//回溯1
			break;
		}
		//CR或LF各1个之后任意字符,行结束
		if (cntCR + cntLF >= 2) {
			break;
		}
		//CR或LF之后出现其它字符,行结束
		if ((cntCR || cntLF) && *p != '\r' && *p != '\n')
			break;


		switch (*p) {
		case '\r':
			cntCR ++;
			break;
		case '\n':
			cntLF ++;
			break;
		case '\'':
			if (!isQuot2)
				isQuot1 = 1 - isQuot1;
			break;
		case '\"':
			if (!isQuot1)
				isQuot2 = 1 - isQuot2;
			break;
		case ';':
		case '#':
			if (isQuot1 || isQuot2)
				break;
			if (*rem1 == NULL)
				*rem1 = p - cntblank;
			break;
		default:
			if (isspace((unsigned char)*p)) {
				cntblank ++;
			} else {
				cntblank = 0;
				if ((*rem1 == NULL) && (cont1 == NULL))
					cont1 = p;
			}
			break;
		}
	}


	*nextline = p;
	*rem2 = p - cntCR - cntLF;
	if (*rem1 == NULL)
		*rem1 = *rem2;
	cont2 = *rem1 - cntblank;


	if (cont1 == NULL) {
		cont1 = cont2;
		return LINE_EMPTY;
	}


	i = (int)(cont2 - cont1);
	if (i >= SIZE_LINE)
		return LINE_ERROR;


	//内容头尾已无空格
	memcpy(content, cont1, i);
	content[i] = 0;


	if (content[0] == '[' && content[i - 1] == ']')
		return LINE_SECTION;
	if (strchr(content, '=') != NULL)
		return LINE_VALUE;
	
	return LINE_ERROR;
}




//取一节section
//输入:节名称
//输出:成功与否、节名称首、节名称尾、节内容首、节内容尾(含换行)、下一节首(节尾与下一节首间为空行或注释行)
 int inirw::FindSection(const char *section, char **sect1, char **sect2, char **cont1, char **cont2, char **nextsect)
{
	int type;
	char content[SIZE_LINE];
	char *rem1, *rem2, *nextline;


	char *p;
	char *empty;
	int uselen = 0;
	char found = 0;


	if (gBuffer == NULL) {
		return 0;
	}


	while (gBuflen - uselen > 0) {
		p = gBuffer + uselen;
		type = GetLine(p, gBuflen - uselen, content, &rem1, &rem2, &nextline);
		uselen += (int)(nextline - p);


		if (LINE_SECTION == type) {
			if (found || section == NULL) break;		//发现另一section
			content[strlen(content) - 1] = 0;			//去尾部]
			StrStrip(content + 1);						//去首尾空格
			if (StriCmp(content + 1, section) == 0) {
				found = 1;
				*sect1 = p;
				*sect2 = rem1;
				*cont1 = nextline;
			}
			empty = nextline;
		} else
		if (LINE_VALUE == type) {
			if (!found && section == NULL) {
				found = 1;
				*sect1 = p;
				*sect2 = p;
				*cont1 = p;
			}
			empty = nextline;
		}
	}
	
	if (!found) return 0;


	*cont2 = empty;
	*nextsect = nextline;
	return 1;
}




//从一行取键、值
//输入:内容串(将被改写)
//输出:键串、值串
 void GetKeyValue(char *content, char **key, char **value)
{
	char *p;


	p = strchr(content, '=');
	*p = 0;
	StrStrip(content);
	StrStrip(p + 1);
	*key = content;
	*value = p + 1;
}




//释放ini文件所占资源
void inirw:: iniFileFree()
{
	if (gBuffer != NULL) {
		free(gBuffer);
		gBuffer = 0;
		gBuflen = 0;
	}
}




//加载ini文件至内存
int inirw::iniFileLoad(const char *filename)
{
	FILE *file;
	int len;


	//iniFileFree();
	if (strlen(filename) >= sizeof(gFilename))
		return 0;
	strcpy(gFilename, filename);


	file = fopen(gFilename, "ab+");
	if (file == NULL) 
		return 0;


	fseek(file, 0, SEEK_END);
	len = ftell(file);
	gBuffer =(char *) malloc(len);
	if (gBuffer == NULL) {
		fclose(file);
		return 0;
	}


	fseek(file, 0, SEEK_SET);
	len = fread(gBuffer, 1, len, file);
	fclose(file);
	gBuflen = len;
	return 1;
}




//读取值原始串
 int inirw::iniGetValue(const char *section, const char *key, char *value, int maxlen, const char *defvalue)
{
	int type;
	char content[SIZE_LINE];
	char *rem1, *rem2, *nextline;
	char *key0, *value0;


	char *p;
	int uselen = 0;
	char found = 0;
	int len;


	if (gBuffer == NULL || key == NULL) {
		if (value != NULL)
			value[0] = 0;
		return 0;
	}


	while (gBuflen - uselen > 0) {
		p = gBuffer + uselen;
		type = GetLine(p, gBuflen - uselen, content, &rem1, &rem2, &nextline);
		uselen += (int)(nextline - p);


		if (LINE_SECTION == type) {
			if (found || section == NULL) break;		//发现另一section
			content[strlen(content) - 1] = 0;			//去尾部]
			StrStrip(content + 1);						//去首尾空格
			if (StriCmp(content + 1, section) == 0) {
				found = 1;
			}
		} else
		if (LINE_VALUE == type) {
			if (!found && section == NULL) {
				found = 1;
			}
			if (!found)
				continue;
			GetKeyValue(content, &key0, &value0);
			if (StriCmp(key0, key) == 0) {
				len = strlen(value0);
				if (len == 0) break;		//空值视为无效
				if (value != NULL) {
					len = fmin(len, maxlen - 1);
					strncpy(value, value0, len);
					value[len] = 0;
				}
			//	printf("value = %s\n",value);
				return 1;


			}
		}
	}
	
	//未发现键值取缺省
	if (value != NULL) {
		if (defvalue != NULL) {
			len = fmin(strlen(defvalue), maxlen - 1);
			strncpy(value, defvalue, len);
			value[len] = 0;
			iniSetString(section, key, defvalue);
		} else {
			value[0] = 0;
		}
	}
	return 0;
}


//
//int inirw::iniGetIP(const char *section, const char *key, BasicHashTable *hashtable, int maxlen, const char *defvalue)
//{
//
//	
//	int type;
//	char content[SIZE_LINE];
//	char *rem1, *rem2, *nextline;
//	char *key0, *value0;
//	char *value=NULL;
//	char *p;
//	int uselen = 0;
//	char found = 0;
//	int succed=0;
//	int len;
//
//	if (gBuffer == NULL || key == NULL) {
//		if (value != NULL)
//			value[0] = 0;
//		return 0;
//	}
//
//	while (gBuflen - uselen > 0) {
//		p = gBuffer + uselen;
//		type = GetLine(p, gBuflen - uselen, content, &rem1, &rem2, &nextline);
//		uselen += (int)(nextline - p);
//
//		if (LINE_SECTION == type) {
//			if (found || section == NULL) break;		//发现另一section
//			content[strlen(content) - 1] = 0;			//去尾部]
//			StrStrip(content + 1);						//去首尾空格
//			if (StriCmp(content + 1, section) == 0) {
//				found = 1;
//			}
//		} else
//			if (LINE_VALUE == type) {
//				if (!found && section == NULL) {
//					found = 1;
//				}
//				if (!found)
//					continue;
//				GetKeyValue(content, &key0, &value0);
//				if (StriCmp(key0, key) == 0) {
//					len = strlen(value0);
//					if (len == 0) break;		//空值视为无效
//					if (value != NULL) {
//						len = fmin(len, maxlen - 1);
//					//	strncpy(value, value0, len);
//					//	value[len] = 0;
//					//printf("value0 =%s\n",value0);
//					//	
//					}
//					value=strDup(value0);
//					//printf("value =%s\n",value);
//					char *key3="-";
//				/*	GetKeyValue(value, &key3, &value0);
//					printf("str1 =%s\n",value0);
//						
//						printf("value =%s\n",value);*/
//				//	printf("value = %s\n",value);
//					char *str1=strstr(value,"-");
//					if(str1!=NULL){
//						len =strlen(value)-strlen(str1);
//						str1+=1;
//					//	printf("str1 =%s\n",str1);
//						
//						value[len] = 0;
//					//	printf("value=%s\n",value);
//						char *begin_str=strrchr(value,'.')+1;
//						char *end_str=strrchr(str1,'.')+1;
//
//					//	printf("begin_str=%s\n",begin_str);
//					//	printf("end_str=%s\n",end_str);
//						
//
//						int iBeginIP=atoi(begin_str);
//						int iEndIP=atoi(end_str);
//						len =strlen(value)-strlen(begin_str);
//						value[len]=0;
//					//	printf("value = %s\n",value);
//					//	printf("%d -%d \n",iBeginIP,iEndIP);
//						while(iBeginIP<=iEndIP){
//							char ipaddr[100]={0};
//							sprintf(ipaddr,"%s%d",value,iBeginIP);
//								printf("ipaddr=%s\n",ipaddr);
//								hashtable->AddStreamName(ipaddr,(void *)1);
//							iBeginIP++;
//						}
//
//					}
//					else
//						hashtable->AddStreamName(value,(void *)1);
//
//					succed=1;
//				}
//			}
//	}
//	if(succed)
//		return 1;
//	return 0;
//}


//获取字符串,不带引号
int inirw::iniGetString(const char *section, const char *key, char *value, int maxlen, const char *defvalue)
{
	int ret;
	int len;


	ret = iniGetValue(section, key, value, maxlen, defvalue);
	if (!ret)
		return ret;


	//去首尾空格
	len = strlen(value);
	if (value[0] == '\'' && value[len - 1] == '\'') {
		value[len - 1] = 0;
		memmove(value, value + 1, len - 1);
	} else
	if (value[0] == '\"' && value[len - 1] == '\"') {
		value[len - 1] = 0;
		memmove(value, value + 1, len - 1);
	}
	return ret;
}




//获取整数值
int inirw::iniGetInt(const char *section, const char *key, int defvalue)
{
	char valstr[64];


	if (iniGetValue(section, key, valstr, sizeof(valstr), NULL))
	    return (int)strtol(valstr, NULL, 0);
	iniSetInt(section, key,defvalue,10);
	return defvalue;
}




//获取浮点数
double inirw::iniGetDouble(const char *section, const char *key, double defvalue)
{
	char valstr[64];


	if (iniGetValue(section, key, valstr, sizeof(valstr), NULL))
	    return (int)atof(valstr);
	return defvalue;
}




//设置字符串:若value为NULL,则删除该key所在行,包括注释
int inirw::iniSetString(const char *section, const char *key, const char *value)
{
	FILE *file;
	char *sect1, *sect2, *cont1, *cont2, *nextsect;
	char *p;
	int len, type;
	char content[SIZE_LINE];
	char *key0, *value0;
	char *rem1, *rem2, *nextline;




	if (gBuffer == NULL) {
		return 0;
	}


	if (FindSection(section, §1, §2, &cont1, &cont2, &nextsect) == 0)
	{
		//未找到节


		//value无效则返回
		if (value == NULL) 
			return 0;


		//在文件尾部添加
		file = fopen(gFilename, "ab");
		
		if (file == NULL) 
			return 0;


		fprintf(file, "\r\n[%s]\r\n%s=%s;\r\n", section, key, value);
		fclose(file);
		iniFileLoad(gFilename);
		return 1;
	}


	//找到节,则节内查找key
	p = cont1;
	len = (int)(cont2 - cont1);
	while (len > 0) {
		type = GetLine(p, len, content, &rem1, &rem2, &nextline);


		if (LINE_VALUE == type) {
			GetKeyValue(content, &key0, &value0);
			if (StriCmp(key0, key) == 0) {
				//找到key
				file = fopen(gFilename, "wb");
				if (file == NULL) 
					return 0;
				len = (int)(p - gBuffer);
				fwrite(gBuffer, 1, len, file);					//写入key之前部分
				if (value == NULL) {
					//value无效,删除
					len = (int)(nextline - gBuffer);			//整行连同注释一并删除
				} else {
					//value有效,改写
					fprintf(file, "%s=%s", key, value);
					len = (int)(rem1 - gBuffer);				//保留尾部原注释!
				}
				fwrite(gBuffer + len, 1, gBuflen - len, file);	//写入key所在行含注释之后部分
				fclose(file);
				iniFileLoad(gFilename);
				return 1;
			}	
		}


		len -= (int)(nextline - p);
		p = nextline;
	}


	//未找到key


	//value无效则返回
	if (value == NULL) 
		return 0;


	//在文件尾部添加
	file = fopen(gFilename, "wb");
	if (file == NULL) 
		return 0;
	len = (int)(cont2 - gBuffer);
	fwrite(gBuffer, 1, len, file);					//写入key之前部分
	fprintf(file, "%s=%s;\r\n", key, value);
	fwrite(gBuffer + len, 1, gBuflen - len, file);	//写入key之后部分
	fclose(file);
	iniFileLoad(gFilename);
	return 1;
}




//设置整数值:base取值10、16、8,分别表示10、16、8进制,缺省为10进制
int inirw::iniSetInt(const char *section, const char *key, int value, int base)
{
	char valstr[64];


	switch (base) {
	case 16:
		sprintf(valstr, "0x%x", value);
		return iniSetString(section, key, valstr);
	case 8:
		sprintf(valstr, "0%o", value);
		return iniSetString(section, key, valstr);
	default:	//10
		sprintf(valstr, "%d", value);
		return iniSetString(section, key, valstr);
	}
}


用法用例
inirw *configRead=new inirw("test.ini");
 char *sect="general";
//若文件中没有这个配置,则会自动生成
int x= configRead->iniGetInt(sect,"num" ,1);//整型数字的获取
char g_var_departcode[1024]={0};//字符串的获取
configRead->iniGetString(sect, "departcode", g_var_departcode, sizeof(g_var_departcode), "0");
delete configRead;


跨平台C、C++代码注意的事项及如何编写跨平台的C/C++代码 在我们的开发中,跨平台的需求越来越强烈,如何保持C/C++代码能在多个平台上编译,是一个比较值得研究的问题。关于跨平台的文章网上很多,跨平台的库网上也很多。那么我从自己的跨平台开发经验谈一谈自己的心得,希望对大家能够起到一定的作用。主要涉及到Windows和linux两个操作系统。 1、  关于路径和头文件路径分隔符的问题 在Windows中,正斜杠和反斜杠都可以,但是在Linux中, 阅读详情

相关推荐

C++跨平台开发:程序员凌晨三点在Linux下崩溃的真相

defined#elifdefined不要用反向判断避免WIN32和_WIN64的混用永远用__linux__而不是LINUXif(WIN32)endif()

weixin_44626085的博客 1324

转 源码分享:c++配置类

网上一个热心的大牛分享了一个c++配置类,如下:Config.h [cpp]view plaincopy //Config.h #pragmaonce #include<string> #include<map> #include<iostream>...

demonzsmj12315的博客 174

在window 下使用Visual Studio Code和docker,调试Linux c/c++ 程序

       调试linux的c/c++ 程序,在window下一直是个麻烦的问题,一般需要安装一个虚拟机或者在linux下系统才方便,随着Visual Studio Code越来越流行可以用它来打造自己的全栈式的开发环境,实现的原理是docker 和 pipeTransport。首先,安装: Visual Studio Code,安装插件 vscode-cpptools;docker-machi...

kilmas2012的博客 5789

深入理解C++中的配置文件处理(Config)及其应用场景

深入理解C++中的配置文件处理(Config)及其应用场景

qq_46017342的博客 6118

inirw源码文件

主要特点: 1、支持;和#注释符号,支持行尾注释。 2、支持带引号'或"成对匹配的字符串,提取时自动去引号。引号中可带其它引号或;#注释符。 3、支持无section或空section(名称为空)。......

GPU运维工程师入门指南 (第九篇): 高性能网络 - InfiniBand与RDMA技术

本文介绍了支撑AI分布式训练的高性能网络技术InfiniBand和RDMA。传统TCP/IP网络因内核开销和内存拷贝成为性能瓶颈,而InfiniBand提供高带宽、低延迟的专用网络,RDMA则通过内核旁路和零拷贝技术实现节点间内存直接访问,显著提升通信效率。特别介绍了GPUDirect RDMA技术,使GPU显存可直接通信。文章还列举了运维人员在部署这些技术时需要考虑的硬件、驱动、配置和监控等关键点。这些技术共同构成了支撑大规模AI集群的"数据高速公路",为后续讨论存储性能瓶颈奠定了基础

weixin_42587823的博客 1096

c++ 配置类

网上一个热心的大牛分享了一个c++配置类,如下: Config.h //Config.h #pragma once #include <string> #include <map> #include <iostream> #include <fstream> #include <sstream> /* *

skysys的研究小屋 1009

Charles 抓包工具下载安装及基础使用

本篇内容主讲关于Charles抓包工具,从下载安装以及配置信息,证书的下载安装以及PC端设置代理配置和移动端设备配置代理,阐述关于Charles抓包工具面板的基础使用以及如何进行抓包和设置断点,对于软件测试以及对抓包感兴趣的读者可以翻阅!感谢大家的支持!!!

灵魂学者的博客 2957

c语言直接读写ini配置文件

现场好多地方反馈记录全采出来,无法入库。实际上采集部门专门做有一数据分析入库工具,但不是标准的,每个地方都需要采集部门特殊改。 于是想到自己做一工具,模拟车载机通信,把全采出来的数据通过连接采集前置传至采集本地库。但是遇到一问题,参数和配置如何保存? windows系统中有一种ini配置文件,可以用它来保存配置。高级语言操作ini文件很简单,有现有的库,但c语言,只能自己做一个了。分享下 C...

猫哥 的沉淀、积累、总结。天天学习,好好向上...c/c++,嵌入式 linux,Android,HarmonyOS,AIOT) 2万+

Star CCM+中的物性参数(定值、多项式、查表)

仿真过程中我们一定会遇到设置物性参数的问题,对于固定的物性参数还好说,直接输入一个固定的值即可。但是对于冷却液、气体、两相流等,物性参数是随着温度或温度和压力变化的。此时就涉及到多项式和查表。首先创建物理连续体,选择计算模型。

2201_75375391的博客 2957

Autosar诊断实战系列02-Dem(DTC&Event)要点及配置开发详解

Dem模块及其与Dcm等其他模块的交互是整个诊断Stack的重中之重,本文先对与其他模块的交互逻辑进行介绍,有一定掌握后继续重点介绍配置部分的开发。

initiallizer的博客 3330

c++工程模式+配置文件+动态调用类

前言 主函数 SimpleFactoryRefactor.cpp #include <iostream> #include<string> #include "DynOBJ.h" #include "get_config.h" using namespace std; #define CFG_FILE_PATH "test.cfg" class Api { public...

Rexinx博客 891

5.7 BGP属-ORIGIN

注意:当去往同一个目的地存在多条不同Origin属性的路由时,在其他条件都相同的情况下,BGP将按如Origin的下顺序优选路由:IGP > EGP > Incomplete。通过以上输出可以看到路由表选择了R3发过来的路由,因为R1的路由的起源为?通过以上输出我们可以看到针对于1.1.1.1这条路由有两条,从R1和R3传过来的起源都属于IGP。(4)把从R1传过来的路由的起源改为incomplete。通过以上输出可以看到,从R1传过来的路由是最优的。(2)在R2上查看1.1.1.1的路由详细信息。

lwljh134的博客 308

ini配置文件读取ConfigureParse

用于解析类似windows下ini配置格式文件。INI配置文件有三要素parameters,sections和comments。使用virant结构获取对象值。

热爱生活,忠于自己 687

19、情境理论中的信息结构解析

本文系统解析了情境理论中的信息结构,从信息元(infon)的基本概念出发,深入探讨了关系结构与简单信息结构的构建方法,分析了标准信息结构所满足的一系列公理(如A1-A14),并阐述了角色、同一性、高阶信息、循环现象、参数适当性及信息元部分性等核心性质。通过具体示例和流程图展示了信息结构的构建过程,并对比了不同公理下的结构差异,最后讨论了该理论在与其他领域融合中的发展趋势及面临的挑战。

book8的博客 78

DeepSeek邮件管理全攻略

DeepSeek邮件助手是一款高效的邮件处理工具,提供智能分类、撰写、回复和任务自动化功能。通过API调用或多智能体系统,它能自动分类邮件意图、生成专业回复并优化邮件内容。核心功能包括智能过滤、会议安排和任务提醒,支持与主流邮箱服务集成。提供精准提示词模板,帮助用户快速生成得体邮件,提升工作效率。适合个人和企业使用,通过简单配置即可实现邮件处理自动化。

Genio_Wang的博客 180

C++ Log4cpp跨平台日志库使用记录(Window与Linux)

介绍log4cpp的项目用法,将在项目中常用的用法代码写下来分享!

cpp_learner的博客 8031

用playwright封装一个处理web网页的爬虫,并隐藏自动化特征,自动处理反爬

本文介绍了一个使用Playwright封装的Python爬虫函数,具备反爬对抗能力。该脚本通过移除自动化标志、注入真实用户代理、禁用Chrome自动化属性等措施,有效绕过电商、新闻等中等反爬网站的检测。核心功能包括:隐藏navigator.webdriver标志、模拟人类浏览行为、设置合理的设备参数,并支持代理和延迟加载。使用时需注意避免高频访问并定期更新User-Agent。该方案适用于需要JavaScript渲染的动态网页,性能优于非无头模式。

数据知道的博客 3393

【C++ 线程包裹类设计】跨平台C++线程包装类:属性设置与平台差异的全面探讨

在现代软件开发中,多线程编程(Multithreading)已经成为一项不可或缺的技术。它允许程序同时执行多个任务,有效利用多核处理器的能力,从而提高应用程序的性能和响应速度。然而,随着这一技术的广泛应用,它也带来了一系列挑战,尤其是在确保线程安全(Thread Safety)和高效资源管理方面。

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 1362

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

agentic-awesome-skills 实战:用 apify-lead-generation 技能与 Apify Actors 自动化多平台潜在客户挖掘

本文深入解析 agentic-awesome-skills 开源仓库中 `apify-lead-generation` 技能(Skill)的完整用法:它是一套"以 Agent 为核心"的潜在客户(Lead)挖掘工作流,通过 Apify MCP(`mcpc`)动态发现并挑选合适的 Apify Actor,再借助配套的 Node.js 运行器脚本完成从"发起 Actor 运行"到"轮询状态、导出 CS

gitblog_00901的博客 435

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

一个跨平台c++封装的.ini文件读写类

这些天一直在进行跨平台基础函数和类的编写,准备编写跨平台服务器版本的VLink,首先碰到的一个问题就是,Linux缺少直接读写.ini的系统或者C库函数,用google检索了一下,有人用C实现了一个INI文件的读写函数,但是分析他的代码,发现没有优化,也就是象windows api GetPrivatexxxxx系列函数一样,需要每次分析,效率不高,不太适合我;然后又检索到不少使用MFC写的INI

danscort2000的专栏 5106

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Linux与Windows下C++读写ini文件解决方案:让配置文件管理更简单

Linux与Windows下C++读写ini文件解决方案:让配置文件管理更简单 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在软件开发过程中,配置文件管理是至关重要的一环。Linux与Windows下C++读写ini文件解决方案,专为解决配置文件读写问题而生。此开源项目提供了一套适用于Linux和Windows操作系统的C++源代码,帮助开发者轻松实现ini文件的读...

gitblog_06729的博客 982

利用vs2017 CMake开发跨平台C++项目实战

       对于windows程序员来说,在linux上开发C++程序会非常困难,一来没用过makefile,其语法非常生涩难懂,二来vs之外的IDE,其易用性与vs相差甚远,宇宙第一IDE不是盖的。致使C++不同于其他编程语言,硬生生催生出Windows程序员和Linux程序员两个群体,直到有了CMake。        常用开源库的同学想必对CMake非常熟悉,它可以在Linux上可以自动...

青菜虫虫的专栏 3万+

window_manager跨平台支持:Linux、macOS与Windows窗口管理实现对比

**window_manager** 是 Flutter 桌面应用开发中不可或缺的窗口管理插件,它为开发者提供了统一的 API 来控制和管理应用程序窗口。无论你是在开发 Linux、macOS 还是 Windows 平台的桌面应用,这个插件都能帮助你轻松实现跨平台的窗口管理功能。本文将深入探讨 window_manager 在三大主流桌面操作系统上的实现差异,帮助你更好地理解和使用这个强大的工具。

gitblog_01060的博客 309

C++跨平台开发注意事项(Win/Linux) 【一】

随着多系统的普及,不少软件面临跨平台的需求,普通 Windows PC 端可以使用的代码,需要在另一个平台下编译和运行。以 Linux 平台为例,整理了从 Windows 平台上的可编译代码到 Linux 平台上代码移植问题,以及跨平台开发的建议规范与需要注意的事项。 Windows 平台上的 MSVC 编译器容错率比较高,部分代码问题编译器会自动纠正或忽略,但是 Linux 下的 gcc/g++ 比较严格,且运行环境、库不一致,Windows 下可编译的代码,直接在 Linux 下编译会产生很多问题。

Loup&卡普的博客 4713

QML Window Flags属性详解与跨平台开发实践

窗口管理是GUI开发的核心技术,QML通过Window Flags属性实现精细化的窗口控制。作为位掩码枚举类型,Qt.WindowFlags通过组合不同标志位来定义窗口层级、样式和交互行为。在跨平台应用开发中,合理使用Window Flags能解决80%的窗口管理问题,特别是在处理无边框窗口、模态对话框和置顶窗口等场景时。本文结合Qt.Window、Qt.Dialog和Qt.FramelessWindowHint等关键标志位,深入分析其在Windows、macOS和Linux等平台下的实现差异与兼容性方案,

clijovtbq401783153的博客 382
上一篇: 自己写的C++日志类log
下一篇: 从0开始,快速简单搭建webrtc服务器
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值