免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1214 | 回复: 2

老师留的作业,大家帮忙挑挑毛病!!! [复制链接]

论坛徽章:
0
发表于 2004-08-17 16:54 |显示全部楼层
/**********************[[水乐天作品]]****************************/
/******************模拟编译系统(演示版)**********************/
/*********************版本号:0.0130************************/



#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "ctype.h"
#include "conio.h"
#include "alloc.h"
#include "graphics.h"
#include "Svga64k.h"
#include "fcntl.h"
#include "malloc.h"
#include "io.h"#define TRUE 1
#define FALSE 0
#define STACK_INIT_SIZE 100/*存储空间初始分配量*/
#define STACKINCREMENT 20/*存储空间分配增量*/char*Messages[]=
{
    /*语句类型信息列表*/
    /*错误!*/
    "(0)Error!",
    /*说明语句*/
    "(1)Explain language sentence!",
    /*函数*/
    "(2)Fouction!",
    /*表达式*/
    "(3)Expression!",
    /*内存不足*/
    "(4)EMS memory not enough!",
    /*正常无类型*/
    "(5)nomal"
};typedef struct
{
    int *pBase;/*在构造之前和销毁之后,base的值为NULL*/
    int *pTop;/*栈顶指针*/
    int StackSize;/*当前已分配的存储空间,以元素为单位*/
}Stack;struct Kind
{
    char Int_name[32];
    int Int_value ;
}
;
/*用来模拟储存变量的内存*/struct Result
{
    int Int ;
}
;
/*用来模拟储存结果的内存*/
struct Kind kind[10];
struct Result result ;char Source_text[100][600];
/*源文件数组*/
char Temp_text[600];
/*临时存放数组*/
char Clean_text[600];
/*临时存放脱去空格与关键字的数组*/
int Type=0 ;
/*语句的类型*/
char Type_name[32];
/*语句的类型名*/
int Embody=1 ;
/*语句具体类型*/const int MaxWordLen=32 ;
typedef int BOOLEAN;char Count[600];/*临时存放表达式的数组*/
int Count_i=-1;
char Operator[8]="+-*/()#";/*合法的操作符存储在字符串中*/
char Optr;/*操作符*/
int Opnd=-1;/*操作符*/
int Number_Result;/*操作结果*/int huge Return_SVGA64K(void)
{
    return(0);
    /* 返回各种分辨率的对应编号 0~6 宏定义参见 Svga64k.h */
}/*16Mrgb像素类型*/
typedef struct
{
    unsigned char b ;
    unsigned char g ;
    unsigned char r ;
}
rgb16M ;void putpoint65536(int x,int y,rgb16M color)
{
    setrgbpalette(1026,color.r>;>;3,color.g>;>;2,color.b>;>;3);
    putpixel(x,y,0);
}/*以下是有关运算使用到的函数*/
Stack InitStack();
void DestoryStack(Stack *S);
int GetTop(Stack S);
int Push(Stack *S,int e);
int Pop(Stack *S,int *e);
char CheckPriority(char operator_1,char operator_2);
void GetInput(void);
int Calc(int a,char theta,int b);
BOOLEAN EvaluateExpression();void readme(void);
/*显示说明的函数*/
void Judge_type(void);
/*判断语句类型*/
void Judge_embody(void);
/*具体判断是什么语句*/
void No_key(void);
/*脱掉空格和关键字的函数*/
void No_space(void);
/*仅脱掉空格的函数*/
void Choice(void);
/*选择语句执行函数*/
void Run_program(int);
/*模拟运行程序的函数*/
void Run_Int(void);
/*模拟运行int的函数*/
void Run_Printf(void);
/*模拟运行printf()的函数*/
void Evaluate(void);
/*进行四则运算的函数*/
void No_line(void);/*这是程序执行时的标准参数写法,argc是参数的个数,argv表示参数具体的字串*/
void main(int argc,char*argv[])
{
    FILE*fsource,*ftarget ;
    /*两个文件指针分别指向源文件和目标文件*/
    int i,ln,end ;
    char line[600];
    if(argc<3)
    {
        /*程序使用方法是:xx 原文件名 目标文件名 (假设程序编译为xx.exe)*/
        readme();
        getch();
        exit(1);
    }
    /*使用fopen打开源文件失败的处理*/
    if((fsource=fopen(argv[1],"rt")==NULL)
    {
        printf("Can't open source file %s.\n",argv[1]);
        exit(1);
    }
    /*使用fopen打开目标文件失败的处理*/
    if((ftarget=fopen(argv[2],"wt")==NULL)
    {
        printf("Can't open target file %s.\n",argv[2]);
        exit(1);
    }
    ln=0 ;
    /*以下是从源文件中逐行读出内容并存入Source_text[][]直到文件结束*/
    while(fgets(line,512,fsource)!=NULL)
    {
        stpcpy(Source_text[ln],line);
        ln++;
        /*逐行读源文件*/
    }
    fclose(fsource);
    for(i=0;i<=ln;i++)
    {
        printf("%s",Source_text);
    }
   
    printf("\n-------------------------------------------------------------------\n";    end=1 ;
    /*以下是向目标文件中逐行写入内容直到全部写完*/
    while(end<=ln+1)
    {
        fprintf(ftarget,"%d:   %s",end++,Source_text[end-1]);
        /*加上行号写入目标文件*/
    }
    Run_program(ln);
    /*开始模拟运行程序*/
   
    fprintf(ftarget,"\n-------------------------------------------------------------------\n",end++,Source_text[end-1]);
    fprintf(ftarget,"Ok!\nResult is:%d",result.Int);
    fclose(ftarget);
   
    printf("\nOperation accomplished.\n";
    getch();
}



/*显示说明的函数*/
void readme(void)
{
    int width,height,i=DETECT,j=0,x0,y0,fp ;
    char fix ;
    rgb16M*buffer ;
    installuserdriver("Svga64K",Return_SVGA64K);
    /*对于svga64k必需执行该函数以安装BGI驱动*/
    initgraph(&i,&j,"";
    /* 执行TC默认的BGI初始化函数 */
   
    if((fp=open("readme.bmp",O_RDONLY|O_BINARY))==-1)
    {
        puts("Can't find file " "readme.bmp" ".";
        printf("Incorrect Argument Numbers.\nUsagex Source_file Target_file\n";
        exit(1);
    }
    lseek(fp,18,SEEK_SET);
    read(fp,&width,4);
    read(fp,&height,4);
    fix=width%4 ;
    x0=(320-width)/2 ;
    y0=(200-height)/2 ;
    lseek(fp,54,SEEK_SET);
    buffer=(rgb16M*)malloc(width*sizeof(rgb16M));
   
    for(j=height-1;j>;=0;j--)
    {
        read(fp,buffer,width*sizeof(rgb16M));
        lseek(fp,fix,SEEK_CUR);
        for(i=0;i<width;i++)
        putpoint65536(x0+i,y0+j,buffer);
    }
    free(buffer);
    close(fp);
    getch();
    closegraph();
}

/*模拟运行的主函数*/
void Run_program(int ln)
{
    int i ;
    char a=176,b=2;
    for(i=0;i<=ln;i++)
    {
        stpcpy(Temp_text,Source_text);
        printf("\n\n%d :",i);
        Judge_type();
        /*判断语句类型*/
        Judge_embody();
        /*具体判断是什么语句*/
        if(Type!=3)
        {
            No_key();
        }
        else
        {
            No_space();
        }
        /*脱掉空格和关键字*/
        Choice();
        /*根据相应的类型进行选择*/
        Type=0 ;
        /*语句的类型*/
        Embody=1 ;
        /*语句具体类型*/
        printf("\nPress any key continue...",b,a,a,a,b);
        getch();
    }

  /*显示完成信息*/
  clrscr();
  printf("%c%c%c%c%c%c%c\n",a,a,a,a,a,a,a);
  printf("%c%c%c%c%c%c%c\n",a,a,a,a,a,b,a);
  printf("%c%c%c%c%c%c%c\n",a,a,a,a,b,a,a);
  printf("%c%c%c%c%c%c%c\n",a,b,a,b,a,a,a);
  printf("%c%c%c%c%c%c%c\n",a,a,b,a,a,a,a);
  printf("%c%c%c%c%c%c%c\n",a,a,a,a,a,a,a);
  printf("\n";
  printf("  \1  OK!\n"
         "  \1  All done!\n"
         "  \1  Thank you for use!!!\n";
   
}


/*检验语句基本类型的函数*/
void Judge_type(void)
{
    register int i=0,j=0,in_word=0 ;
    char*Prompt="\nThe type of this sentence is:" ;
    char*TestWord ;
    char c ;
   
    char*IsLegal(char*CheckWord);
   
    TestWord=(char*)malloc(sizeof(char)*MaxWordLen);
    /*TestWord存放用户输入*/
    if(!TestWord)
    return ;
    for(i=0;(c=Temp_text)!='\0';i++)
    if(c==' ')
    {
        if(in_word==1)
        {
            in_word=0 ;
            TestWord[j]='\0' ;
            j=0 ;
            if((IsLegal(TestWord))!=Messages[5])
            printf("%s %s",Prompt,IsLegal(TestWord));
        }
    }
    else
    {
        TestWord[j]=c ;
        in_word=1 ;
        j++;
    }
   
    free(TestWord);
    /*释放分配的内存区域*/
   
}


/*此函数检验语句的类型*/
char*IsLegal(char*CheckWord)
{
    char*KeyWords[]=
    {
        "auto","break","case","char","continue","const","default",
        "do","double","else","enum","extern","float","for","goto",
        "if","int","long","noalias","register","return","short",
        "signed","sizeof","static","struct","switch","typedef",
        "union","unsigned","void","volatile","while","defined",
        "define","undef","include","ifdef","ifndef","endif","line",
        "error","elif","pragma"
    }
    ;
    /*C关键字列表*/
    char*Functions[]=
    {
        "close","creat","eof","fclose","fcloseall","feof","fopen",
        "ferror","fgetchar","fgets","fprintf","fputc","fputchar",
        "fseek","get","putch","putc","printf","open","putchar",
        "puts","read","scanf","abs","acos","asin","math","atan",
        "atan2","atof","atoi","atol","ceil","dos","cosh","ecvt",
        "exp","fabs","floor","fmod","frexp","itoa","labs","ldexp",
        "log","log10","modf","pow","rand","sin","sqrt","srand",
        "strtod","strlol","tan","tanh","ultoa","memset","strcpy",
        "struct","strchr","strcmp","calloc","isalnum","isalpha",
        "toascii","tolower","tollpper","exit"
    }
    ;
    /*C主要函数列表*/
   
    char*Operation[]=
    {
        "+","-","*","/","="
    }
    ;
    /*运算符列表*/
    register int i ;
    char*WordTemp ;
   
    WordTemp=(char*)malloc(MaxWordLen*sizeof(char));
    if(!WordTemp)return Messages[4];
   
    /*判断其类型是否为关键字*/
    for(i=0;i<44;i++)
    {
        if(!strcmp(CheckWord,KeyWords))
        {
            Type=1 ;
            stpcpy(Temp_text,CheckWord);
            return Messages[1];
        }
    }
    /*判断其类型是否为函数*/
    for(i=0;i<69;i++)
    {
        if(!strcmp(CheckWord,Functions))
        {
            Type=2 ;
            stpcpy(Temp_text,CheckWord);
            return Messages[2];
        }
    }
    /*判断其类型是否为运算表达式*/
    for(i=0;i<5;i++)
    {
        if(!strcmp(CheckWord,Operation))
        {
            Type=3 ;
            Embody=1 ;
            return Messages[3];
        }
    }
   
    free(WordTemp);
    return Messages[5];
}

/*进行具体语句类型判断的函数*/
void Judge_embody(void)
{
    int i=1 ;
    char*KeyWords[]=
    {
        "","int"
    }
    ;
    /*C关键字列表*/
    char*Functions[]=
    {
        "","printf"
    }
    ;
    /*C主要函数列表*/
    if(Type==1)
    for(i=1;!strcmp(Type_name,KeyWords);i++)
    Embody=i ;
    if(Type==2)
    for(i=1;!strcmp(Type_name,Functions);i++)
    Embody=i ;
    printf("\n(%d,%d)Type analysis succeed!\n",Type,Embody);
}

/*去除关键字和空格的函数*/
void No_key(void)
{
    int i=0,j=0,hold=0 ;
   
    i=strlen(Type_name);
    /*取关键字最后一个字符*/
   
    for(j=0;Type_name[i-1]!=Temp_text[j];j++)
    ;
    /*查找这个字符在字符串中的首位址*/
   
    for(i=j+1;Temp_text!=';';i++)
    if(Temp_text!=' ')
    {
        Clean_text[hold]=Temp_text;
        hold++;
    }
    /*脱空格,脱关键字*/
   
    Clean_text[hold+1]='\0' ;
   
}

/*单纯去除空格的函数*/
void No_space(void)
{
    int i=0,hold=0 ;
   
    for(i=0;Temp_text!=';';i++)
    if(Temp_text!=' ')
    {
        Clean_text[hold]=Temp_text;
        hold++;
    }
    /*脱空格*/
   
    Clean_text[hold+1]='\0' ;
   
}

/*进行选择的函数*/
void Choice(void)
{
    void(*Function_name[5][2])(void)=
    {
        {
            NULL,No_line
        }
        /*首位为空*/
        ,
        {
            NULL,Run_Int
        }
        /*存放关键字的指向函数的指针*/
        ,
        {
            NULL,Run_Printf
        }
        /*存放函数的指向函数的指针*/
        ,
        {
            NULL,Evaluate
        }
        /*存放用于运算的指向函数的指针*/
    }
    ;
    (*Function_name[Type])();
}



/*模拟int的函数*/
void Run_Int(void)
{
    int i=0,j=0,hold=0,in_word=0 ;
    char c ;
   
   
    c=Clean_text[0];
   
    do
    {
        if((c==',')||(c=='\0'))
        {
            if(in_word==1)
            {
                in_word=0 ;
                kind[hold].Int_name[j]='\0' ;
                hold++;
                j=0 ;
            }
        }
        else
        {
            kind[hold].Int_name[j]=c ;
            in_word=1 ;
            j++;
        }
        i++;
    }
    while((c=Clean_text)!='\0');
   
    printf("\nInteger is:";
    for(i=0;i<=hold;i++)
    printf(" %s ",kind.Int_name);
}

/*模拟printf()的函数*/
void Run_Printf(void)
{
    int i=0,j=0,k=0,in_word=0,hold=0 ;
    char temp[32];
    char c ;
   
    c=Clean_text[0];
   
    do
    {
        if((c==',')||(c==')')||(c=='\"'))
        {
            if(in_word==1)
            {
                in_word=0 ;
                temp[j]='\0' ;
                j=0 ;
                if(!strcmp(temp,"%d"))
                {
                    hold=1 ;
                }
                ;
                if(hold==1)
                for(k=0;k<=10;k++)
                if(!strcmp(temp,kind[k].Int_name))
                result.Int=kind[k].Int_value ;
                /*如果是变量则把变量的值付给结果*/
            }
        }
        else
        {
            temp[j]=c ;
            in_word=1 ;
            j++;
        }
        i++;
    }
    while((c=Clean_text)!='\0');
   
    printf("printf :%d",result.Int);
   
}

/*进行运算的函数*/
void Evaluate(void)
{
  int i=0,j=0,k,f,temp=0,in_word=0;
  char c='';
  char c1[32]={""},c2[10]={""};

  /*找到空格的位置*/
  for(temp=0;Clean_text[temp]!='=';temp++)
    ;

  i=temp+1;
  c=Clean_text;
  do
  {
   
    /*判断是否是运算中用到的关键字*/
    if(
       (c=='+')||(c=='-')||(c=='/')||(c=='*')||
       (c==')')||(c=='(')||(c=='\0')||(c>;='0'&&c<='9')
      )
    {

        /*如果是则判断是否是变量,并把关键字存入变量之中*/
        if(in_word==1)
        {
            in_word=0 ;
            c1[j]='\0' ;
            j=0 ;
        for(k=0;k<=10;k++)
        if(!strcmp(c1,kind[k].Int_name))
                {
                    itoa(kind[k].Int_value,c2, 10);
                    strcat(Count,c2);
                }
        }
    f=strlen(Count);
    Count[f]=c;
    }
    /*如果不是则字符入串*/
    else
    {
        c1[j]=c ;
        in_word=1 ;
        j++;
    }
    i++;
    c=Clean_text;
   /*因为为了把最后一位的字符加入所以i-1*/
  }while(Clean_text[i-1]!='\0');

  /*在字符串最后加入结束标记#*/
  k=strlen(Count);
  Count[k-1]='#';
  Count[k]='\0';

  /*开始进行运算*/
  EvaluateExpression();

  /*输出运算过程*/
  printf("=%d\n",Number_Result);

  /*清空c1*/
  stpcpy(c1,"");

  /*找到=之前的标识符*/
  for(i=0;i<temp;i++)
    c1=Clean_text;
  c1[i+1]='\0';

  /*显示结果标识符的值*/
  for(k=0;k<=10;k++)
    if(!strcmp(c1,kind[k].Int_name))
    {
        kind[k].Int_value=Number_Result;
        printf("%s=%d\n",kind[k].Int_name,kind[k].Int_value);
    }

}

/*运算符间的优先关系*/
char PriorityTable[7][7]=
{
    {'>;','>;','<','<','<','>;','>;'},
    {'>;','>;','<','<','<','>;','>;'},
    {'>;','>;','>;','>;','<','>;','>;'},
    {'>;','>;','>;','>;','<','>;','>;'},
    {'<','<','<','<','<','=','o'},
    {'>;','>;','>;','>;','o','>;','>;'},
    {'<','<','<','<','<','o','='},
};

/* 数据对象的操作方法 */
/* 构造一个空栈,如果返回值为0,则表示初始化失败 */
Stack InitStack()/*这是个效率低的方法*/
{
    Stack S;
    S.pBase=(int*)malloc(STACK_INIT_SIZE*sizeof(int));
    if(!S.pBase)
    {/*内存分配失败*/
        printf("内存分配失败,程序中止运行\n");
        exit(-1);
    }
    else
    {
        S.pTop=S.pBase;
        S.StackSize=STACK_INIT_SIZE;
    }
    return S;
}

/* 销毁栈S,S不再存在 */
void DestoryStack(Stack *S)
{
    if(S->;pBase)
    {
        free(S->;pBase);
        S->;pTop=S->;pBase=NULL;
        
    }
}

/* 若栈不空,则用e返回S的栈顶元素 */
/* 注:由于应用的特殊,可以不检查栈是否为空 */
int GetTop(Stack S)
{
    return *(S.pTop-1);
}

/* 插入元素e为新的栈顶元素,如果成功则返回1,否则返回0 */
int Push(Stack *S,int e)
{
    if(S->;pTop-S->;pBase==S->;StackSize)
    {/* 栈满,追加存储空间 */
        S->;pBase=(int*)realloc(S->;pBase,S->;StackSize+STACKINCREMENT*sizeof(int));
        if(!S->;pBase)
            return 0;/* 存储分配失败 */
        S->;pTop=S->;pBase+S->;StackSize;
        S->;StackSize+=STACKINCREMENT;
    }
    *(S->;pTop++)=e;
    return 1;
}

int Pop(Stack *S,int *e)
{/* 若栈不空,则删除S的栈顶元素,用e 返回其值,并返回1;否则返回0 */
    if(S->;pTop==S->;pBase)
        return 0;
    *e=*--(S->;pTop);
    return 1;

}

/* 主函数及其它函数的实现 */
/* 比较两个数学符号operator_1,operator_2的计算优先权,在算符优先关系表中查找相应的关系并返回'<','=',或'>;' */
char CheckPriority(char operator_1,char operator_2)
{
    int i,j;/* 用来查询算符间优先关系表的下标 */
    /* char *ptr; */
    i=strchr(Operator,operator_1)-Operator;/* 找到传入操作符在字符串Operators中的相对位置 */
    j=strchr(Operator,operator_2)-Operator;
    /* 返回算符优先关系表中相应值 */
    return PriorityTable[j];
}

BOOLEAN IsOperator(char ch)
{/* 判断一个字符是否为打操作符 */
    if(strchr(Operator,ch))
        return TRUE;
    else
        return FALSE;

}
/* 从数组中获得字符 */
void GetInput(void)
{
    char Buffer[20];/* 键盘输入缓冲区,用来处理输入多位数的情况 */
    char ch;/* 存放键盘输入 */
    int index;/* 存放Buffer的下标 */
    index=0;
    Count_i+=1;
    ch=Count[Count_i];/* 从键盘读入一个字符 */
    while(ch!='#'&&!IsOperator(ch))
    {/* 如果字符是回车符或是操作符,循环结束 */
        if(ch>;='0'&&ch<='9')
        {/* 将字符回显到屏幕 */
            printf("%c",ch);
            Buffer[index]=ch;
            index++;

        }
        Count_i+=1;
        ch=Count[Count_i];
    }
    if(ch=='#')
        Optr='#';/* 输入的表达式以#结束 */
    else
    {
        Optr=ch;
        printf("%c",ch);

    }
    if(index>;0)
    {
        Buffer[index]='\0';
        Opnd=atoi((Buffer));
    }
    else
        Opnd=-1;/* 程序不支持输入负数,当Opnd为负数时,表示输入的字符为操作符 */
}
/* 计算形如a+b之类的表达式,theta为操作符,a,b为操作数 */
int Calc(int a,char theta,int b)
{
    switch(theta)
    {
    case '+':
        return a+b;
    case '-':
        return a-b;
    case '*':
        return a*b;
    default:
        if(b==0)/* 除数为零的情况 */
        {
            printf("除数不能为");
            return 0;/* 返回0用以显示 */
        }
        else
            return a/b;
    }
}
/*表达式求值*/
BOOLEAN EvaluateExpression()
{
    int temp;/* 临时变量 */
    int itheta;/* 存放出栈的操作符的变量add by me */
    int a,b;/* 存放表达式运算时的中间值 */
    int topOpnd;/* 栈顶操作数 */
    char topOptr;/* 栈顶操作符 */
   
    Stack OPTR=InitStack();/* 操作符栈 */
    Stack OPND=InitStack();/* 操作数栈 */

    if(!Push(&OPTR,'#'))/* 操作符栈中的第一个为#字符 */
        return FALSE;

    GetInput();/* 从获得字符 */

    while(Optr!='#'||GetTop(OPTR)!='#')
    {/* 如果Optr>;=0,表示有操作数输入 */
        if(Opnd>;=0)Push(&OPND,Opnd);
        switch(CheckPriority(GetTop(OPTR),Optr))
        {
        case '<':/* 栈顶元素优先权低 */
            if(!Push(&OPTR,Optr))return FALSE;
                GetInput();
            break;
        case '=':/* 脱括号并接收键盘输入 */
            Pop(&OPTR,&temp);GetInput();
            break;
        case '>;':/* 退栈并将运算结果入栈 */
            /* 先用itheta得到操作符在赋给theta */
            Pop(&OPTR,&itheta);
            Pop(&OPND,&b);
            Pop(&OPND,&a);
            Push(&OPND,Calc(a,itheta,b));
            Opnd=-1;
            break;

        }
    }
    /* 本算法中,当输入只有一个操作数然后就输入回车符时, */
    /* OPND.pTop==OPND.pBase */
    /* 如果OPND.pTop==OPND.pBase并且Opnd<0,则说明用户 */
    /* 未输入任何操作和操作符而直接输入#,程序直接 */
    /* 退出运行 */
    if(OPND.pTop==OPND.pBase&&Opnd<0)
    {
        printf("\n\nThank you choice!\n");
        exit(1);

    }
    else if(OPND.pTop==OPND.pBase)
        Number_Result=Opnd;
    else
    {
        Number_Result=GetTop(OPND);
        DestoryStack(&OPND);
        DestoryStack(&OPTR);
    }
    return TRUE;

}

/*对于没有语句的处理*/
void No_line(void)
{
    printf("Can't find line");
}

论坛徽章:
0
发表于 2004-08-17 17:25 |显示全部楼层

老师留的作业,大家帮忙挑挑毛病!!!

我没学过编译原理~~~还没开课~~
老师留个题目就摸索着做~~~
现在这个程序已经可以编译通过了
不过在最后结尾的处理出来的数字总是少了一位???
为什么?

论坛徽章:
0
发表于 2004-08-17 18:53 |显示全部楼层

老师留的作业,大家帮忙挑挑毛病!!!

自己给程序加上code标记!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP