*本文并不会给出全部的实现,只借助problem e,讨论一下输入处理
题目如下
小度熊是一个尽职尽责的程序熊,每天产出数千行的代码,代码当中存在很多判断条件。度熊想让自己代码中的这些条件不存在交集。为了简化问题,一个条件可以是一个『简单条件』或者是一个『复合条件』,简单条件由『变量』、『比较符』和『运算数』组成,其中『变量』是用小写字符表示的一串字符,『运算数』仅为整数,『运算符』包括:<、>、<=、>=、==。分别代表:小于、大于、小于等于、大于等于和等于关系。简单条件的格式固定,左边为变量名,中间为操作符,右边为数字。若干个『简单条件』中间通过英文逗号组成一个『复合条件』,各『简单条件』之间是逻辑与的关系,例如:
简单条件: a > 100 复合条件: duxiong < 1000 , a > 100
输入
这里包括一组测试数据,第一行一个正整数N(1≤N≤1000),接下来 N行,每行一个条件,条件可能是一个『简单条件』或者是一个『复合条件』。其中『变量』不会超过30个字符,『运算数』的绝对值在10,000以内。测试数据中,不同变量的数量不会超过30个。其中『变量』、『比较符』和『运算数』之前和之后都有可能出现若干空格字符。所有简单规则都是按照『变量』『比较符』『运算数』这样的顺序定义的,没有特例。
输出
对于第 i个条件,输出其与前i-1个条件是否存在交集非空的情况。如果不存在交集非空的其他条件,输出一行字符串:“unique”。否则按照从小到大的顺序输出与其存在非空交集的条件的编号,编号之间用空格分隔,最后一个编号末尾不加空格。各条件从1−N编号。
样例输入
4
a < 100
c > 99
b > 100 , b == 99 , c < 98
a < 1000, a >= 99
样例输出
unique
1
unique
1 2
完整的实现可以参考http://blog.csdn.net/chenzhenyu123456/article/details/51406976
这个题目中,输入的总行数固定,但每一行会出现多少个简单条件却并不固定,给输入处理带来了麻烦。上面链接中给出的方法是,采用先读取一整行,再一一分解出简单条件。
各位或许想的同我一样,会不会还有更好的办法?
再看代码之前,考虑这样一个问题:
in test.cpp
...
scanf("%d%d",&v,&u)//或者cin>>v>>u;
...
在控制台中,输入数字10,会发生什么?
什么也没发生。
那我们接着输入20 30会发生什么?
u被赋值为20?等等,按回车没?
在按下回车之前,所有的赋值都没有发生。
也就是 当按下回车后 ,缓冲区中第一个数赋值给v,第二个给u,还剩数字30还呆在缓冲区。
进入本题
当存在如下数据结构
typedef struct{
char var[32];//变量名
char op[4];//比较运算符
int one;
}node;//一个简单句
node complex[30];//一个复合句
对于本题的输入的存取,
若是简单句,我们可以:
scanf(“%s%s%d”, var, op, &one );
输入如下时,如何赋值给复合句结构体呢?
b > 100 , b == 99 , c < 98
难点在于当输入完一个简单句后,既可能输入’, ’ 也可能换行进入下一句——那么,就判断一下下一个字符 c==’,’还是 c==’\n’ 。所以,输入的处理就可以这么写:
#include
typedef struct{
char var[32];//变量名
char op[4];//比较运算符
int one;
}node;//简单句
const int MAX_N = 1024;
node all[MAX_N][30];//所有
int c[MAX_N];//每个复合句中,有多少简单句
int main()
{
int n;
scanf("%d", &n);
char tmp_ch;
for (int i = 0; i < n; ++i)
{
c[i] = 0;
int & top = c[i];
scanf("%s%s%d", all[i][top].var, all[i][top].op, &all[i][top].one );//存入一个简单句
top = 1;
while( 1 ){
tmp_ch=getchar();
if(tmp_ch=='\n' ) break;
if(tmp_ch!=',' ) continue;//
scanf("%s%s%d", all[i][top].var, all[i][top].op, &all[i][top].one );//存入一个简单句
top ++;
}
}
return 0;
}
事实上,本篇想说明的是——在进行类似处理时,并不需要先读取一整行,再一一分解。
因为流是一个FIFO的数据结构,里面是已输入的所有数据。在按下回车键后,队首出队,赋值给相应变量,队首出队,赋值给相应变量…直到队首为空 or 类型不匹配 or 暂时没有数据需要被赋值。这个出队的过程,与( 直接读入一整行,再一一分解的过程),是一致的。
而大部分人选择 读入整行再进行分解,可能是因为对于 字符(char)输入函数的 不理解。
因为不同控制符 or 函数,读入的char, 其范围是有区别的。
最后给出一些字符类型(char)的输入函数:
char ch;
scanf(“%c”,&ch);//会匹配任意一个字符x
scanf(” %c”,&ch);//会匹配非空白字符(排除了 ‘\n’ ‘\t’ 空格 等)
ch = getchar();//会匹配任意一个字符x
例:
int main()
{
char ch;
//改成ch = getchar() 时,对于同样的输入,有相同输出
while( scanf(“%c” ,&ch)!=EOF )
printf(“%c*”,ch );
return 0;
}
输入为 1 2223 并按下回车时,输出为
1* 2*2*2*3
*
(ch被赋值两次,第一次’a’,第二次是’\n’)
当程序如下修改(注意控制符” %c”中的空格)
int main()
{
char ch;
while( scanf(” %c” , &ch)!=EOF )
printf(“%c*”, ch );
return 0;
}
输入
1 2223 4 5
输出
1*2*2*2*3*4*5*