代码改变世界

对一个文件的所有行进行重新排列

2016-04-24 21:27  双头蛇  阅读(252)  评论(0编辑  收藏  举报
#include <iostream>

#include <time.h>

using namespace std;

//#define DEBUG

//#define TOO_MANY_RECORDS

#define FCLOSE(fp) do    \
{                        \
    if(NULL!=(fp))        \
    {                    \
        fclose((fp));    \
        fp=NULL;        \
    }                    \
} while (0);

enum ERRORCODE
{
    ERR_OK,
    ERR_BAD_PARA,
    ERR_FILE_OPEN_ERR,
    ERR_LINE_BUFF_TWO_LONG,
#ifdef TOO_MANY_RECORDS
    ERR_TOO_MANY_RECORDS,
#endif
    ERR_MAX
};

const int  RECORD_COUNT           = 10000;              //THIS CAN BE CHANGE IF YOU NEED!!!

const int  MAX_CHARACHTR          = 260;              //the max number of characters of absolute path name is 259 characters.

const int  SIZE                   = 2*MAX_CHARACHTR;  //because of above, I can assume that each line must be less than 520bytes.

      char buf[RECORD_COUNT*SIZE] = {0};              //assume that the file has 10000 records,and each record has 520 bytes.

      char line[SIZE]             = {0};

      char errmsg[ERR_MAX][128]      = {0};

      int  rndbuf[RECORD_COUNT]   = {0};

void initial_error_msg()
{
    sprintf(errmsg[ERR_OK],                 "no error.");
    sprintf(errmsg[ERR_BAD_PARA],           "parameter is wrong.");
    sprintf(errmsg[ERR_FILE_OPEN_ERR],      "can't open file for read or write.");
    sprintf(errmsg[ERR_LINE_BUFF_TWO_LONG], "file has a line that more than %d bytes.",SIZE);
#ifdef TOO_MANY_RECORDS
    sprintf(errmsg[ERR_TOO_MANY_RECORDS],   "file has too many records(more than %d).",RECORD_COUNT);
#endif
}

void die(enum ERRORCODE err)
{
    if(err < ERR_MAX)
    {
        printf("%s",errmsg[err]);
        exit(err);
    }
};

void main(int argc, const char *argv[])
{
    char *p,*q;
    int i,j;
    int records;
    FILE *fp;

#ifndef DEBUG
    if(argc!=2)
    {
        printf("use %s -h to find help.",argv[0]);
        exit(ERR_BAD_PARA);
    }
#endif

    initial_error_msg();

#ifndef DEBUG
    if( (((char *)argv[1])[0]=='-') && (((char *)argv[1])[1]=='h') && (((char *)argv[1])[2]=='\0') )
    {
#ifdef TOO_MANY_RECORDS
        printf("USAGE:\t%s -h:look up this help.\n\t%s filename:rearrange the file.\n\tNOTE:THE RETURN VALUE HAS THE FOLLOWING MEANINGS\n\t%d:%s\n\t%d:%s\n\t%d:%s\n\t%d:%s\n\t%d:%s",\
                    argv[0],argv[0],
                    ERR_OK,errmsg[ERR_OK],
                    ERR_BAD_PARA,errmsg[ERR_BAD_PARA],
                      ERR_FILE_OPEN_ERR,errmsg[ERR_FILE_OPEN_ERR],
                    ERR_LINE_BUFF_TWO_LONG,errmsg[ERR_LINE_BUFF_TWO_LONG],
                    ERR_TOO_MANY_RECORDS,errmsg[ERR_TOO_MANY_RECORDS]
              );
#else
        printf("USAGE:\t%s -h:look up this help.\n\t%s filename:rearrange the file.\n\tNOTE:THE RETURN VALUE HAS THE FOLLOWING MEANINGS\n\t%d:%s\n\t%d:%s\n\t%d:%s\n\t%d:%s",\
                    argv[0],argv[0],
                    ERR_OK,errmsg[ERR_OK],
                    ERR_BAD_PARA,errmsg[ERR_BAD_PARA],
                    ERR_FILE_OPEN_ERR,errmsg[ERR_FILE_OPEN_ERR],
                    ERR_LINE_BUFF_TWO_LONG,errmsg[ERR_LINE_BUFF_TWO_LONG]
              );
#endif
        exit(ERR_OK);
    }
#endif

#ifndef DEBUG
    fp = fopen(argv[1], "rb");
#else
    fp = fopen("list.tmp","rb");
#endif
    if(fp==NULL)
    {
        FCLOSE(fp);
        die(ERR_FILE_OPEN_ERR);
    }

    i = 0;

    p = buf+i*SIZE;

    /*Read file lines to buf*/
    while((q=fgets(p, SIZE, fp))!=NULL)
    {
        int len = strlen(p);
        if(len >= SIZE - 1)
        {
            //line buff is too long.
            FCLOSE(fp);
            die(ERR_LINE_BUFF_TWO_LONG);
        }
        else if( (p[0] == 0x0d)||(p[0] == 0x0a) )
        {
            //empty line.
            continue;
        }
        i++;
        if(i>=RECORD_COUNT)
        {
            //too many records.
#ifdef TOO_MANY_RECORDS
            while((q=fgets(line, SIZE, fp))!=NULL)
            {
                if( (line[0]!=0x0d)&&(line[0]!=0x0a) )
                {
                    FCLOSE(fp);
                    die(ERR_TOO_MANY_RECORDS);
                }
            }
#endif
            break;
        }
        p = buf+i*SIZE;
    }/*END OF READ*/

    records = j = i;//record counts

    for(i = 0; i < records; i++)
    {
        rndbuf[i] = i;
    }

    srand(time(0));

    while(j > 1)
    {
        register int tmp;
        register int rnd = rand()%j;
        tmp = rndbuf[rnd];
        rndbuf[rnd] = rndbuf[j-1];
        rndbuf[j-1] = tmp;

        j--;
    }

    FCLOSE(fp);

#ifndef DEBUG
    fp = fopen(argv[1], "wb");
#else
    fp = fopen("list.tmp","wb");
#endif
    if(fp==NULL)
    {
        FCLOSE(fp);
        die(ERR_FILE_OPEN_ERR);
    }

    for(i=0; i < records; i++)
    {
        fputs(&buf[rndbuf[i]*SIZE],fp);
    }

    FCLOSE(fp);
}