#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);
}