C++代码压行机

2020-02-26 22:10:22


这个程序用来压行(当然也可以让人看不懂你的代码)

它会删掉代码中的注释与大部分多余空格

每次输入一个输入文件名和一个输出文件名(含后缀名)和每行最大字符数LEN,
它会把除了#号开头的行压成一个宽不超过LEN的近似矩形的形状
LEN为1时会鬼畜,为非正数时会这些行压到同一行里
当你输入的LEN内容开头不是数字时会启用默认值80

ta会调用库函数tmpnam生成临时文件,临时文件会自动删除

也可以使用命令行调用。对于每个文件,第一个参数是文件名name,然后
是开关-l与-o(顺序可变)
若填写-l,后应紧跟一个整数LEN
若填写-o,后应紧跟一个文件名,表示输出文件名(不填则默认覆盖输入文件)
比如: compress t1.cpp t2.cpp -o t3.cpp -l 5
意为每行80字符压缩t1.cpp, 每行5字符压缩t2.cpp并输出到t3.cpp

这是它把自己的源代码压缩后的样子:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
using namespace std;char buff[0x100000],buffer[0x100000],*s,*p;char*const buf=b\
uff+100;bool isname(char ch){return isdigit(ch)||isalpha(ch)||ch=='_';}void rem\
ove_backslash(const char*in_,const char*out_){FILE*in=fopen(in_,"r");FILE*out=f\
open(out_,"w");if(!in||!out){fclose(in);fclose(out);return;}while(fgets(buf,0x8\
0000,in)!=NULL){for(s=buf;*s;s++);if(s[-1]=='\n')*(--s)='\0';if(s[-1]=='\\'){s[\
-1]='\0';fputs(buf,out);}else{fputs(buf,out);fputc('\n',out);}}fclose(in);fclos\
e(out);}bool string1,string2,comment,ispre;void remove_comment_and_space(){stri\
ng1=string2=false;for(p=buffer,s=buf;*s;s++){if(!comment&&*s=='/'&&s[1]=='/')br\
eak;if(!comment&&*s=='/'&&s[1]=='*'){comment=true;s+=4;}if(comment&&s[-1]=='/'&\
&s[-2]=='*')comment=false;if(comment)continue;if(string2==0&&*s=='"'&&(s[-2]=='\
\\'||s[-1]!='\\'))string1^=1;if(string1==0&&*s=='\''&&(s[-2]=='\\'||s[-1]!='\\'\
))string2^=1;if(string1==0&&string2==0)if(isspace(*s)&&!(isname(p[-1])&&isname(\
s[1])))continue;*p++=isspace(*s)?' ':*s;}if(comment&&s[-1]=='/'&&s[-2]=='*')com\
ment=false;*p='\0';}void compress(const char*in_,const char*out_,const char*tmp\
_,int max_len){comment=false;remove_backslash(in_,tmp_);FILE*in=fopen(tmp_,"r")\
;FILE*out=fopen(out_,"w");if(!in||!out){fclose(in);fclose(out);return;}bool isp\
re=true;int cnt=0;buf[-1]=' ';while(fgets(buf+1,0x80000,in)!=NULL){if(ispre)buf\
[-1]='\0';*buf=' ';remove_comment_and_space();if(*buffer=='#'&&!ispre){ispre=tr\
ue;fputc('\n',out);cnt=0;}for(s=buffer;*s;s++,cnt++){if(cnt==max_len-1){fputc('\
\\',out);fputc('\n',out);cnt=0;}fputc(*s,out);}if(*buffer=='#'){fputc('\n',out)\
;cnt=0;}else if(*buffer)ispre=false;char*q;for(q=buffer;*q;q++);buffer[-1]=q[-1\
];}fclose(in);fclose(out);remove(tmp_);}char n1[1024],n2[1024],n3[1024];int mai\
n(int argc,char**argv){tmpnam(n3);if(argc==1){while(1){puts("Enter input filena\
me:");gets(n1);puts("Enter output filename:");gets(n2);puts("Enter the maximum \
number of characters per line:");int len=80;scanf("%d",&len);compress(n1,n2,n3,\
len);fflush(stdin);}}for(int i=1;i<argc;i++){const char*in=argv[i],*out=in;prin\
tf("compressing file '%s'.\n",in);int len=80;bool flag1=0,flag2=0;while(i+1<arg\
c&&argv[i+1][0]=='-'){if(argv[i+1][1]=='l'){if(flag1){puts("Error! Repeated -l.\
");return 1;}flag1=1;if(i+2==argc||(!isdigit(argv[i+2][0])&&argv[i+2][0]!='-'))\
{puts("Error! Unknown format.");return 1;}sscanf(argv[i+2],"%d",&len);i+=2;}els\
e if(argv[i+1][1]=='o'){if(flag2){puts("Error! Repeated -o.");return 1;}flag2=1\
;if(i+2==argc){puts("Error! Unknown format.");return 1;}out=argv[i+2];i+=2;}els\
e{puts("Error! Unknown format.");return 1;}}compress(in,out,n3,len);}}

注:g++毒瘤特性
下面代码可正常编译
//qa\
q
#incl\
ude <\
cstdio>
int m\
a\
i\
n() {
    puts("Hello\
 World");
}
与下面代码等价
//qaq
#include <cstdio>
int main() {
    puts("Hello World");
}

