uestc oj 1081 统计上机成绩

题目:http://www.acm.uestc.edu.cn/problem.php?pid=1081




/*经过多方求助和不懈努力,这个题目终于被我做出来了。
其实并不复杂的,只是对于字符串的处理把握自己在能力上还是不足的。
注意几点:RunID才是题目的提交顺序,如果
6855_Tommy_Wrong Answer_1038.cc
7036_2910201009_Compile Error_1038.cc
6915_Tommy_Accepted_1038.cc
这样的话对于Tommy来说6915才是1038题的第一次提交所以100分而不是95分*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

struct node
{
    char AuthorID[51];
    char RunID[10];
    int  Result;
    int  Number;
    int  Total;
}stu[2005];

int T,i,j,id,start,end;
char key;
char s[100],RunID[10];

void input()
{
        //printf("hehe");
        gets(s);
        int len = strlen(s);

        i=len-1;
        while(s[i]!='.') i--;            //得到.的位置,从而得到题号

        id = 0;                          //得到题号
        id+=s[i-1]-'0';
        id+=(s[i-2]-'0')*10;
        id+=(s[i-3]-'0')*100;
        id+=(s[i-4]-'0')*1000;


        j =i-6;                           //得到判决结果
        while(s[j]!='_')j--;
        key = s[j+1];
        switch(key)
        {
            case 'A':
            stu[T].Result = 1;
            break;

            case 'P':
            stu[T].Result = 2;
            break;

            case 'W':
            stu[T].Result = 3;
            break;

            case 'C':
            stu[T].Result = 4;
            break;

        }

        end = j-1;                        //得到AuthorID的最后一个字符位置

        i=0;
        while(s[i]!='_')
        {
          RunID[i] = s[i];
          i++;
        }
        RunID[i] = '\0';
        start = i+1;                      //得到Authorid的开始字符位置

        char ss[55];

        for(j=0,i=start;i<=end;i++,j++)
        ss[j]=s[i];
        ss[j]='\0';//加入‘/0’是必须的

        strcpy(stu[T].AuthorID,ss);
        stu[T].Number = id;
        //printf("%d  ",stu[T].Result);
        strcpy(stu[T].RunID,RunID);
}

bool cmp(node a,node b)
{
    if(strcmp(a.AuthorID,b.AuthorID)<0||
       (strcmp(a.AuthorID,b.AuthorID)==0&&a.Number<b.Number)||
       (strcmp(a.AuthorID,b.AuthorID)==0&&a.Number==b.Number&&strcmp(a.RunID,b.RunID)<0))
    return 1;
    else  return 0;
}
int main()
{
    //freopen("1.txt","r",stdin);
    scanf("%d",&T);
    getchar();
    int M = T;
    T = 1;
    while(T<=M)
    {
       input();
       T++;
    }
   sort(stu+1,stu+M+1,cmp);
   //for(i=1;i<=M;i++)
   //cout<<stu[i].AuthorID<<"  "<<stu[i].Number<<"  "<<stu[i].Result<<endl;
   int s = 1,t,ss,tt,k;
   while(s<=M)
   {

       for(t=s+1;t<=M&&strcmp(stu[t].AuthorID,stu[s].AuthorID)==0;t++);
       ss = s;                    //ss标记的是一个人的起点

       while(ss<t)               //这是同一个人的范围  t-1表示的是一个人的终点
       {
           for(tt=ss+1;tt<t&&(stu[tt].Number == stu[ss].Number);tt++);//这是单个题目的范围  ss表示一个题目的起点 tt-1表示终点
           if(stu[ss].Result == 1)
           stu[s].Total+=100;                       //这是问题的关键
           else
           {
               k = stu[ss].Result;
               //printf("%d %d %d \n",k,ss,tt);
               for(j=ss+1;j<tt;j++)
               {
                   if(stu[j].Result<k)
                   k = stu[j].Result;
                  // cout<<"heeh";
               }

               //printf("%d %d %d \n",k,ss,t);
               switch(k)
               {
                    case 1:
                    stu[s].Total+=95;
                    break;

                    case 2:
                    stu[s].Total+=90;
                    break;

                    case 3:
                    stu[s].Total+=70;
                    break;

                    case 4:
                    stu[s].Total+=50;
                    break;
                }
           }

           ss = tt;//跳到下一个范围
       }
       s = t; // 跳到下一个人
       //printf("%d  ",s);
   }

    for(i=1;i<=M;i++)
    {
        if(stu[i].Total>0)
        printf("%s %d\n",stu[i].AuthorID,stu[i].Total);
    }

    return 0;
}




下面是我写错了的代码,以作留念

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct node
{
    char name[55];//auther id
    int  score[6];//每个题目对应的得分
    int ex[8];//用于记录是否是第一次提交
}stu[2005];

int T,index1,flag;
char s[2000];

void init() //初始化
{
    for(int i =0;i<T;i++)
    {
        memset(stu[i].ex,0,sizeof(stu[i].ex));
        memset(stu[i].score,0,sizeof(stu[i].score));
    }

}

int search(struct node stu[],char *tok)//查找已有数据中是否有此id 有的话返回i没有的话index1+1
{
   for( int i=0;i<=index1;i++)
   {
       if(strcmp(tok,stu[i].name)==0)
       {
          flag = 0;
          return i;
       }

   }
   flag = 1;
   return index1+1;
}

int swap(char *p)//将字符串类型的题目编号转换为int
{
   int sum = 0;
   int i=0;
   int beilv;
   while(i!=4)
   {
    if(i==0) beilv = 1000;
    else if(i==1) beilv =100;
    else if(i==2) beilv = 10;
    else beilv = 1;
    sum+=beilv*(*(p+i)-'0');
    i++;
   }
   return sum;

}

bool cmp(const node a,const node b)//比较函数
{
    if(a.name<b.name)
    return true;
    else  return false;
}

void output()//输出函数
{

   for(int i=0;i<=index1;i++)
   {
         int sum  = 0;

         for(int j =0;j<6;j++)
         {
               sum+=stu[i].score[j];
         }


         printf("%s ",stu[i].name);
         printf("%d\n",sum);
   }

}
int main()
{
     freopen("1.txt","r",stdin);
     scanf("%d",&T);
     getchar();
     index1=-1;
     init();
     while(T--)
     {
        gets(s);
        char *tok = strtok(s,"_.");
        int temp;
        int a = 0;
        int id;
        while(tok!=NULL)
        {

            if(a==1)//如果是第二个字符串
            {
                temp = search(stu,tok);
                   if(flag)
                    {
                    strcpy(stu[temp].name,tok);
                    }
            }


            if(a==2)//如果是第三个字符串
            {
                char *exeID = strtok(NULL,"_.");
                id = swap(exeID);
                switch(*tok)
                {

                    case 'A':
                    if(stu[temp].ex[id-1038]==0)
                    stu[temp].score[id-1038] = 100;
                    else stu[temp].score[id-1038] = 95;
                    break;

                    case 'P':
                    if(stu[temp].score[id-1038]<90)
                    {
                        stu[temp].score[id-1038] = 90;
                        stu[temp].ex[id-1038] = 1;
                    }
                    break;

                    case 'W':
                    if(stu[temp].score[id-1038]<70)
                    {
                        stu[temp].score[id-1038] = 70;
                        stu[temp].ex[id-1038] = 1;
                    }
                    break;

                    case 'C':
                    if(stu[temp].score[id-1038]<50)
                    {
                        stu[temp].score[id-1038] = 50;
                        stu[temp].ex[id-1038] = 1;
                    }
                    break;

                }
            }

            tok = strtok(NULL,"_.");
            a++;
        }
        if(flag)
        index1++;
    }
     sort(stu,stu+index1+1,cmp);//按照字符排序
     output();
     return 0;
}

上面的代码错误之处出在如果在 AuthorID中出现Acce_haha的类此字符串

就会出现悲剧的错误,于是乎本题就不能用strtok函数了

要自己亲手处理字符串了,下面是处理的悲剧过程

首先给出介绍substr函数的介绍

#include <iostream>
#include <string>
using namespace std;
int main ()
{
  string str="We think in generalities, but we live in details.";
                                           // (quoting Alfred N. Whitehead)

  string str2 = str.substr (12,12);   // "generalities"
  unsigned pos = str.find("live");         // position of "live" in str

  string str3 = str.substr (pos);     // get from "live" to the end

  cout << str2 << endl<< str3 << '\n';

  return 0;
}
 

string::substr

substr是C++下string类的一个方法,通过string对象进行调用,当用两个参数时,表示从start开始的len个字符被

截取(包括start,并且字符串是从0开始计数的)。

当只有一个地址的时候,表示从改地址直到结束

另外例程中使用了string类的find方法

find方法的返回值是字符串的左边第一个开头字符的位置

#include <iostream>

using namespace std;

int main()
{
    char a[100] = "Welcome to UESTC!";
    string s =a;
    unsigned int b = s.find("to");
    cout <<s.substr(b)<< endl;
    return 0;
}

string类型的变量也是可以通过char类型的数组来直接进行赋值的。

 花了半天时间写了下面的代码

解决了上面的bug不过还是wa

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

struct node
{
    char name[55];//auther id
    int  score[6];//每个题目对应的得分
    int ex[6];//用于记录是否是第一次提交
}stu[2005];

int T,index1,flag;
char s[2000];

void init() //初始化
{
    for(int i =0;i<T;i++)
    {
        //memset(stu[i].ex,0,sizeof(stu[i].ex));
        //memset(stu[i].score,0,sizeof(stu[i].score));
        stu[i].ex[0]=0;
        stu[i].ex[1]=0;
        stu[i].ex[2]=0;
        stu[i].ex[3]=0;
        stu[i].ex[4]=0;
        stu[i].ex[5]=0;

        stu[i].score[0]=0;
        stu[i].score[1]=0;
        stu[i].score[2]=0;
        stu[i].score[3]=0;
        stu[i].score[4]=0;
        stu[i].score[5]=0;
    }

}

int search(struct node stu[],char tok[])
{
   for( int i=0;i<=index1;i++)
   {
       if(strcmp(tok,stu[i].name)==0)
       {
          flag = 0;
          return i;
       }
   }
   flag = 1;
   return index1+1;
}



bool cmp(const node a,const node b)
{
    if(strcmp(a.name,b.name)<=0)
    return true;
    else  return false;
}

void output()
{

   for(int i=0;i<=index1;i++)
   {
         int sum  = 0;
         for(int j =0;j<6;j++)
         {
               sum+=stu[i].score[j];
         }
         printf("%s ",stu[i].name);
         printf("%d\n",sum);
   }
   //printf("\n");

}

int main()
{
     freopen("1.txt","r",stdin);
     int i,j,id,start,end,temp;
     char key;
     scanf("%d",&T);
     getchar();
     index1=-1;
     init();

     while(T--)
     {
        gets(s);
        int len = strlen(s);

        i=len-1;
        while(s[i]!='.') i--;


        id = 0;
        id+=s[i-1]-'0';
        id+=(s[i-2]-'0')*10;
        id+=(s[i-3]-'0')*100;
        id+=(s[i-4]-'0')*1000;

        j =i-6;
        while(s[j]!='_')j--;
        key = s[j+1];

        end = j-1;

        i=0;
        while(s[i]!='_') i++;
        start = i+1;

        char ss[55];

        for(j=0,i=start;i<=end;i++,j++)
        ss[j]=s[i];
        ss[j]='\0';

        temp = search(stu,ss);
        if(flag)
        strcpy(stu[temp].name,ss);

        switch(key)
        {

            case 'A':
                if(stu[temp].ex[id-1038]==0)
                stu[temp].score[id-1038] = 100;
                else stu[temp].score[id-1038] = 95;
                stu[temp].ex[id-1038] = 1;
            break;

            case 'P':
                if(stu[temp].score[id-1038]<90)
                {
                    stu[temp].score[id-1038] = 90;
                    stu[temp].ex[id-1038] = 1;
                }
            break;

            case 'W':
                if(stu[temp].score[id-1038]<70)
                {
                    stu[temp].score[id-1038] = 70;
                    stu[temp].ex[id-1038] = 1;
                }
            break;

            case 'C':
                if(stu[temp].score[id-1038]<50)
                {
                    stu[temp].score[id-1038] = 50;
                    stu[temp].ex[id-1038] = 1;
                }
            break;

        }
        if(flag)
        index1++;
      }
     sort(stu,stu+index1+1,cmp);//按照字符排序
     output();
     return 0;
}

经过分析求证询问找出另一个问题,这个问题存在于题目本身,题目本身就是又bug的

题目的真是意图是RunID也是有用处的,我默认给出数据的顺序就是提交的顺序(事实上从题目表面意思来看就是这个意思的)

而事实上不是的RunID才是真正的提交顺序,因此还要对RunID进行排序

在书写过程中又发现了一个问题

C++的string类型是可以直接通过> < 来进行比较的,但是char []  字符串只能通过字符串比较函数strcmp来进行比较

各种纠结哈!求解救!

switch()

case 1:  呵呵





你可能感兴趣的:(字符串)