微软的一款代码编辑器 VS Code 需要在编辑代码时将代码高亮。其中,有一个子问题是判断一串文本是否是 一个合法字符串。一个合法字符串是指由一对单引号或一对双引号包裹的文本字符集,字符集包括所有英文小写字母、单引号、双引号和斜杠(\)。
比如"abc"、'ab"c’都是一个合法的字符串,而"abc"de"、‘ab’'c’和abc都不是一个合法的字符串。
字符串中可能有转义字符,转义字符只有 33 种:"、’ 和 \,分别表示:字符串中的双引号、单引号和斜杠。
当字符串由 双引号 包裹时,字符串中的 双引号 必须以转义字符出现,否则会被认为是不合法字符串;
当字符串由 单引号 包裹时,字符串的 单引号 必须以转义字符出现,否则会被认为是不合法字符串;
字符串中的斜杠(\)必须以转义字符出现,否则会被认为是不合法字符串。
输入格式
只有一行,表示输入的文本,文本的长度 lenlen 满足 1 \leq len \leq 100001≤len≤10000。保证输入只包含英文小写字母、单引号、双引号和斜杠(\)。
输出格式
如果输入的一串文本是一个合法的字符串,则输出Yes,否则输出No。
样例输入1
“abc”
样例输出1
Yes
样例输入2
“abc”“def”
样例输出2
No
样例输入3
“ab\c”
样例输出3
No
这道题相当的坑,考虑的比较多,首先你需要知道如何判断第一个字符是不是左单引号,判断方法是 if(a=='\'')
其中 \'
为'
的转义字符,本质上是相同的,还有就是\
的转义字符为\\
,其次要考虑一种情况是这个样例:"ab\\"a"
,普通的判断的话吗,这个样例很难过,我的解决方法是把已经配对过的字符给改变了,标记的话应该也可以,还需要注意是在双引号的包裹下,还是在单引号的包裹下,这两种需要考虑的情况是不一样的,比如在双引号下可以有单引号,在单引号包裹下可以有双引号,我当时写的时候没过的样例有:'\'
,"ab\\"a"
,"\""
,""
,"
好了接下来就上代码吧:
#include<stdio.h>
#include<string.h>
int main()
{
int i,j,flag,len,flag1,f1,f2;
char str[20000];
while(~scanf("%s",str))
{
flag=flag1=f1=f2=0;
len=strlen(str);
if(len<2)
printf("No\n");
else if(str[0]=='"'&&str[len-1]=='"'||str[0]=='\''&&str[len-1]=='\'')
{
if(str[0]=='"')
f1=1;//表示的是在双引号的包裹下
if(str[0]=='\'')
f2=1;//表示的是在单引号的包裹下
flag=1;
}
if(flag==0&&len>=2)//首尾对不上的情况下则直接输出
printf("No\n");
if(len==2&&flag==1)
printf("Yes\n");
if(flag==1&&len>2)
{
for(i=1;i<len-1;i++)//注意我这里是直接从中间开始的跳过了首尾字符
{
if(str[i]=='#')
continue;
if(f1==1)//在双引号包裹的情况
{
/*如果中间出现了双引号,并且其前一
个字符不为\,就表示这个双引号不是以转义字符出现*/
if(str[i]=='"'&&str[i-1]!='\\')
flag1=1;
if(str[i]=='"'&&str[i-1]=='\\')//把已配对的转义字符给换成其他的字符
{
str[i]='#';
str[i-1]='#';
}
}
if(f2==1)
{
if(str[i]=='\''&&str[i-1]!='\\')
flag1=1;
if(str[i]=='\''&&str[i-1]=='\\')
{
str[i]='#';
str[i-1]='#';
}
}
if(str[i]=='\\')//如果这个字符是\
{
if(str[i+1]!='\''&&str[i+1]!='"'&&str[i+1]!='\\')//就需要知道它的下一个字符是否能跟它构成转义字符
flag1=1;
if(str[i+1]=='\''||str[i+1]=='"'||str[i+1]=='\\')
{
if(i+1==len-1)
flag1=1;//这里就是为了过'\'这个样例
str[i]='#';
if((i+1)!=len-1)
str[i+1]='#';
}
}
}
if(flag1==0)
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}