跨平台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]