任务描述
任务背景
我们在编写程序时,代码在通常情况下都是平台无关的。但是,在某些情况下,某一些代码是和平台相关的,比如 SSE intrinsics 函数(是一组函数,主要是把 x86 汇编封装成了函数,一个函数对应一个 x86 汇编)的底层实现是 x86 汇编,所以该类函数只能够在 x86 平台运行。
针对上述情况,当我们在代码中需要用到这些函数的时候,就要用 x86 相关的宏来标示和控制该代码段,保证该代码段不会在非 x86 平台上运行。
x86 宏的使用
除了上一关提到的 __x86_64__ 这个预定义的 x86 宏外,还有很多其他预定义的 x86 宏,其他一些 x86 宏如下所示:
__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__
__X86__
_X86_
本赛题共涉及 25 个宏,宏的定义和使用规则与第一阶段规则一样,只是其中的__x86_64__ 可以替换为上述中的其他预定义宏,详细信息请见第一关的相关知识介绍。
本关任务
任务要求
本赛题提供了多个使用 C 语言编写的代码片段文件,其中部分代码片段中包含了只能在 x86 平台运行的代码,这些代码会通过相应的宏来标示。
本赛题要求编写代码,读取控制台输入的代码片段文件,识别出该文件中所有通过任何 x86 相关的宏标示的只能在 x86 平台上运行的代码,并打印输出代码文件中只能在 x86 平台上运行的代码的起始行与结束行的行号,若无 x86 相关代码则输出NULL
。
注意:本题中,输出结果中起始行和结束行为实际在 x86 平台运行的代码的起始行和结束行,不包括 if defined
和else
等宏定义所在的代码行,具体参考下面的示例。此外,题目测试集所提供的代码片段文件中代码的书写格式与下面给出的参考示例文件相同。
评测示例
(1) test.c 文件内容如下:
#include <stdio.h>
#include <string.h>
int main()
{
#if defined(__ATOMIC_HLE_ACQUIRE)
printf("The platform is __ATOMIC_HLE_ACQUIRE. ");
#endif
#if defined(__ATOMIC_HLE_RELEASE)
printf("The platform is __ATOMIC_HLE_RELEASE. ");
#endif
#if !defined(__DECIMAL_BID_FORMAT__)
printf("The platform is __DECIMAL_BID_FORMAT__. ");
#endif
return 0;
}
输出为:
起始行为7,结束行为8。
起始行为12,结束行为12。
(2) test.c 文件内容如下:
#include <stdio.h>
#include <string.h>
int main()
{
#if defined(__AAAA_bbbb_cccc_DDDD)
printf("The platform is__AAAA_bbbb_cccc_DDDD. ");
#endif
输出为:NULL
本题不需考虑宏定义的嵌套语句,即类似下面的代码示例:
int main()
{
#if defined(__x86_64__)
#ifdef __x86_64__
printf("The platform is x86_64. ");
printf("This is a test case. ");
#endif
#endif
return 0
}
测试说明
在右侧编辑器中完成代码编写,识别每个代码片段中只能在 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 ##########
开始你的任务吧,祝你成功!