有图为证:(洛谷在线IDE代码高亮鬼畜辣)

未压缩的源码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
using namespace std;

char buff[0x100000], buffer[0x100000], *s, *p;
char *const buf = buff + 100;

bool isname(char ch)
{
    return isdigit(ch) || isalpha(ch) || ch == '_';
}
void remove_backslash(const char *in_, const char *out_)
{
    FILE *in = fopen(in_, "r");
    FILE *out = fopen(out_, "w");
    if (!in || !out) {
        fclose(in);
        fclose(out);
        return;
    }
    while (fgets(buf, 0x80000, in) != NULL) {
        for (s = buf; *s; s++);
        if (s[-1] == '\n')
            *(--s) = '\0';
        if (s[-1] == '\\') {
            s[-1] = '\0';
            fputs(buf, out);
        } else {
            fputs(buf, out);
            fputc('\n', out);
        }
    }
    fclose(in);
    fclose(out);
}

bool string1, string2, comment, ispre;
void remove_comment_and_space()
{
    string1 = string2 = false;
    for (p = buffer, s = buf; *s; s++) {
        // 一堆对注释的特判
        if (!comment && *s == '/' && s[1] == '/')
            break;
        if (!comment && *s == '/' && s[1] == '*') {
            comment = true;
            s += 4;
        }
        if (comment && s[-1] == '/' && s[-2] == '*')
            comment = false;
        if (comment)
            continue;
        // 一堆对字符串的特判
        if (string2 == 0 && *s == '"' && (s[-2] == '\\' || s[-1] != '\\'))
            string1 ^= 1;
        if (string1 == 0 && *s == '\'' && (s[-2] == '\\' || s[-1] != '\\'))
            string2 ^= 1;
        if (string1 == 0 && string2 == 0)
            if (isspace(*s) && !(isname(p[-1]) && isname(s[1])))
                continue;
        *p++ = isspace(*s) ? ' ' : *s;
    }
    if (comment && s[-1] == '/' && s[-2] == '*')
        comment = false;
    *p = '\0';
}

void compress(const char *in_, const char *out_, const char *tmp_, int max_len)
{
    comment = false;
    remove_backslash(in_, tmp_);
    FILE *in = fopen(tmp_, "r");
    FILE *out = fopen(out_, "w");
    if (!in || !out) {
        fclose(in);
        fclose(out);
        return;
    }
    bool ispre = true;
    int cnt = 0;
    buf[-1] = ' ';
    while (fgets(buf + 1, 0x80000, in) != NULL) {
        if (ispre)
            buf[-1] = '\0';
        *buf = ' ';
        remove_comment_and_space();
        if (*buffer == '#' && !ispre) {
            ispre = true;
            fputc('\n', out);
            cnt = 0;
        }
        for (s = buffer; *s; s++, cnt++) {
            if (cnt == max_len - 1) {
                fputc('\\', out);
                fputc('\n', out);
                cnt = 0;
            }
            fputc(*s, out);
        }
        if (*buffer == '#') {
            fputc('\n', out);
            cnt = 0;
        } else if (*buffer)
            ispre = false;

        char *q;
        for (q = buffer; *q; q++);
        buffer[-1] = q[-1];
    }
    fclose(in);
    fclose(out);
    remove(tmp_);
}

char n1[1024], n2[1024], n3[1024];

int main(int argc, char **argv)
{
    tmpnam(n3);
    if (argc == 1) {
        while (1) {
            puts("Enter input filename:");
            gets(n1);
            puts("Enter output filename:");
            gets(n2);
            puts("Enter the maximum number of characters per line:");
            int len = 80;
            scanf("%d", &len);
            compress(n1, n2, n3, len);
            fflush(stdin);
        }
    }
    for (int i = 1; i < argc; i++) {
        const char *in = argv[i], *out = in;
        printf("compressing file '%s'.\n", in);
        int len = 80;
        bool flag1 = 0, flag2 = 0;
        while (i + 1 < argc && argv[i + 1][0] == '-') {
            if (argv[i + 1][1] == 'l') {
                if (flag1) {
                    puts("Error! Repeated -l.");
                    return 1;
                }
                flag1 = 1;
                if (i + 2 == argc || (!isdigit(argv[i + 2][0]) && argv[i + 2][0] != '-')) {
                    puts("Error! Unknown format.");
                    return 1;
                }
                sscanf(argv[i + 2], "%d", &len);
                i += 2;
            } else if (argv[i + 1][1] == 'o') {
                if (flag2) {
                    puts("Error! Repeated -o.");
                    return 1;
                }
                flag2 = 1;
                if (i + 2 == argc) {
                    puts("Error! Unknown format.");
                    return 1;
                }
                out = argv[i + 2];
                i += 2;
            } else {
                puts("Error! Unknown format.");
                return 1;
            }
        }
        compress(in, out, n3, len);
    }
}
已知bug: 

1. 若当前行以#开头,以0-9_a-zA-z结尾,且下一行不以#开头,则会有一个多余空格。
2. 可能出现运算符合并的情况,如 > > 被合并成 >>。在C++98中导致CE。