批处理之家's Archiver

happy886rr 发表于 2017-8-25 21:55

跨平台printf工具pr

[i=s] 本帖最后由 happy886rr 于 2017-8-26 10:12 编辑 [/i]

[quote]
pr  与printf类似,但远超printf。可以对各类文本格式化输出,对各类命令的返回结果进行格式化整理。内嵌表达式计算核心,堪比小型计算器。
(图片为外部链接)
[img]http://i2.bvimg.com/604745/a0975b615cabb534.png[/img]
[/quote]

用法[code]
pr -e [格式化表达式] [参数1] [参数2] [参数3] ...
[/code]由于windows的批处理对%号敏感,我用\代替百分号,因此有了如下的格式化类型字符串[code]
\d 数字
\x 十六进制
\c 字符
\s 字符串
\f 浮点数
\o 八进制
\u 无符号数
\e 科学计数法
\g 科学计数精度
\r 回车
\n 换行
\t tab
\T 显示本地时间字符串
\C 颜色格式化
\, 千分位格式化
[/code]示例:
显示本地时间[code]
> pr -e\T
Sat, 25 Aug 2017 19:59:12
[/code]彩色输出
[img]http://i1.bvimg.com/604745/b60d7dded049953d.png[/img][code]
> pr -e"\CW\Cel\Cco\Cm\Ce to \CBat\CHom\Ce" "1|4|8" "1|2|8" "1|8" "2|8" "1|4|8" "1|2" "1|4|8" "1|2|8"
Sat, 25 Aug 2017 19:59:12
[/code]千分位格式化[code]
> pr -e\, 1234567
1,234,567
[/code]用于科学计算输出[code]
> pr -e"Result: \3.6f" sin((pi)/3)
Result: 0.866025
[/code]用于字符串对齐、文本对齐[code]
> pr -e"\-10.10s" da5da5d12ad21a1d2a1d
> pr -e"\10s" da5
> pr -e"\ 7d"  666
[/code]用于打印换行特殊字符[code]
> pr -eAafafa\r\nafa+56a\r\nfsaf565ad\r\n
> pr -e\c 7
[/code]辅助echo实现各类增强功能,用处广,跨平台。更是各类控制台手机终端的必备良器。

源码发行,推荐gcc编译。不提供任何附件下载,请自行编译。[code]
/*
    CONSOLE PRINT TOOL, PR.EXE COPYRIGHT@2017~2019 BY HAPPY
    VERSION 1.0
*/
#include   <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <unistd.h>
#include    <math.h>

#if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
#include <windows.h>
#endif

#define HELPINFORMATION "\
Console print tool, Copyright@2017~2019, Version 1.0\n\
pr -e[expression] {args...}\n\
\n\
Options:\n\
    -e print expression\n\
    -h help information\n\
\n\
Support math functions:\n\
     pi, e, torad, sin, cos, tan, sinh, cosh, tanh\n\
     arcsin, arccos, arctan, arcsinh, arccosh, arctanh\n\
     sqrt, abs, lg, ln, exp, gamma, rand, round, int, ceil, floor\n"

#define STACK_SIZE 4096
static const char* KEY_WORDS[]= {"e", "pi", "sqrt", "lg", "ln", "sin", "cos", "tan", "arcsin", "arccos", "arctan", "torad", "abs", "round", "floor", "ceil", "exp", "sinh", "cosh", "tanh", "arcsinh", "arccosh", "arctanh", "int", "gamma", "rand", NULL};
char   STACK1[STACK_SIZE]= {0};
char   STACK2[STACK_SIZE]= {0};
double STACK3[STACK_SIZE]= {0};

int prThousandsformatted(char* oStr)
{
    int len = strlen(oStr), rl = len%3, i;
    for(i=0; i<rl; i++)
    {
        putc(oStr[i], stdout);
    }
    if(rl)
        putc(',', stdout);
    for(; i<len; i++)
    {
        putc(oStr[i], stdout);
        if(!((i-rl+1)%3) && i!=len-1)
            putc(',', stdout);
    }
    return 0;
}

long long fact(long long n)
{
    return (n<2) ?1 :n*(fact(n-1));
}

