第三届全国高校绿色计算机大赛(初赛题目)

任务描述

任务背景

我们在编写程序时,代码在通常情况下都是平台无关的。但是,在某些情况下,某一些代码是和平台相关的,比如 SSE intrinsics 函数(是一组函数,主要是把 x86 汇编封装成了函数,一个函数对应一个 x86 汇编)的底层实现是 x86 汇编,所以该类函数只能够在 x86 平台运行。

针对上述情况,当我们在代码中需要用到这些函数的时候,就要用 x86 相关的宏来标示和控制该代码段,保证该代码段不会在非 x86 平台上运行。

x86 宏的使用

除了上一关提到的 __x86_64__ 这个预定义的 x86 宏外,还有很多其他预定义的 x86 宏,其他一些 x86 宏如下所示:

  1. __ATOMIC_HLE_ACQUIRE
  2. __ATOMIC_HLE_RELEASE
  3. __DECIMAL_BID_FORMAT__
  4. __FXSR__
  5. __GCC_ASM_FLAG_OUTPUTS__
  6. __MMX__
  7. __SEG_FS
  8. __SEG_GS
  9. __SIZEOF_FLOAT128__
  10. __SIZEOF_FLOAT80__
  11. __SSE2_MATH__
  12. __SSE2__
  13. __SSE_MATH__
  14. __SSE__
  15. __amd64
  16. __amd64__
  17. __code_model_small__
  18. __k8
  19. __k8__
  20. __x86_64
  21. __x86_64__
  22. i386
  23. __i386__
  24. __X86__
  25. _X86_

本赛题共涉及 25 个宏,宏的定义和使用规则与第一阶段规则一样,只是其中的__x86_64__ 可以替换为上述中的其他预定义宏,详细信息请见第一关的相关知识介绍。

本关任务

任务要求

本赛题提供了多个使用 C 语言编写的代码片段文件,其中部分代码片段中包含了只能在 x86 平台运行的代码,这些代码会通过相应的宏来标示。

本赛题要求编写代码,读取控制台输入的代码片段文件,识别出该文件中所有通过任何 x86 相关的宏标示的只能在 x86 平台上运行的代码,并打印输出代码文件中只能在 x86 平台上运行的代码的起始行与结束行的行号,若无 x86 相关代码则输出NULL

注意:本题中,输出结果中起始行和结束行为实际在 x86 平台运行的代码的起始行和结束行,不包括 if definedelse等宏定义所在的代码行,具体参考下面的示例。此外,题目测试集所提供的代码片段文件中代码的书写格式与下面给出的参考示例文件相同。

评测示例

(1) test.c 文件内容如下:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. #if defined(__ATOMIC_HLE_ACQUIRE)
  6. printf("The platform is __ATOMIC_HLE_ACQUIRE. ");
  7. #endif
  8. #if defined(__ATOMIC_HLE_RELEASE)
  9. printf("The platform is __ATOMIC_HLE_RELEASE. ");
  10. #endif
  11. #if !defined(__DECIMAL_BID_FORMAT__)
  12. printf("The platform is __DECIMAL_BID_FORMAT__. ");
  13. #endif
  14. return 0;
  15. }

输出为:

  1. 起始行为7,结束行为8
  2. 起始行为12,结束行为12

(2) test.c 文件内容如下:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. #if defined(__AAAA_bbbb_cccc_DDDD)
  6. printf("The platform is__AAAA_bbbb_cccc_DDDD. ");
  7. #endif

输出为:NULL

本题不需考虑宏定义的嵌套语句,即类似下面的代码示例:

  1. int main()
  2. {
  3. #if defined(__x86_64__)
  4. #ifdef __x86_64__
  5. printf("The platform is x86_64. ");
  6. printf("This is a test case. ");
  7. #endif
  8. #endif
  9. return 0
  10. }

测试说明

在右侧编辑器中完成代码编写,识别每个代码片段中只能在 x86 平台上运行的代码段,参照示例打印输出相关代码的起始行和结束行。完成代码后点击评测,平台将运行你的代码进行测试,如果与预期输出一致,则算通过相应的测试用例。

#include <bits/stdc++.h>//沿用上一道题目的思路

using namespace std;

string files;

long long int k[1000000],h[1000000];

int l=0,q;

string a[25]=

{

    "__ATOMIC_HLE_ACQUIRE",

    "__ATOMIC_HLE_RELEASE",

    "__DECIMAL_BID_FORMAT__",

    "__FXSR__",

    "__GCC_ASM_FLAG_OUTPUTS__",

    "__MMX__",

    "__SEG_FS",

    "__SEG_GS",

    "__SIZEOF_FLOAT128__",

    "__SIZEOF_FLOAT80__",

    "__SSE2_MATH__",

    "__SSE2__",

    "__SSE_MATH__",

    "__SSE__",

    "__amd64",

    "__amd64__",

    "__code_model_small__",

    "__k8",

    "__k8__",

    "__x86_64",

    "__x86_64__",

    "i386",

    "__i386__"

};

void fun(string t)

{

    int sum=0,flag=0;

    ifstream ifile;

    ifile.open(files.data());

    string s;

    while(getline(ifile,s))//将特定的名字用变量替换掉即可

    {

        sum++;

        string s1=s.substr(0,("#if defined("+t+")").length());

        string s2=s.substr(0, ("#if !defined("+t+")").length());

        string s3=s.substr(0, ("#ifdef "+t).length());

        string s4=s.substr(0, ("#ifndef "+t).length());

        string s5=s.substr(0, ("#elif defined("+t+")").length());

        string s6=s.substr(0, ("#elif !defined("+t+")").length());

        string s7=s.substr(0, 5);

        string s8=s.substr(0, 6);

        if((s1=="#if defined("+t+")") || (s3=="#ifdef "+t && s[("#ifdef "+t).length()]!='_') || (s5=="#elif defined("+t+")"))

        {

            //判断条件加一个s[("#ifdef "+t).length()]!='_')否则会区分不出xxx和xxx_

            k[q]=sum+1;

            l++;

            flag=2;

        }

        if(s8=="#endif" && flag==2)

        {

            h[q]=sum-1; q++;

            l++;

            flag=0;

        }

        if(s8=="#endif")

            flag=0;

        if(s2=="#if !defined("+t+")" || s4=="#ifndef "+t || s6=="#elif !defined("+t+")")

            flag=1;

        if(s7=="#else" && flag==1)

        {

            k[q]=sum+1;

            l++;

            flag=2;

        }

    }

    ifile.close();  

}

int main()

{

    cin>>files;

    for(int i=0;i<25;i++)

        fun(a[i]);

    sort(k,k+1000000);//这里有一个很关键的思路:分别对两个数组(起始行的数组、结束行的数组)排序即可,然后两个数组同时输出即可(不会出现交错的问题)

    sort(h,h+1000000);

    for(int i=0;i<1000000;i++)

    {

        if(k[i]!=0)

            cout<<"起始行为"<<k[i]<<",";//输出数组k中的

        if(h[i]!=0)

        {

            cout<<"结束行为"<<h[i]<<"。";//输出数组h中的

            cout<<endl;

        }

    }

    if(l==0) cout<<"NULL";

    return 0;

}

//########## End ##########


开始你的任务吧,祝你成功!

这篇文章,是又一个故事的结束...
lazy's story is continuing.
原文地址:https://www.cnblogs.com/Hello-world-hello-lazy/p/13653014.html