当前位置: 首页 > news >正文

Linux下C开发使用小技巧

Linux下C开发使用小技巧

基础类

整形,字符串互转

C语言提供了几个标准库函数,可以将任意类型(整型、长整型、浮点型等)的数字转换为字符串,下面列举了各函数的方法及其说明。
● itoa():将整型值转换为字符串。
● ltoa():将长整型值转换为字符串。
● ultoa():将无符号长整型值转换为字符串。
● gcvt():将浮点型数转换为字符串,取四舍五入。
● ecvt():将双精度浮点型值转换为字符串,转换结果中不包含十进制小数点。
● fcvt():指定位数为转换精度,其余同ecvt()。

除此外,还可以使用sprintf系列函数把数字转换成字符串,其比itoa()系列函数运行速度慢

以下是用itoa()函数将整数转换为字符串的一个例子:

# include <stdio.h>
# include <stdlib.h>
void main (void)
{
int num = 100;
char str[25];
itoa(num, str, 10);
printf("The number 'num' is %d and the string 'str' is %s. \n" ,
num, str);
}

itoa()函数有3个参数:第一个参数是要转换的数字,第二个参数是要写入转换结果的目标字符串,第三个参数是转移数字时所用 的基数。在上例中,转换基数为10。10:十进制;2:二进制…

itoa并不是一个标准的C函数,它是Windows特有的,如果要写跨平台的程序,请用sprintf。是Windows平台下扩展的,标准库中有sprintf,功能比这个更强,用法跟printf类似:

char str[255];
sprintf(str, "%x", 100); //将100转为16进制表示的字符串。

cpp中string转int:

void str2int(int &int_temp,const string &string_temp)  
{  int_temp=atoi(string_temp.c_str());                     
}  

cpp中int转string:

void int2str(const int &int_temp,string &string_temp)  
{  char s[12];             //设定12位对于存储32位int值足够  itoa(int_temp,s,10);            //itoa函数亦可以实现,但是属于C中函数,在C++中推荐用流的方法  string_temp=s;  
}  

架构类

Linux C代码实现主函数参数选项解析
1. 手动解析版本