double RevPolishCore(const char* expression)
{
    char   *op=(char*)expression, *S1=STACK1, *S2=STACK2, **key, *cp, *kp;
    double *S3=STACK3, di, ni;
    int    brackets=0;
    STACK3[0]=0;

    while(*op!='\0')
    {
        switch(*op)
        {
        case ' ' :
        case '\t':
        case '\r':
        case '\n':
            op++;
            continue;

        case '(':
            brackets++;
            *(++S1)=*op;
            if(*(op+1)=='-' || *(op+1)=='+')
            {
                *(S2++)='0', *(S2++)=' ';
            }
            break;

        case ')':
            if(brackets ==0)
            {
                fputs("The brackets or ')' are not need", stderr);
                exit(1);
            }
            brackets--;
            while(*S1!='(')
            {
                *(S2++)=*(S1--);
            }
            S1--;
            break;

        case '+':
        case '-':
            while(S1!=STACK1 && *S1!='(')
            {
                *(S2++)=*(S1--);
            }
            *(++S1)=*op;
            break;

        case '&':
        case '|':
        case '^':
            while('A'<=(*S1) && (*S1)<='Z')
            {
                *(S2++)=*(S1--);
            }
            *(++S1)=*op;
            break;

        case '!':
            *(S2++)=*op;
            break;

        case '%':
        case '*':
        case '/':
            while(('A'<=(*S1) && (*S1)<='Z') ||*S1=='%' ||*S1=='*' ||*S1=='/' ||*S1=='^')
            {
                *(S2++)=*(S1--);
            }
            *(++S1)=*op;
            break;

        default :
            if('a'<=*op && *op<='z')
            {
                key=(char**)KEY_WORDS;
                while(*key !=NULL)
                {
                    cp=op, kp=*key;
                    while((*cp==*kp || *cp+32==*kp) && *kp!='\0')
                    {
                        cp++, kp++;
                    }
                    if(!('a'<=*cp && *cp<='z')  && (*kp=='\0'))
                    {
                        op=cp;
                        break;
                    }
                    key++;
                }
                if(*key !=0)
                {
                    *(S2++)='.';
                    *(S2++)=' ';
                    while('A'<=(*S1) && (*S1)<='Z')
                    {
                        *(S2++)=*(S1--);
                    }
                    *(++S1)=key-(char**)KEY_WORDS+65;
                    continue;
                }
                else
                {
                    fputs("Unrecognized math function\n", stderr);
                    exit(1);
                }

            }
            else if(('0'<=*op && *op<='9') || (*op=='.'))
            {
                while(('0'<=*op && *op<='9') || (*op=='.'))
                {
                    *(S2++)=*(op++);
                }
                if('a'<=*op && *op<='z')
                {
                    fputs("Missing required operator\n", stderr);
                    exit(1);
                }
                op--;
                *(S2++)=' ';

            }
            else
            {
                fputs("Unrecognized operator\n", stderr);
                exit(1);
            }
            break;
        }
        op++;
    }

    if(brackets !=0)
    {
        fputs("The brackets '(' are not closed", stderr);
        exit(1);
    }

    while(S1 !=STACK1)
    {
        *(S2++)=*(S1--);
    }
    *S2=' ';

    op=STACK2;
    while(*op!=' ')
    {
        switch(*op)
        {
        case 'A':
            *S3=2.7182818284590452;
            break;
        case 'B':
            *S3=3.1415926535897932;
            break;
        case 'C':
            if(*S3 <0)
            {
                fputs("Negative numbers have no square root\n", stderr);
                exit(1);
            }
            *(S3-1)=sqrt(*S3);
            S3--;
            break;
        case 'D':
            if(*S3 <0)
            {
                fputs("Negative numbers are not logarithmic\n", stderr);
                exit(1);
            }
            *(S3-1)=log10(*S3);
            S3--;
            break;
        case 'E':
            if(*S3 <0)
            {
                fputs("Negative numbers have no natural logarithms\n", stderr);
                exit(1);
            }
            *(S3-1)=log(*S3);
            S3--;
            break;
        case 'F':
            *(S3-1)=sin(*S3);
            S3--;
            break;
        case 'G':
            *(S3-1)=cos(*S3);
            S3--;
            break;
        case 'H':
            if(*S3==3.1415926535897932/2)
            {
                fputs("The pi/2 has no tangent\n", stderr);
                exit(1);
            }
            *(S3-1)=tan(*S3);
            S3--;
            break;
        case 'I':
            *(S3-1)=asin(*S3);
            S3--;
            break;
        case 'J':
            *(S3-1)=acos(*S3);
            S3--;
            break;
        case 'K':
            *(S3-1)=atan(*S3);
            S3--;
            break;
        case 'L':
            *(S3-1)=(*S3)*3.1415926535897932/180.0;
            S3--;
            break;
        case 'M':
            *(S3-1)=fabs(*S3);
            S3--;
            break;
        case 'N':
            *(S3-1)=round(*S3);
            S3--;
            break;
        case 'O':
            *(S3-1)=floor(*S3);
            S3--;
            break;
        case 'P':
            *(S3-1)=ceil(*S3);
            S3--;
            break;
        case 'Q':
            *(S3-1)=exp(*S3);
            S3--;
            break;
        case 'R':
            *(S3-1)=sinh(*S3);
            S3--;
            break;
        case 'S':
            *(S3-1)=cosh(*S3);
            S3--;
            break;
        case 'T':
            *(S3-1)=tanh(*S3);
            S3--;
            break;
        case 'U':
            *(S3-1)=asinh(*S3);
            S3--;
            break;
        case 'V':
            *(S3-1)=acosh(*S3);
            S3--;
            break;
        case 'W':
            *(S3-1)=atanh(*S3);
            S3--;
            break;
        case 'X':
            *(S3-1)=(int)(*S3);
            S3--;
            break;
        case 'Y':
            if(*S3 <0)
            {
                fputs("Negative numbers have no factorial", stderr);
                exit(1);
            }
            *(S3-1)=tgamma(*S3);
            S3--;
            break;
        case 'Z':
            if(*S3 <0)
            {
                fputs("A negative number can not be used as a random upper bound", stderr);
                exit(1);
            }
            else if(*S3 <2)
            {
                *(S3-1)=rand() % 8192 /8192.0;
            }
            else
            {
                *(S3-1)=rand() % (int)(*S3);
            }
            S3--;
            break;
        case '+':
            *(S3-1)+=*S3;
            S3--;
            break;
        case '-':
            *(S3-1)-=*S3;
            S3--;
            break;
        case '*':
            *(S3-1)*=*S3;
            S3--;
            break;
        case '%':
        case '/':
            if(*S3 !=0)
            {
                if(*op=='%')
                {
                    *(S3-1)=(int)*(S3-1) % (int)*S3;
                }
                else
                {
                    *(S3-1)/=*S3;
                }

            }
            else
            {
                fputs("Divisor is zero error\n", stderr);
                exit(1);
            }
            S3--;
            break;
        case '|':
            *(S3-1) =(int)(*(S3-1)) | (int)(*S3);
            S3--;
            break;
        case '&':
                *(S3-1) =(int)(*(S3-1)) & (int)(*S3);
            S3--;
            break;
        case '^':
            if(*(S3-1)==0 && *S3<0)
            {
                fputs("Function pow's divisor is zero error\n", stderr);
                exit(1);
            }
            *(S3-1)=pow(*(S3-1), *S3);
            S3--;
            break;
        case '!':
            if(*S3 <0)
            {
                fputs("Negative numbers have no factorial\n", stderr);
                exit(1);
            }
            *S3=fact((long long)(*S3));
            break;
        default :
            di=0, ni=1;
            while('0'<=*op && *op<='9')
            {
                di=10*di+(*op)-'0';
                op++;
            }
            if(*op=='.')
            {
                op++;
                while('0'<=*op && *op<='9')
                {
                    di=10*di+(*op)-'0';
                    op++, ni*=10;
                }
            }
            *(++S3)=di/ni;
            break;
        }
        op++;
    }

    if (isinf(*S3)||isnan(*S3))
    {
        fputs("Overflow or illegal operation is calculated", stderr);
        exit(1);
    }
    return *S3;
}

