百度之星 2016 problem e 输入处理

*本文并不会给出全部的实现,只借助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*

你可能感兴趣的:(百度之星 2016 problem e 输入处理)