使用argc、argv,逐个字符比较,得到要想的参数名字即进行判断、解析。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>int debug;void show_version(char* name)
{printf("%s by Late Lee, version: 1.0\n", name);
}void usage(char* name)
{show_version(name);printf("         -h,  --help           short help\n");printf("         -v,  --version        show version\n");
}int main(int argc, char *argv[])
{int i = 0;/* early check for debug and config parameter */if (argc > 1) {for (i = 1; i < argc; i++){if ((strcmp(argv[i], "-D")==0) || (strcmp(argv[i], "--debug")==0)){debug = 1;}}}///* parse parameters, maybe not the best way but... */for (i = 1; i < argc; i++){if (debug)printf("arg %d: \"%s\"\n",i,argv[i]);// helpif ((strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0)){usage(argv[0]);return 0;}// versionelse if ((strcmp(argv[i],"-v")==0) || (strcmp(argv[i],"--version")==0)){show_version(argv[0]);return 0;}// debugelse if ((strcmp(argv[i],"-D")==0) || (strcmp(argv[i],"--debug")==0)){debug=1;}else if ((strcmp(argv[i],"fpga")==0)){printf("test of fpga...\n");}// stringelse if ((strcmp(argv[i],"-i")==0) || (strcmp(argv[i],"--iface")==0)){if (i+1<argc){char interface[32] = {0};strncpy(interface, argv[i+1], 32);if (debug)printf("Used interface: %s\n", interface);i++;continue;} else {printf("Error: Interface for -i missing.\n");return 1;}}// numberelse if ((strcmp(argv[i],"-ru")==0) || (strcmp(argv[i],"--rateunit"))==0){if (i+1<argc && isdigit(argv[i+1][0])) {int rateunit = 0;rateunit = atoi(argv[i+1]);if (rateunit < 0 || rateunit > 1){printf("Error: Invalid parameter \"%d\" for --rateunit.\n", rateunit);printf(" Valid parameters:\n");printf("    0 - bytes\n");printf("    1 - bits\n");return 1;}if (debug)printf("Rateunit changed: %d\n", rateunit);i++;continue;}else{}}// only oneelse if (strcmp(argv[i],"--enable")==0){int enable = 0;enable = 1;}else{printf("Unknown parameter \"%s\". Use --help for help.\n",argv[i]);return 1;}}
}
2. 利用getopt函数完成
/**
解析命令选项示例#include <unistd.h>
extern char *optarg;   //选项的参数指针
extern int optind,    //下一次调用getopt的时,从optind存储的位置处重新开始检查选项。
extern int opterr,   //当opterr=0时,getopt不向stderr输出错误信息。
extern int optopt;   //当命令行选项字符不包括在optstring中或者选项缺少必要的参数时,该选项存储在optopt中,getopt返回'?’、
int getopt(int argc, char * const argv[], const char *optstring);使用:
$ ./a.out -Wall -o hello.c*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>int debug_level = 0;#define _AUTHOR "Late Lee"
#define _VERSION_STR "1.0"
#define _DATE ""// 默认打印error等级
enum
{MSG_ERROR = 0,MSG_WARNING,MSG_INFO,MSG_DEBUG,MSG_MSGDUMP,MSG_EXCESSIVE,
};void ll_printf(int level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));void ll_printf(int level, const char *fmt, ...)
{va_list ap;va_start(ap, fmt);if (debug_level >= level){
#ifdef CONFIG_DEBUG_SYSLOGif (wpa_debug_syslog) {vsyslog(syslog_priority(level), fmt, ap);} else {
#endif /* CONFIG_DEBUG_SYSLOG *///debug_print_timestamp();
#ifdef CONFIG_DEBUG_FILEif (out_file) {vfprintf(out_file, fmt, ap);fprintf(out_file, "\n");} else {
#endif /* CONFIG_DEBUG_FILE */vprintf(fmt, ap);printf("\n");
#ifdef CONFIG_DEBUG_FILE}
#endif /* CONFIG_DEBUG_FILE */
#ifdef CONFIG_DEBUG_SYSLOG}
#endif /* CONFIG_DEBUG_SYSLOG */}va_end(ap);
}void show_version(char* name)
{printf("%s by %s, version: %s\n", name, _AUTHOR, _VERSION_STR);
}void usage(char* name)
{show_version(name);printf("    -h,    short help\n");printf("    -v,    show version\n");printf("    -d,    debug level\n");exit(0);
}const char* my_opt = "hOo:W:d:";int main(int argc, char *argv[])
{int c;const char* p1 = NULL;const char* p2 = NULL;const char* p3 = NULL;while(1){c = getopt(argc, argv, my_opt);printf("optind: %d\n", optind);if (c < 0){break;}printf("option char: %x %c\n", c, c);switch(c){case 'd':debug_level = atoi(optarg);printf("debug level: %d\n", debug_level);break;case 'O':printf("optimization flag is open.\n\n");break;case 'o':printf("the obj is: %s\n\n", optarg);p1 = optarg;break;case 'W':printf("optarg: %s\n\n", optarg);p2 = optarg;break;case ':':fprintf(stderr, "miss option char in optstring.\n");break;case '?':case 'h':default:usage(argv[0]);break;//return 0;}}if (optind == 1){usage(argv[0]);}ll_printf(MSG_ERROR, "p1: %s p2: %s\n", p1, p2);return 0;
}

使用 getopt() 进行命令行处理

网络模块
日志模块
读取配置文件模块
内存池模块
缓存库模块
文件系统模块
管理后台模块
数据库模块

技巧类

Linux程序中预定义的几个调试宏

Linux下C语言编程中有几个很实用的调试宏

__LINE__ __FILE__  __FUNCTION__ __TIME__ __DATA__

这几个预定义宏是属于ANSI标准的,内置于编译器,全局性的变量,可以方便地实现代码跟踪调试,不是在哪个头文件中包含的,见下例:

#include <stdio.h>int main()
{printf("The file is %s.\n",__FILE__);printf( "The date is %s.\n", __DATE__ );printf( "The time is %s.\n", __TIME__ );printf( "This is line %d.\n", __LINE__ );printf( "This function is %s.\n", __FUNCTION__ );   return 0;
}

运行结果:

The file is macro.c.
The date is Aug 24 2012.
The time is 23:13:26.
This is line 8.
This function is main.

line 行数 文件名指令可以改变它的值,简单的讲,编译时,它们包含程序的当前行数和文件名。

DATE 宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。
TIME 宏指令包含程序编译的时间。时间用字符串表示,其形式为时:分:秒

__func__代表这条语句所在的函数的函数名

联合体用途

字节序有两种表示方法:大端法(big ending),小端法(little ending)。网络字节序采用的是大端法。主机字节序不同的CPU采用的方法不一样,可以通过代码来查看自己主机的字节序。

  • 大端法:高位字节排放在内存低地址端,低位字节排放在内存的高地址端。
  • 小端法:低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
    看一个unsigned short 数据,它占2个字节,给它赋值0x1234。
  • 若采用的大端法,则其低地址端应该存放的是0x12;
  • 若采用的小端法,则其低地址端应该存放的是0x34;
    可以通过联合体来获得其高低地址的数据。测试主机字节序的代码:
typedef union{unsigned short value;unsigned char bytes[2];
}Test;int main(void)
{Test test_value;test_value.value = 0x1234;if(test_value.bytes[0] == 0x12 && test_value.bytes[1] == 0x34){printf("big ending");}else if(test_value.bytes[0] == 0x34 && test_value.bytes[1] == 0x12){printf("little ending");}else{printf("use test_value error");}return 0;
}

工具类

自定义日志的调试打印信息
#define TRACE_NONE      0
#define TRACE_FATAL     1
#define TRACE_ERROR     2
#define TRACE_WARNING   3
#define TRACE_INFO      4
#define TRACE_DEBUG     5#define TRACE_LEN_MAX    64extern int  *TraceLevel;
extern char TraceName[TRACE_LEN_MAX + 1];#define Log(A, format,args...) \((TraceLevel == NULL || TraceName == NULL || *TraceLevel < (A)) ? 0 : LogMsg(A, __FILE__, __LINE__, format, ##args))#define LogFatal(format,args...) \Log(TRACE_FATAL, format, ##args)
#define LogError(format,args...) \Log(TRACE_ERROR, format, ##args)
#define LogWarning(format,args...) \Log(TRACE_WARNING, format, ##args)
#define LogInfo(format,args...) \Log(TRACE_INFO, format, ##args)
#define LogDebug(format,args...) \Log(TRACE_DEBUG, format, ##args)
int LogMsg(int level, const char *filename,int line, const char *fmt, ...)
{va_list      ap;FILE         *fp;char         sLogFile[128 + 1];char         sCurrTime[6 + 1];struct timeb tTimeB;char         sMilliTM[4];memset(sLogFile, 0, sizeof(sLogFile));LogFile(sLogFile);GetTime_HHMMSS(sCurrTime);memset(&tTimeB, 0, sizeof(tTimeB));    ftime(&tTimeB);snprintf(sMilliTM, sizeof(sMilliTM), "%03d", tTimeB.millitm);fp = fopen(sLogFile, "a+");if (fp != (FILE*)NULL) {fprintf(fp, "[%08d][%.6s:%.3s][%16s][%04d][%7s]",getpid(), sCurrTime, sMilliTM, filename, line, g_LevelDsp[level]);va_start(ap, fmt);vfprintf(fp, fmt, ap);va_end(ap);fprintf(fp, "\n");fflush(fp);fclose(fp);}return 0;
}

再在后台进程中设置TraceLevel和TraceName即可。

获取当前系统日期、时间
/*******************************************************************************  函数名称: GetDate**  功能描述: 取当前系统日期                           **  当前版本: 1.0.0.0                                                    **  作    者:                                             **  修    改:                                                        **  输入参数:**  输出参数: char * psDate  -- 系统日期, 格式为yyyymmdd**  返回结果:int0    --->  成功****************************************************************************/
int GetDate(char * psDate)
{time_t nSeconds;struct tm * pTM;time(&nSeconds);pTM = localtime(&nSeconds);/* 系统日期, 格式:YYYYMMDD */sprintf( psDate,"%04d%02d%02d",pTM->tm_year + 1900, pTM->tm_mon + 1,pTM->tm_mday );return 0;
}
/*******************************************************************************  函数名称: GetTime**  功能描述: 取当前系统时间                           **  当前版本: 1.0.0.0                                                    **  作    者:                                            **  修    改:                                                        **  输入参数:**  输出参数: char * psTime  -- 系统时间, 格式为HHMMSS**  返回结果:int0    --->  成功****************************************************************************/
int GetTime(char * psTime)
{time_t nSeconds;struct tm * pTM;time(&nSeconds);pTM = localtime(&nSeconds);/* 系统时间, 格式:HHMMSS */sprintf( psTime,"%02d%02d%02d",pTM->tm_hour,pTM->tm_min, pTM->tm_sec);return 0;
}
/*******************************************************************************  函数名称: GetDateTime**  功能描述: 取当前系统日期和时间                           **  当前版本: 1.0.0.0                                                    **  作    者:                                            **  修    改:                                                        **  输入参数:**  输出参数: char * psDateTime  -- 系统日期时间, 格式为yyyymmddHHMMSS**  返回结果:int0    --->  成功****************************************************************************/
int GetDateTime(char * psDateTime)
{time_t nSeconds;struct tm * pTM;time(&nSeconds);pTM = localtime(&nSeconds);/* 系统日期和时间, 格式:yyyymmddHHMMSS */sprintf( psDateTime,"%04d%02d%02d%02d%02d%02d",pTM->tm_year + 1900, pTM->tm_mon + 1,pTM->tm_mday,pTM->tm_hour,pTM->tm_min, pTM->tm_sec );return 0;
}

调用的时候定义一个char数组,大小为日期的长度大小加1,然后直接调用上面的函数,参数为数组名即可。
  当然,还有其他许多关于日期、时间操作的函数,比如不同日期、时间格式间的转换等。

相关文章:

  • TIM定时中断
  • 17 vue3之tsx手写vite tsx插件
  • 每天学习一个技术栈 ——【Django Channels】篇(1)
  • Kafka与RabbitMQ:深入理解两者之间的区别
  • MySQL基础--表的增删改查
  • 时间技能物品竞品抢拍拍卖发布h5公众号小程序开源版开发
  • 笔记整理—linux进程部分(2)使用fork创建进程
  • 尚品汇-自动化部署-Jenkins的安装与环境配置(五十六)
  • 十分钟实现内网连接,配置frp
  • JavaWeb图书借阅系统
  • MapBox Android版开发 6 关于Logo
  • [java][代码]DateUtil用于处理日期和时间
  • excel怎么转换json
  • C++初阶:STL详解(九)——stacke和queue的模拟实现
  • kmeans聚类分析 生活使用案例
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • classpath对获取配置文件的影响
  • go append函数以及写入
  • Java基本数据类型之Number
  • JS笔记四:作用域、变量(函数)提升
  • Kibana配置logstash,报表一体化
  • PHP CLI应用的调试原理
  • spark本地环境的搭建到运行第一个spark程序
  • tensorflow学习笔记3——MNIST应用篇
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 如何使用 JavaScript 解析 URL
  • 网络应用优化——时延与带宽
  • 微信小程序填坑清单
  • 因为阿里,他们成了“杭漂”
  • 优秀架构师必须掌握的架构思维
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • $GOPATH/go.mod exists but should not goland
  • (C语言)二分查找 超详细
  • (简单) HDU 2612 Find a way,BFS。
  • (南京观海微电子)——示波器使用介绍
  • (三)终结任务
  • (四) Graphivz 颜色选择
  • (四)Android布局类型(线性布局LinearLayout)
  • (算法)前K大的和
  • (转)我也是一只IT小小鸟
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .cn根服务器被攻击之后
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .net Stream篇(六)
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .NET编程——利用C#调用海康机器人工业相机SDK实现回调取图与软触发取图【含免费源码】
  • .NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数
  • .net中调用windows performance记录性能信息
  • @我的前任是个极品 微博分析
  • [ C++ ] STL---stack与queue