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

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]);
        // help
        if ((strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0))
        {
            usage(argv[0]);
            return 0;
        }
        // version
        else if ((strcmp(argv[i],"-v")==0) || (strcmp(argv[i],"--version")==0))
        {
            show_version(argv[0]);
            return 0;
        }
        // debug
        else 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");
        }
        // string
        else 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;
            }
        }
        // number
        else 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 one
        else 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_SYSLOG
        if (wpa_debug_syslog) {
            vsyslog(syslog_priority(level), fmt, ap);
        } else {
#endif /* CONFIG_DEBUG_SYSLOG */
        //debug_print_timestamp();
#ifdef CONFIG_DEBUG_FILE
        if (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    64

extern 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
  **  返回结果:int
                   0    --->  成功
  ****************************************************************************/
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
  **  返回结果:int
                   0    --->  成功
  ****************************************************************************/
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
  **  返回结果:int
                   0    --->  成功
  ****************************************************************************/
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,然后直接调用上面的函数,参数为数组名即可。
  当然,还有其他许多关于日期、时间操作的函数,比如不同日期、时间格式间的转换等。


http://www.kler.cn/a/323935.html

相关文章:

  • Flutter:Widget生命周期
  • Gitcode文件历史记录查看和还原
  • 【解决】Layout 下创建槽位后,执行 Image 同步槽位位置后表现错误的问题。
  • Spring Cloud Eureka 服务注册与发现
  • 自由学习记录(22)
  • windows tomcat 报错后如何让窗口不闪退
  • _RET_IP_ 和_THIS_IP_ 作用
  • cesium的学习过程和使用案例
  • 闲盒支持的组网方式和注意事项
  • gitlab使用小结
  • 原宝,四周年快乐!
  • leetcode621. 任务调度器
  • Linux系统使用iptables配置入站端口
  • 教师工作量|基于springBoot的教师工作量管理系统设计与实现(附项目源码+论文+数据库)
  • shell脚本定时任务通知到钉钉
  • 使用yum为centos系统安装软件以及使用(包含阿里云yum源配置)
  • React封装登录逻辑
  • python的逻辑控制
  • JAVA打造全球商品集散地国际版多商户商城系统小程序源码
  • 1. go 环境与命令
  • python 获取当前git的repo地址
  • electron 设置界面右下角打开
  • 浅谈java异常[Exception]
  • JAVA红娘婚恋相亲交友系统源码全面解析
  • python 实现gradient boosting regressor梯度增强回归器算法
  • 车间调度问题数学建模与CPLEX优化