//MAIN主函数入口
int main(int argc, char** argv)
{
    if ((argc==1) || (argc==2 && !strcasecmp(argv[1], "-h")))
    {
        fprintf(stderr, HELPINFORMATION);
        return 0;
    }

    int i = 2;
    char* prExp = NULL;
    if ((argc > 1) && (argv[1][0]=='-' && (argv[1][1]=='e' || argv[1][1]=='E')))
    {
        prExp = (argv[1][2] != '\0') ?(argv[1]+2) :((argc > 2)?(argv[i++]):NULL);
    }

    if (prExp == NULL)
    {
        fprintf(stderr, HELPINFORMATION);
        return 1;
    }

    srand((int)getpid());
    char prBuf[STACK_SIZE], *t=prBuf, *p=prExp;
    static char nowTime[128];
    static const char* timeFormatGMT = "%a, %d %b %Y %H:%M:%S";

#if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
        HANDLE handle_out=GetStdHandle(STD_OUTPUT_HANDLE);
        WORD orgCOLOR;
        CONSOLE_SCREEN_BUFFER_INFO buffINFO;
        GetConsoleScreenBufferInfo(handle_out, &buffINFO);
        orgCOLOR=buffINFO.wAttributes;
#endif


    while(*p)
    {
        if (*p == '\\')
        {
            t=prBuf;
            *t++ = '%';
            p++;
            while(*p=='+' || *p=='-' || *p=='0' || *p==' ' || *p=='#' || ('0'<=*p && *p<='9') || *p=='.')
                *t++ = *p++;

            switch (*p)
            {
            case 'n':
                printf("\n");
                break;

            case 'r':
                printf("\r");
                break;

            case 't':
                printf("\t");
                break;

            case 'T':
                    {
                        time_t timeNow = time((time_t*)0);
                        strftime(nowTime, sizeof(nowTime), timeFormatGMT, (const struct tm*)localtime(&timeNow));
                        printf("%s", nowTime);
                    }
                    break;
                   
#if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)
            case 'C':
                if(i >= argc)
                    break;
                SetConsoleTextAttribute(handle_out, (int)RevPolishCore(argv[i++]));
                    break;
#endif

            case '\\':
                printf("\\");
                break;

            case ',':
                if(i >= argc)
                    break;
                prThousandsformatted(argv[i++]);
                break;

            case 's':
                *t++ = *p;
                *t='\0';
                if(i >= argc)
                    break;
                printf(prBuf, (char*)argv[i++]);
                break;

            case 'c':
                *t++ = 'c';
                *t='\0';
                if(i >= argc)
                    break;
                printf(prBuf, (char)(int)RevPolishCore(argv[i++]));
                break;

            case 'd':
                *t++ = 'd';
                *t='\0';
                if(i >= argc)
                    break;
                printf(prBuf, (int)RevPolishCore(argv[i++]));
                break;

            case 'o':
                *t++ = 'o';
                *t='\0';
                if(i >= argc)
                    break;
                printf(prBuf, (int)RevPolishCore(argv[i++]));
                break;

            case 'e':
            case 'E':
                *t++ = *p;
                *t='\0';
                if(i >= argc)
                    break;
                printf(prBuf, RevPolishCore(argv[i++]));
                break;

            case 'g':
            case 'G':
                *t++ = *p;
                *t='\0';
                if(i >= argc)
                    break;
                printf(prBuf, RevPolishCore(argv[i++]));
                break;

            case 'x':
            case 'X':
                *t++ = *p;
                *t='\0';
                if(i >= argc)
                    break;
                printf(prBuf, (int)RevPolishCore(argv[i++]));
                break;

            case 'u':
                *t++ = 'u';
                *t='\0';
                if(i >= argc)
                    break;
                printf(prBuf, (unsigned int)RevPolishCore(argv[i++]));
                break;

            case 'f':
                *t++ = 'f';
                *t='\0';
                if(i >= argc)
                    break;
                printf(prBuf, RevPolishCore(argv[i++]));
                break;

            default:
                fprintf(stderr, "Unknow flag '%c'", *p);
                return 1;
            }
            p++;
        }

        t=prBuf;
        while(*p && *p != '\\')
            *t++ = *p++;

        *t='\0';
        printf("%s", prBuf);

        if(i >= argc && argc!=2)
            break;

    }
   
#if defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) || defined(_MSC_VER)   
        SetConsoleTextAttribute(handle_out, orgCOLOR);
#endif

    return 0;
}

[/code]

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.