一无是处杜某某

或许是东川路第一老实人

2019年,上海交通大学工科平台(工科试验班)建设进入第5个年头。

2014级开始招第一届工科试验班,共有8个学院23个专业。
2015级软件工程、化学工程与工艺和核工程与核技术退出试验班专业名录。
2016级取消招生时的面试,生物工程退出试验班专业目录。
2017级软件工程重回试验班,建筑学纳入试验班高考招生,在上海将除特定试点班外的工科全部纳入工科试验班。
2018级工科大平台推广到全校工科专业,专业预选后试验班被打散。

当我查阅《上海交通大学年鉴》的时候,翻阅到了一些试验班的新闻片段。现张贴如下:

……依托试点学院探索工科试验班类提前批招生新模式。……工科大平台面向全国12个省市招收了407名(含贫困专项定向招生21人)学生。共有八个学院的23个工科专业参与平台建设,专业预选前三志愿满足率达到98%。——《上海交通大学年鉴2015》

继续实施基于试点学院改革的工科大类提前批招生工作。在部分省(市)高考本科第一批次前投放理科计划,以“工科试验班类”为代码,采用综合评价方式招生,纳入到学校“工科创新人才培养平台”进行培养,为对大工程学科有强烈兴趣、具有创新和发展潜质的学生提供更多进入上海交大的机会。……2014级工科平台专业分流进展顺利,共有63名学生实现了二次专业选择。2015级工科平台专业预选**前三志愿满足率达到了97.1%**。——《上海交通大学年鉴2016》

工科平台第一届学生已圆满结束平台学习期,2015级工科平台专业分流进展顺利,共有56名学生实现了二次专业选择,成功转专业比例达61%。在前两年运行成效显著的基础上,全校共有六个学院的19个专业参与工科平台建设,面向14个省市招收了735名学生,2016级工科平台专业预选前三志愿满足率达到了97.1%。——《上海交通大学年鉴2017》

2017级工科平台和生环平台专业分流进展顺利,2017级工科平台专业预选**前三志愿满足率达到98.64%。生环平台达到88.84%,二次分流成功转专业比例分别为70%和63%**。——《上海交通大学年鉴2018》

将上述数据和其他公开数据整理之后,成表如下:

这里需要解释一下“前三志愿满足率”。工科平台在进校第一个月结束的时候进行专业预选(注意这里不叫专业分流),需要按照顺序填写六个学院的志愿。按照2018级各学院预选人数表,假设所有人的前三志愿都是“电-机-船”(顺序无关),那么前三志愿满足率就有(524+268+150)/1122=83.96%。

关于转专业,2016级及以前的资料可以参见我的知乎回答。
2017上海交通大学工科大平台大一新生面临分流,学长学姐学的是什么专业,有什么建议吗?

2017级转专业结果可以参见下面的链接。
【专业分流】上海交通大学关于2017级工科平台专业分流结果公示的通知 - 上海交通大学 工科平台

2017级转入转出表

2017级转入专业录取名次区间表(不对数据真实性负责)

关于工科平台和非工科平台的对比,可以参见《上海交通大学2017-2018学年本科教学质量报告》。

2018年,工科平台首届毕业生毕业,学校对首届平台学生进行了学业跟踪调查,结果显示,①平台学生在学习成绩、知识层面上,整体水平和末端水平都较面上学生优异。②平台学生7种学习能力增长值均较面上工科学生大,特别是平台学生在工程设计能力、工程实践能力、集成创新能力的增长显著。受访学生中具有创新意识的平台学生比例明显高于面上学生,约为后者的三倍。③平台学生在5个方面学习素养的同期增长均优于面上学生。④学生普遍反映,通过平台的学习,具备了广阔的知识面,为后续专业学习、深造及就业提供了良好的知识储备;平台科学的课程体系设置,增强了学生的学习能力,调动了学生的学习主动性;平台的培养模式,扩大了学生的交际圈,不同专业同学可进行知识互补,学学相长。⑤工科平台学生平均GPA高于面上学生;出国深造和在国内深造的比例接近全部工科平台学生的三分之二,略高于非工科平台学生,学生培养了专业兴趣,保持了浓厚的继续深造势头。

本文提及资料来源:
上海交通大学2017-2018学年本科教学质量报告 - 本科教学质量报告 - 上海交通大学信息公开网
上海交通大学年鉴

本文为政治经济学课程作业。

2018年底,上海交通大学电子信息与电气工程学院召开第九次学生代表大会。

根据学院介绍,学代会是是学生维护权益的重要方式,也是学院和同学交流意见的重要渠道。从电院学生中选择一定的学生代表参与会议,代表应该是很光荣和有话语权的。会前学院学生会在各班通知选出代表参加学代会,然而根据实际情况来看,积极报名参加的学生寥寥无几。学生会事先考虑到了同学们的积极性不高,因此承诺参与学代会可以计入综合测评的素质拓展分数。按照电院综合测评条例,参与学代会可以获得1学分满分的素拓。在这种奖励下,各班凑齐了参与学代会的学生代表。

在学代会现场,第八届学生会主席做第八届学生会工作报告和第九届学代会筹备工作报告。按照事后的新闻稿的说法是“经代表审议后一致通过”,而现场实际上是氛围沉闷。工作人员请代表审阅并是否提出异议,少有人仔细聆听并无人提出异议。而后的主席团选举,各位候选人发布竞选演讲并展示“施政纲领”。各自的“施政纲领”大同小异,并无本质上的区别,因此选举中并未有压倒性的一边倒情况,各位候选人的得票较为平均。

从理性选择角度来分析,参与学代会的成本很大,而收益却很小。参加学代会意味着需要在临近期末的时候花掉周末中的一整个白天。对于交大学生来说,时间是稀缺的资源,一整天的时间成本确实很大。学代会还要求着正装出席,这对代表们又是一件增加成本的事情。而学代会的受益只有所谓的选举主席团和1分素拓。按照电院的综合测评条例来看,1分素拓分实在是有限。而所谓的选举主席团,如果真的要了解候选人的信息,代表们需要付出很大的代价。根据理性选择,参与学代会的成本大而受益小,因此积极性不高。

更加核心的问题在于,学代会选谁上主席团,对于学生而言并无本质区别。从表象来看,各位候选人的“施政纲领”大同小异,无本质区别。从候选人角度来看,按照理性选择观点,候选人的“纲领”不能过于激进,需要靠近中间代表。因此各自的差异就非常小,代表们选谁都没什么区别。从实质来看,学生会的权力实在是太小,并不能在学生事务上做主。各项和学生有关的事项均是由学院负责老师和领导决定,学生会只能传达上面的政策和反馈下面的意见,更多时候并不会进行反馈。学生会的日常就是主持承办各种文体活动,这和学生的利益并没有太大关系。所以选举主席团并没有能给学生带来很大的收益。

综上所述,按照理性选择分析学代会的成本和收益,就能够解释学代会中的积极性不高的现象。

时光飞逝,转眼已是2019年。在交大已经生活学习了近3年的我,已经开始面对未来的选择了。大三上这一学期经历了很多事情,做了许多工作,也有许多不足的反思,值得细细总结。新的一学期已经开始,面对未来的发展方向,我需要有一些计划,并为之付出行动了。

整个学期,对于必修课而言,脱离了基础课的学习,进入了专业课的学习,我需要适应各课程老师的风格与节奏。对于某些课程,我很好地跟随老师的教学,最终取得了高分。而对于另外一些课程,自己没能妥善安排,加上长期存在的“数学恐惧症”,没能拿到高分。除此之外,凭借着选课系统对于高年级的优先级,在必修课以外,我相较于前几学期,更多地按照兴趣选择了一些课程。这些选修课对我一些技能和视野的开阔还是取得了比较好的效果。

在其他方面,我比较喜欢数学建模比赛,因此积极地参加了国赛、美赛,都有精心准备并参与其中。另外,由于我比较喜欢水群,经常活跃在新生群里面,我担任了生活园区C++学业辅导员。别人看来或许会很费时间,然而对我而言,我觉得这种事情却能给我带来存在感和满足感。

对于课程学业而言,或许我是一直以来就存在着只盯着平均分看,对自己要求不高,期望值较低这种问题,因此最终的成绩反映出来也就仅仅对得上这种低要求。回想大一大二的时候,对待课程基本上就是完成作业,然后期末前简单复习一下就完事。这种状态一直持续下来,每学期面对相比于上学期都在增加的学积分沾沾自喜,至于当我面对排名的时候,却发现虽然大家都在进步,但是同学们的进步幅度比我大很多。

在新的学期里面,首先我要做的事情是继续提高课业成绩,圆满完成这学期的必修课任务。这方面主要需要合理安排时间,紧凑而不失节奏地安排好课程。另外还要在课余时间进行项目的准备,自我探索的实践。而且这学期前半学期的时间相当充裕,而后半学期的时间比较紧张。对于我来说,常常会在时间宽松充裕的时候白白浪费时间。因此,不浪费时间也是一个巨大的挑战。

我希望,当我在本学期结束的时候,各方面都能达到自己设定的目标,各项决定都不留下遗憾。这个希望听起来简单,但是实施起来却不是那么容易。不管怎么样,我还是拭目以待吧。

一、环境

项目 内容
系统 Ubuntu 18.04 (Windows Subsystem for Linux), Windows 10 Home, version 1809
GCC Ubuntu 7.3.0-27ubuntu1~18.04
Python Python 2.7.15 [GCC 7.3.0] :: Anaconda, Inc. on linux2
flex flex 2.6.4

二、功能实现

1、指数转换

首先,分析Python中指数的可能形式。

由于题目中的Python 版本为2.7,通过查询Python 2.7相关文档( https://docs.python.org/2.7/reference/lexical_analysis.html ),获得浮点数的相关词法定义。

1
2
3
4
5
6
floatnumber   ::=  pointfloat | exponentfloat
pointfloat ::= [intpart] fraction | intpart "."
exponentfloat ::= (intpart | pointfloat) exponent
intpart ::= digit+
fraction ::= "." digit+
exponent ::= ("e" | "E") ["+" | "-"] digit+

如下为一些浮点数的形式:

1
3.14    10.    .001    1e100    3.14e-10    0e0

可以看出,Python中指数的形式可以描述为:(整数部分|浮点数)(e|E)[-+]?整数部分。其中,整数部分允许前导0,浮点数允许省略0.X开头的0 X.0结尾的0e可以为大写也可以为小写,e之后可以或者省略紧跟+-表示指数次数的正负,而后的次数只能为整数,整个数字中间不存在空格。

下面给出单个数字、整数部分、浮点数和指数在LEX中的规则:

1
digit [0-9]
1
intpart {digit}+
1
pointfloat ({intpart}?[.]{intpart})|({intpart}[.])
1
exponentfloat ({intpart}|{pointfloat})(e|E)([-+]?){intpart}

当匹配到exponentfloat时,将其转换为小数并写入输出流。下面给出匹配到exponentfloat时的程序操作:

1
2
3
4
5
{exponentfloat} {
int precision = 0;
double decimal = str2double(yytext, 0, yyleng, &precision);
printByPrecision(decimal, precision);
}

str2double是把字符串中sted范围内的子串转换成浮点数并返回其小数位数的函数。函数原型如下,具体实现见附录:

1
double str2double(const char *str, int st, int ed, int * precision);

printByPrecision是给出浮点数及其精度,去掉小数点后多余的0后输出的函数,最少有一位小数。函数定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void printByPrecision(double x, int precision)
{
char buffer[20] = {0};
sprintf(buffer, "%.*lf", precision, x);
int len = strlen(buffer);
for (int i = len - 1; i >= 0; i--)
{
if (buffer[i] == '0')
precision--;
else
break;
}
if (precision == 0)
precision++;
printf("%.*lf", precision, x);
}

将程序作用到题目所给的test.py,执行结果如下:

1
2
3
4
5
6
7
> flex flex.l
> gcc lex.yy.c -lfl
> ./a.out <test.py >result.py
> python ./test.py
10000000000.0 0.05 579 3399.95 45.73
> python ./result.py
10000000000.0 0.05 579 3399.95 45.73

result.py内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python 

def main():
a = 10000000000.0
b = 0.05
c = 123+456
d = 3400.0-0.05
e = 34+800.0+0.73-789
print a,b,c,d,e

if __name__ == '__main__':
main()

2、加减法计算

在上一问的基础上,只需要识别加减表达式即可。在这里我考虑了变量与常量混合的情况,并且忽略+-连续出现而没有运算数的情况。

在只考虑十进制的情况下,表达式可以用描述为,以-+符号或者-+符号连接上数字或者变量开头,随后紧跟0个或者若干个由-+符号连接上数字或者变量的算式。在LEX中的规则可以定义为:

1
decimalinteger ([1-9][0-9]*)|0
1
numeric {decimalinteger}|{pointfloat}|{exponentfloat}
1
alphabet [a-zA-Z]
1
variable ({alphabet}|_)+({numeric}|{alphabet}|_)*
1
expression [-+]?({numeric}|{variable})([-+]({numeric}|{variable}))*

当匹配到expression时,需要将其计算出结果,并写入到输出流中。考虑到实际代码中整数和浮点数的内存占用不同,这里需要将整数与浮点数区别开考虑。表达式参与计算的值如果全部为整数,得到的结果也应该是整数,如果有浮点数参与运算,那么结果就应该是浮点数。对于整数,这里假设其范围在-2147483648~2147483647之间,即C语言中int类型的范围。

下面给出匹配到expression时的程序操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
{expression} {
int st = 0, flag = 1; //st:当前数字的在字符串中开始的位置,flag:需要加还是减

int hasVar = 0;
//判断是否有变量
for (int i = 0; i < yyleng; i++)
{
if ((yytext[i] == '+' || yytext[i] == '-') && !(yytext[i + 1] >= '0' && yytext[i + 1] <= '9' || yytext[i + 1] == '.'))
{
ECHO;
hasVar = 1;
break;
}
}

if (!hasVar)
{
int isfloat = 0; //是否作为浮点数进行计算
for (int i = 0; i < yyleng; i++)
{
if (yytext[i] == '.' || yytext[i] == 'e' || yytext[i] == 'E')
{
isfloat = 1;
break;
}
}
if (isfloat)
{
int maxprecision = 0, precision = 0;
double sum = 0; //运算结果
for (int i = 0; i < yyleng; i++)
{
//遇到+-号就可以判断数字的起止位置
if (yytext[i] == '+' || yytext[i] == '-')
{
//如果是第一个符号,那么不进行计算,只更改符号
if (i == 0)
{
flag = (yytext[i] == '+') ? 1 : -1;
st = i + 1;
}
//如果前面不是E,那么进行计算,如果是E的话,认为是数字的一部分,交给str2double处理
else if (yytext[i - 1] != 'E' && yytext[i - 1] != 'e')
{
double tmp = str2double(yytext, st, i, &precision);
if (precision > maxprecision)
maxprecision = precision;
sum += tmp * flag;
flag = (yytext[i] == '+') ? 1 : -1;
st = i + 1;
}
}
//遇到匹配末尾
if (i == yyleng - 1)
{
double tmp = str2double(yytext, st, yyleng, &precision);
if (precision > maxprecision)
maxprecision = precision;
sum += tmp * flag;
}
}
printByPrecision(sum, maxprecision);
}
else
{
int sum = 0; //运算结果
for (int i = 0; i < yyleng; i++)
{
//遇到+-号就可以判断数字的起止位置
if (yytext[i] == '+' || yytext[i] == '-')
{
//如果不是第一个符号,进行计算
if (i != 0)
{
int tmp = str2int(yytext, st, i);
sum += tmp * flag;
}
//整数情况下不存在E
flag = (yytext[i] == '+') ? 1 : -1;
st = i + 1;
}
//遇到匹配末尾了
if (i == yyleng - 1)
{
int tmp = str2int(yytext, st, yyleng);
sum += tmp * flag;
}
}
printf("%d", sum);
}
}
}

str2int是把字符串中sted范围内的子串转换成整数的函数。函数原型如下,具体实现见附录:

1
int str2int(const char *str, int st, int ed);

将程序作用到题目所给的test.py,执行结果如下:

1
2
3
4
5
6
7
> flex flex.l
> gcc lex.yy.c -lfl
> ./a.out <test.py >result.py
> python ./test.py
10000000000.0 0.05 579 3399.95 45.73
> python ./result.py
10000000000.0 0.05 579 3399.95 45.73

result.py内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python 

def main():
a = 10000000000.0
b = 0.05
c = 579
d = 3399.95
e = 45.73
print a,b,c,d,e

if __name__ == '__main__':
main()

3、更多case

下面是一个考虑了更多情况的测试文件test2.py

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python 

def main():
a = 1e+2+3
b = .53e3+100.
c = 1+2+a
d = +1+2+3-4-2e-1
e = a+3+b+1e5
print 1+5
print a,b,c,d,e

if __name__ == '__main__':
main()

终端中执行结果如下:

1
2
3
4
5
6
7
8
9
> flex flex.l
> gcc lex.yy.c -lfl
> ./a.out <test2.py >result2.py
> python ./test2.py
6
103.0 630.0 106.0 1.8 100736.0
> python ./result2.py
6
103.0 630.0 106.0 1.8 100736.0

result2.py内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python 

def main():
a = 103.0
b = 630.0
c = 1+2+a
d = 1.8
e = a+3+b+1e5
print 6
print a,b,c,d,e

if __name__ == '__main__':
main()

三、感想

本次大作业利用LEX进行代码预处理。在实际操作中我先是简单的执行了书上给出的样例,观察了输出和匹配串的行为,然后再设计题目要求的功能。在处理浮点数时,最开始考虑的是在Python中进行尝试,然后总结出指数的正规式,基于自己总结的正规式完成了整个功能。后来在和同学交流中发现Python官网的文档里面有写指数的词法定义,于是对规则进行了完善。

在我的代码中,我对输入做了一定的假设。比如,假设输入的整数只能是C语言int类型的范围,不支持输入l表示长整型等。在输出的时候,由于double的精度问题,输出的小数默认都是6位,而题目样例中给的输出参考是1位或者2位的自适应长度。为了解决这个问题,特意在提取数值的时候求出浮点数的小数位数,并在表达式中取最大的一个精度,然后利用这个精度将求出的结果重新转换为字符串,最后删去末尾多余的0即可。

附:完整的flex.l代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int str2int(const char *str, int st, int ed)
{
int num = 0;
int base = 10;
for (int i = st; i < ed; i++)
{
num = num * base + str[i] - '0';
}
return num;
}

double str2double(const char *str, int st, int ed, int *precision)
{
int isfloat = 0; //是否作为浮点数进行计算
for (int i = st; i < ed; i++)
{
if (str[i] == '.' || str[i] == 'e' || str[i] == 'E')
{
isfloat = 1;
break;
}
}
if (!isfloat)
{
*precision = 0;
return str2int(str, st, ed);
}

double num1 = 0; //e之前的数值
int num2 = 0; //e之后的数值
int flag1 = 0, flag2 = 0; //flag1:是否在小数点后,flag2:是否在e之后
double e = 1; //小数点之后的权重
for (int i = st; i < ed; i++)
{
if (str[i] >= '0' && str[i] <= '9')
{
if (!flag1 && !flag2) //e以前,小数点前
num1 = num1 * 10 + (str[i] - '0');
else if (flag1 && !flag2) //e以前,小数点后
{
e = e / 10.0;
(*precision)++;
num1 = num1 + (str[i] - '0') * e;
}
else if (flag2) //e以后
num2 = num2 * 10 + (str[i] - '0');
}
else if (str[i] == '.')
{
flag1 = 1;
(*precision)++;
}
else if (str[i] == 'e' || str[i] == 'E')
flag2 = 1;
else if (str[i] == '-')
flag2 = 2;
}

if (e != 1)
(*precision)--;

double k = 1; //10的num2次方
if (flag2 == 1) //e之后是正幂次
{
(*precision) -= num2;
for (int i = 0; i < num2; i++)
k = k * 10;
}
else if (flag2 == 2) //e之后是负幂次
{
(*precision) += num2;
for (int i = 0; i < num2; i++)
k = k / 10;
}
if (*precision <= 0)
*precision = 1;
num1 = num1 * k;
return num1;
}

void printByPrecision(double x, int precision)
{
char buffer[20] = {0};
sprintf(buffer, "%.*lf", precision, x);
int len = strlen(buffer);
for (int i = len - 1; i >= 0; i--)
{
if (buffer[i] == '0')
precision--;
else
break;
}
if (precision == 0)
precision++;
printf("%.*lf", precision, x);
}

%}
digit [0-9]
intpart {digit}+
pointfloat ({intpart}?[.]{intpart})|({intpart}[.])
exponentfloat ({intpart}|{pointfloat})(e|E)[-+]?{intpart}
decimalinteger ([1-9][0-9]*)|0
numeric {decimalinteger}|{pointfloat}|{exponentfloat}
alphabet [a-zA-Z]
variable ({alphabet}|_)+({numeric}|{alphabet}|_)*
expression [-+]?({numeric}|{variable})([-+]({numeric}|{variable}))*
%%

{exponentfloat} {
int precision = 0;
double decimal = str2double(yytext, 0, yyleng, &precision);
printByPrecision(decimal, precision);
}

{variable} {
ECHO;
}

{expression} {
int st = 0, flag = 1; //st:当前数字的在字符串中开始的位置,flag:需要加还是减

int hasVar = 0;
//判断是否有变量
for (int i = 0; i < yyleng; i++)
{
if ((yytext[i] == '+' || yytext[i] == '-') && !(yytext[i + 1] >= '0' && yytext[i + 1] <= '9' || yytext[i + 1] == '.'))
{
ECHO;
hasVar = 1;
break;
}
}

if (!hasVar)
{
int isfloat = 0; //是否作为浮点数进行计算
for (int i = 0; i < yyleng; i++)
{
if (yytext[i] == '.' || yytext[i] == 'e' || yytext[i] == 'E')
{
isfloat = 1;
break;
}
}
if (isfloat)
{
int maxprecision = 0, precision = 0;
double sum = 0; //运算结果
for (int i = 0; i < yyleng; i++)
{
//遇到+-号就可以判断数字的起止位置
if (yytext[i] == '+' || yytext[i] == '-')
{
//如果是第一个符号,那么不进行计算,只更改符号
if (i == 0)
{
flag = (yytext[i] == '+') ? 1 : -1;
st = i + 1;
}
//如果前面不是E,那么进行计算,如果是E的话,认为是数字的一部分,交给str2double处理
else if (yytext[i - 1] != 'E' && yytext[i - 1] != 'e')
{
double tmp = str2double(yytext, st, i, &precision);
if (precision > maxprecision)
maxprecision = precision;
sum += tmp * flag;
flag = (yytext[i] == '+') ? 1 : -1;
st = i + 1;
}
}
//遇到匹配末尾
if (i == yyleng - 1)
{
double tmp = str2double(yytext, st, yyleng, &precision);
if (precision > maxprecision)
maxprecision = precision;
sum += tmp * flag;
}
}
printByPrecision(sum, maxprecision);
}
else
{
int sum = 0; //运算结果
for (int i = 0; i < yyleng; i++)
{
//遇到+-号就可以判断数字的起止位置
if (yytext[i] == '+' || yytext[i] == '-')
{
//如果不是第一个符号,进行计算
if (i != 0)
{
int tmp = str2int(yytext, st, i);
sum += tmp * flag;
}
//整数情况下不存在E
flag = (yytext[i] == '+') ? 1 : -1;
st = i + 1;
}
//遇到匹配末尾了
if (i == yyleng - 1)
{
int tmp = str2int(yytext, st, yyleng);
sum += tmp * flag;
}
}
printf("%d", sum);
}
}
}
%%

int main(void)
{
yylex();
return 0;
}

第一题

题目描述

以自己的学号建立序列$x[n]$,$x[n]={5,1,6,0,2,1,9,1,0,0,3,9},n={0,1,…,11}$。

  1. 画出$x[n]$的傅里叶变换$X(e^{jω})$的幅度和相位曲线;
  2. 画出$x[n]$的32点DFT $X[k]$,要求与(1)画在同一幅图上,验证频域取样关系;
  3. 画出$X[k]$经过32点IDFT得到的$x[n]$,验证DFT与IDFT的唯一性。

MATLAB代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
clear,clc;
N = 32; %点数
x = zeros(1,N);
x(1:12) = [5,1,6,0,2,1,9,1,0,0,3,9];
n = 0:N-1;
cnt = 1;
y = zeros(201);

%用fft和ifft函数求DFT和IDFT
f_y = fft(x,N);
f_x = 2*pi/N.*n;
n_x = ifft(f_y,N);

%求傅里叶变换
syms w;
y = sum(x.*exp(-1i*n*w));

%绘图
figure;
subplot(2,1,1)
fplot(abs(y),[0,2*pi])
hold on
stem(f_x,abs(f_y))

%设置坐标轴刻度与标题
xlabel('ω');
ylabel('幅值');
set(gca,'XTick',0:pi/2:2*pi)
set(gca,'xtickLabel',{'0','π/2','π','3π/2','2π'})
axis([0 pi*2 0 40])

subplot(2,1,2)
fplot(angle(y),[0,2*pi])

%设置坐标轴刻度与标题
xlabel('ω');
ylabel('相位');
set(gca,'XTick',0:pi/2:2*pi)
set(gca,'xtickLabel',{'0','π/2','π','3π/2','2π'})
set(gca,'YTick',-pi:pi/2:pi)
set(gca,'ytickLabel',{'-π','π/2','0','π/2','π'})
axis([0 pi*2 -pi pi])

figure;
stem(0:N-1,n_x); %32点IDFT
axis([0 31 0 10])

图像

第二题

题目描述

采用脉冲响应不变法设计一个巴特沃斯离散时间低通IIR滤波器,要求通带截止频率$ω_p=0.3π rad$,阻带截止频率$ω_s=0.4π rad$,通带最大衰减$α_p=1 dB$,阻带最小衰减$α_s=30 dB$。取$T_d=1$,给出滤波器阶数、连续时间和离散时间滤波器的系统函数,并画出连续时间和离散时间系统的对数幅度响应曲线和单位脉冲响应曲线。

阶数与系统函数

滤波器阶数$N=15$

连续时间滤波器系统函数为
$$
H_c(s) = \frac{\sum^{N}{k=0} b_k s^{N-k}} {\sum^{N}{k=0} a_k s^{N-k}},其中
\
a_k = [1,9.5497,45.5983,144.0774,336.2895,613.3351,\902.0572,1088.6924,1086.7497,897.2369,607.8823,\332.1113,141.7800,44.7113,9.3305,0.9735]
\
b_k = [0,0,0,0,0,0,0,0,\0,0,0,0,0,0,0,\0.973565591260273]
$$
离散时间滤波器系统函数
$$
H(z) = \frac{\sum^{N}{k=0} b_k z^{-k}} {\sum^{N}{k=0} a_k z^{-k}},其中
\
a_k = [1,-5.9705,17.9738,-35.5026,
\50.9018,-55.7017,47.8036,-32.6279,
\17.7990,-7.7395,2.6547,-0.7041,
\0.1395,-0.0194,0.0017,-7.122210^{-5}]
\
b_k=[-2.4429
10^{-8},1.180610^{-7},6.558710^{-6},0.0001,0.0009,
\0.0024,0.0027,0.0014,0.0003,4.0372e-05,1.726610^{-6},
\2.2229
10^{-8},2.824810^{-11},6.998710^{-13},0]
$$

MATLAB代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
clear,clc;
wp = 0.3*pi; ap = 1;
ws = 0.4*pi; as = 30;
Td = 1;
Wp = wp/Td;
Ws = ws/Td;
%求连续时间滤波器阶数和截止频率
[N,Wc] = buttord(Wp,Ws,ap,as,'s')
%连续时间滤波器系统函数
[Bs,As] = butter(N,Wc,'s');
%脉冲响应不变法得到离散滤波器系统函数
[Bz,Az] = impinvar(Bs,As,1/Td);
%绘图
width = 1.5;
[H,W] = freqs(Bs,As);
plot(W*Td/pi,20*(log10(abs(H))),'LineWidth',width);
hold on;
[H,w]=freqz(Bz,Az);
plot(w/pi,20*(log10(abs(H))),'LineWidth',width);
axis([0,1,-200,2]);
grid;
legend('离散','连续');
xlabel('ω(*π rad) Ω(*π rad/s)');
ylabel('幅值响应(dB)');
figure;
[h,n]=impz(Bz,Az);
stem(n,h,'LineWidth',width);
hold on;
g=tf(Bs,As);
[h1,t]=impulse(g,0:0.1:40);
plot(t,h1,'LineWidth',width);
legend('离散','连续');
axis([0,40,-0.3,0.5]);
xlabel('t(s)或n(样本)');
ylabel('单位脉冲响应');

图像

在G++(Code Blocks自带编译器)中,有时会报错undefined reference to 'XX'。而在VS中相同问题的可能报错“无法解析的外部符号,xxxx,该符号在函数XX中被引用”。需要明确的是,这个问题属于链接错误,不是编译错误,因此核心思想是看函数是不是只声明了而没有定义,和函数内部的代码无关。具体原因有几种,下面将分别列举原因与解决方法。

第一种情况:没写main函数

问题分析

报错信息为:undefine reference to 'WinMain'

看到这个报错,只有一种情况,就是没写main函数,找不到可执行程序的入口。

解决方法

在程序中写上main函数即可。

第二种情况:工程文件配置错误

问题分析

这种情况可能会出现在Code Blocks中,一般不会出现在Visual Studio中。

程序代码由多个.cpp文件和若干个.h文件组成,编译时只编译了main函数所在的cpp文件,没有编译(或者链接)上报错中函数的定义所在的cpp文件。

解决方法

  1. 在项目左侧Projects中找到当前工程,在工程名上右键,选择Properties…。

    如果左侧Workspace下为空,说明没有建立工程。请在菜单中File - New - Project…建立工程,并跳到第4步。

  2. 选择Build targets标签页,查看Debug(或者Default)下的Build target files,查看是否所有文件都被选中。

    如果文件都选中了,那么不是这种情况的问题。

  3. 如果有文件没有被选中的话,将其选中,然后点OK。

  4. 下一次在File - New - File的时候,出现下图的窗口时,记得全部勾上。

第三种情况:函数的声明和定义不匹配

问题分析

在这个例子中,Foo是一个类型,我们对其重载了<<运算符。

1
ostream& operator<<(ostream &os,const Foo &x);

但是我们在定义<<运算符重载的时候,写成了如下形式:

1
2
3
4
5
ostream& operator<<(ostream &os, Foo &x)	//这里缺了const
{
//TODO
return os;
}

函数的声明和定义并不匹配,因此会报错。而且这种报错只会出现在,函数已经声明,但没有其定义或者定义不匹配的时候。

如果没有声明函数的话,报错将会是No match for xxx。如果该函数是某个类的友元函数的话,会报XX is private错误。

解决方法

如果没有定义的话,定义函数。如果已经定义了函数的话,将函数的声明和定义保持一致。

第四种情况:类模板的函数声明和定义分离

问题分析

在之前的面向对象程序设计中,一般习惯是将类的成员和成员函数的声明写在.h文件里,而将各个成员函数的实现、和静态成员变量的初始化写在对应cpp文件里面。而当引入类模板之后,如果继续这样操作的话,将会报错。

解决方法

将该类的声明,与成员函数的实现、静态变量的初始化写在同一个文件(一般是头文件)里面。

第五中情况:类模板的友元的声明

问题分析

当有如下代码时,将会报错

1
2
3
4
5
6
7
8
9
10
11
12
template <class T>
class Foo
{
friend ostream& operator<<(ostream &os,const Foo&x);

T a;

public:
Foo(const T &a);
~Foo();
Foo(const Foo& other);
};

这是因为声明友元的时候没有声明其为函数模板。

解决方法

声明友元函数的时候,也需要声明其为函数模板。

方法1

1
2
3
4
5
6
7
8
9
10
11
template <class T>
class Foo
{
template <class Type>
friend ostream& operator<<(ostream &os,const Foo<Type>&x);
T a;
public:
Foo(const T &a);
~Foo();
Foo(const Foo& other);
};

如果将上面的Type改成T,那么在VS上正常编译,在G++(Code Blocks)上无法编译通过,报错如下:

方法2(教材上的示例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <class T> class Foo;

template <class T> ostream& operator<<(ostream &os,const Foo<T>&x);

template <class T>
class Foo
{
friend ostream& operator<< <>(ostream &os,const Foo&x); //注意这里的<>
T a;
public:
Foo(const T &a);
~Foo();
Foo(const Foo& other);
};

总结

  • undefined reference to 'XX'这种报错会出现在,函数已经声明,而且调用时参数与声明的一致,但是没有定义或者声明与定义(实现)不匹配的时候。
  • 如果没有声明函数或者调用时参数与声明不一样的话,报错将会是No match for xxx。如果该函数是某个类的友元函数的话,还会报XX is private错误。

本文为当代中国社会问题课程作业

摘要

当前中国社会经济发展过程中,城镇化是经济发展的主要推动力也是重要结果。中国城镇化过程中对城市规模的规划存在限制特大城市规模,约束大城市规模等政策,这些政策是否会产生城镇化进程中的问题。中小城镇和农村出现的空心化现象能否靠限制大城市人口进行解决。本文列举了当前我国城市规划中对城市规模限制的若干问题,分析了制定限制大城市人口政策的原因,并解决城镇化进程中这些问题给出了几点解决方法。
关键词:当代中国社会问题 城镇化 城市规划 人口

1.引言

在当代中国社会经济发展过程中,城镇化是经济发展的重要结果,也是城市消费和公共服务发展的重要推动力。当前我国城镇化进程中,城市人口始终是一个重要话题。近年来,大城市出现的交通拥堵、环境污染、公共资源与公共服务不足等问题,在舆论上很大程度被指向城市人口过多这个原因。而在三四线城市与农村,媒体关注其“空心化”问题。这些现象都归结到是否应该控制城市规模,怎样合理引导城市积极发展这些问题上。

2.问题现状

2.1 城市首位律

城市首位律是美国知名地理学家马克·杰佛森于1939年提出的对国家城市规模分布规律的概括。该定律认为,在一个国家或地区中往往存在一个比第二大城市大得多的“首位城市”,吸引了全国城市人口的很大部分,在一个国家或地区的政治、经济、社会、文化以及生活等方面占据明显优势。

学者马歇尔对马克·杰佛森的城市首位律进行量化,认为“大得多”比较合理的指数是2.0,即两城市指数法。后来不断发展,相继提出了四城市指数法和十一城市指数法。

2.2 上海的首位度

上海是我国最大的城市,根据上海市统计局发布的《2017年上海市国民经济和社会发展统计公报》数据显示,2017年底上海全市常住人口人口2418.33万人 。根据北京市统计局发布的《北京市2017年国民经济和社会发展统计公报》中显示,2017年底北京全市常住人口2170.7万人 。

按照两城市指数法,在全国层面来看,上海的首位度为1.114,远低于马克·杰佛森认为的“大得多”。上海交通大学安泰经济与管理学院的陆铭教授在《大国大城》一书中认为,上海的人口不是太多了,而是太少了 。

2.3 其他城市的规模

不仅是上海和北京,我国各大城市总体规划中均体现了控制人口的思想。在当前已经批复建设的国家中心城市中,到2020年,广州市域常驻人口控制在1800万以内 ,天津中心城区控制在630万左右 ,重庆中心城区控制在700万以内 ,成都中心城区控制在620万以内 ,武汉主城区控制在502万以内 ,西安主城区控制在528万以内 ,郑州中心城区控制在450万以内 。

3.问题解释

3.1 我国城镇化总体趋势

改革开放40年来,我国城镇常住人口从1.7亿人提高到8.1亿人,城镇化比例从17.9%提高到58.52% 。我国大城市的数量和比重不断增加;中小城市比重甚至数量在减少。大量劳动力从内地到沿海,从西部到东部,每年春节期间形成了中国特色的“春运”现象。很多地方只注重了城市建设的城镇化,而忽视了人的城镇化,忽视城镇居民特别是外来务工人员的基本就业及社会保障需求。

造成这些问题的原因包括,资源配置的行政导向,市场经济的马太效应等等。按照当前我国基本矛盾,我认为可以归结为“不平衡不充分的社会发展”。

3.1城市规模约束

按照《中华人民共和国土地资源法》,“十分珍惜、合理利用土地和切实保护耕地是我国的基本国策”。我国城市发展中,一般需要由上级政府批复该城市的总体规划。我国城镇化的总体政策为,控制大城市规模、合理发展中小城市和小城镇的城镇化规模。例如,在《国务院关于上海市城市总体规划的批复》(国函〔2017〕147号)中明确写出,“严格控制城市规模。……到2035年,上海市常住人口控制在2500万左右,建设用地总规模不超过3200平方公里”。在《中共中央 国务院关于对〈北京城市总体规划(2016年-2035年)〉的批复》中明确写出,“严格控制城市规模。……到2020年,常住人口规模控制在2300万人以内,2020年以后长期稳定在这一水平”。

在这种规划下,城市社会公共资源和公共服务将按照预计的常驻人口和略带余量的流动人口进行设置。但在城镇化进程快速推进的20多年来,上海和北京等大城市的实际人口实际上按照远超过规划的人口增长速度发展。一时间,交通拥堵、教育医疗资源不足等“大城市病”缠绕,“北漂”“沪漂”成为受到关注的词语。舆论和官方认为,我们的城市太大了,需要限制人口。

3.2 城市财政有限

1994年推进分税制改革以来,财政税收分为中央税、地方税和共享税。城市建设是地方政府的事权,也是地方政府的责任,但财税大头上交中央。在这种背景下,地方政府财政有限,仅能按照城市规划人口规模进行配套公共服务投入,难以提供满足实际人口规模需要的公共资源。地方政府缺乏对超过规划的流动人口进行大规模公共服务投入的意愿和能力,导致城市公共服务不足。

3.3 地区、城乡发展不平衡

中国当代城市发展格局,可以追溯到晚清开埠。帝国主义对于通商口岸的选择奠定了一大批近代工商业城市发展的基础。新中国成立后的社会主义改造、三线工程、开发大西北等一系列工程对地区平衡发展起到了重要作用。随着改革开放,市场经济下东部沿海地区得到快速发展,吸引了大量内地劳动力迁入。虽然西部大开发、振兴东北老工业基地、中部崛起和东部率先作为区域协调发展战略,但当前市场作为资源配置的决定性因素,地区差异是短时间内不能抹平的。地区、城乡之间发展的不平衡,使得城市规模的扩张比规划来得更快,因此出现当前城镇化中的问题。

4.解决对策

4.1 高质量经济发展

城镇化建设过程中的问题,最核心的就是钱的问题。地方政府对城市建设负责,那么地方政府有资金才能有意愿进行持续投入。发展不充分的问题要靠发展来解决,经济高质量发展才能带来持续性的资金投入。有了足够资金投入,才能建设满足城市实际需要的公共设施与服务。

4.2 新型城镇化发展

根据党的十八大精神,中共中央国务院印发《国家新型城镇化规划(2014-2020)》,明确走中国特色新型城镇化道路。预计到规划期末,东部地区城市群一体化水平和国际竞争力明显提高,中西部地区城市群成为推动区域协调发展的新的重要增长极。城市规模结构更加完善,中心城市辐射带动作用更加突出,中小城市数量增加,小城镇服务功能增强。稳步推进义务教育、就业服务、基本养老、基本医疗卫生、保障性住房等城镇基本公共服务覆盖全部常住人口,基础设施和公共服务设施更加完善。

4.3 城市群建设

以城市群为主体构建大中小城市和小城镇协调发展的城镇格局。人类历史上从来没有过这么庞大的城市化进程,中国现在需要走出自己的道路。十九大报告中指出,以城市群作为主体。在全国范围内,有着京津冀、长三角、珠三角、成渝等诸多发展完善或发展中的城市群。中国的13亿人口如果要达到发达国家的水平,单凭若干个城市远远承担不了这么庞大的人口,势必会产生严重的大城市病。走中国特色城镇化发展路线,建设一大批城市群,将会是一个更好的选择。例如,十九大报告中特别提到,疏解北京非首都职能,高起点、高标准建设雄安新区。一方面缓解北京严重的大城市病,另一方面促进城市群内其余城市的发展,实现京津冀地区的共同发展。

港珠澳大湾区、长三角一体化已经上升为国家战略,在城市群建设过程中需要破除行政藩篱,实现公共资源一体化发展。

4.4 城乡统筹发展

不光是北上广深等一线城市,不光是东部沿海地区,不光是大城市,小城市、中西部、城镇农村等一大批地区的人民同样有着美好生活的需要。城镇化需要区域协调发展,需要城乡统筹发展,需要进行国家层面的战略性布局。例如,实施西部大开发15年来,西部地区已经具备较强的经济基础,能够实现在2020年全面建成小康社会目标。例如,实施城乡统筹发展,建设全国统筹城乡综合配套改革试验区,使农民和市民在各个方面享有同等权利。

促进城乡统筹发展,有利于减少城乡差距,有利于促进农村人口合理有序转移。

5.结论

当代中国城镇化过程中存在城市规模受限问题,主要原因来源于制度与政策的不够完善以及区域发展不平衡不充分,为了解决这些问题,需要进一步促进区域协调发展,城乡统筹发展。

参考文献

  1. 2017年上海市国民经济和社会发展统计公报. 上海市统计局. [联机] 2018年3月. http://www.stats-sh.gov.cn/html/sjfb/201803/1001690.html.
  2. 北京市2017年国民经济和社会发展统计公报. 北京市统计局. [联机] 2018年2月. http://www.bjstats.gov.cn/zxfb/201802/t20180225_393332.html
  3. 陆铭. 2016. 大国大城. 上海 : 上海人民出版社, 2016.
  4. 国务院关于广州市城市总体规划的批复. 国务院. [联机] 2016年2月. http://www.gov.cn/zhengce/content/2016-02/19/content_5043501.htm
  5. 国务院关于天津市城市总体规划的批复. 国务院. [联机] 2008年3月. http://www.gov.cn/zhengce/content/2008-03/28/content_5542.htm
  6. 国务院关于重庆市城乡总体规划的批复. 国务院. [联机] 2011年10月. http://www.gov.cn/zhengce/content/2011-10/18/content_5243.htm
  7. 国务院关于成都市城市总体规划的批复. 国务院. [联机] 2015年12月. http://www.gov.cn/zhengce/content/2015-12/04/content_10384.htm
  8. 国务院关于武汉市城市总体规划的批复. 国务院. [联机] 2010年3月. http://www.gov.cn/zhengce/content/2010-03/10/content_5388.htm
  9. 国务院关于西安市城市总体规划的批复. 国务院. [联机] 2008年12月. http://www.gov.cn/zhengce/content/2008-05/12/content_5443.htm
  10. 国务院关于郑州市城市总体规划的批复. 国务院. [联机] 2010年8月. http://www.gov.cn/zhengce/content/2010-08/23/content_5368.htm
  11. 改革开放以来我国城镇化水平显著提高. 新华社. [联机] 2018年9月. http://www.xinhuanet.com/2018-09/10/c_1123408567.htm

问题描述

很多时候我们会遇到这样一种情景,第一行读入一个整数n,第二行输入一行字符串str

大家会自然地写出如下代码:

1
2
3
4
5
6
7
int n;
char str[80], str2[80];
cout<<"Input an integer:";
cin>>n;
cout<<"Input a string:";
cin.getline(str, 80);
cout<<"End of Input!";

但是当运行在控制台的时候,我们先输入一个整数,然后回车,然后试图输入一行字符串,会发现第二行字符串没有被输入。当我们检查到底输入了什么的时候,发现str为空字符串。

控制台显示内容如下:

1
2
Input an integer:5
Input a string:End of Input!

原因

cin>>的工作方式为,根据>>后面的数据类型读取数据,从非空白字符开始,遇到回车'\n'、空格' '、制表符'\t'等时结束。结束时将这些空白字符保留在输入流中。

cin.getline()的工作方式为,从输入流读取一行数据,遇到'\n'结束。结束时不在输入流中保留'\n'

在上面的代码和输入中,我们输入5之后按了一下回车,通过判断回车判断对n输入结束。这种情况下,cin不会删除输入流中的'\n',换行符将被留在输入流里面。接下来就被cin.getline()读入,其判断输入为换行符,结束本行输入,因而str为空。

解决方法

cin>>cin.getline()之间把这个换行符从输入流清除即可。

可以使用cin.ignore();忽略这个换行符,也可以使用cin.get();将这个换行符读入。

于是修改后的代码为:

1
2
3
4
5
6
7
8
9
int n;
char str[80], str2[80];
cout<<"Input an integer:";
cin>>n;
cin.ignore();
// 或者 cin.get();
cout<<"Input a string:";
cin.getline(str, 80);
cout<<"End of Input!";

扩展

cin.get()也能输入一行字符串,这种场景的调用方式和cin.getline()一模一样,只是把getline改成了get,如:

1
cin.get(str,80);

那么它和cin.getline()有什么区别呢?

cin.get在这种用法下将输入本行时最后的换行符保留在了输入流中,而cin.getline()不保留换行符。

优点不多说:非刘海的全面屏,骁龙845,101分的拍照,很舒服的陶瓷质感,关注的人都知道。

缺点主要有这几项,不妨一项一项来说。

后置指纹与竖排双摄。这个就见仁见智了,每个人想法可能不一样。
前置摄像头位置。对于我这种从来不自拍的,其实没有影响,不过视频聊天可能会影响。
大且沉。180+g的重量和6寸的屏幕,确实比我之前用的Pro6大。不过,全面屏加持下的6寸MIX2S仅比Pro6大不到一圈,重量比Pro6重一个手机壳的重量,能接受。
没有3.5mm耳机接口。这个常用的耳机接口突然就没了,撂谁都觉得不适应。
LCD屏幕。这个不算缺点,如果从OLED屏幕换成LCD屏幕

作为魅族的老用户,Flyme用久了换到MIUI确实还有一些不适应,在这里详细列出,如果是我不会用,请指教。

mBack。这个好用的一比,谁用谁知道。
没有上划解锁。只有双击解锁没有上划手势解锁,对我确实不习惯。
悬浮球。Flyme的悬浮球比MIUI的好用多了。切换最近应用,回到桌面,下拉悬停。
截图。我甚至连MIX2S截图按哪个键都不知道,别说通知栏和悬浮球。长截图要抢节拍不如Flyme慢慢自己调好用。
输入法。请问如何在中文输入模式,不切换中英文的情况下,快速打出大小写混杂的英文单词?

最后就是一点感慨。

我从小米1开始认识小米到现在已经7年了,买了一大堆小米的东西但都只是小米周边,核心的手机平板电视,今天之前一个都没买。
这都2018年了,雷军亲自抓供应链的事情都过去2年了,小米之家在全国也已经铺开了几百家。我下午2点打了个电话去预定了一台,3点多去就直接拿到手。轻松便捷,不需要在网上抢购。现在买手机还是更多回归线下了,新零售体验远比抢购来的爽。
中国国产手机从中华酷联,到百花齐放,到现在的华米OV。曾经性价比极高的乐视现在成什么样了,曾经好口碑的一加现在也不讲究了,曾经有了起色的魅族还能跟上行业的浪潮吗?360,努比亚和锤子都成为了一众小厂。对我而言,选择似乎是越来越少了。手机发展进入平缓期,当我觉得没有哪款手机吸引我的时候,全国手机销量增速也正好暴跌。
中学6年我换了6部手机,或多或少都是质量问题或者严重跟不上时代了。而大学以来Pro6用了22个月,仅仅是电池和闪存不足。
最早明年5G就要商用了,而我现在就换机了,这也许是我4G时代的最后一款手机吧。

去智博会的路上,我爸说晚上一定要去吃这家火锅,而且发给了我一篇推文。

老城门洞火锅位于渝中区罗汉寺附近的筷子街,已经开了三十余年。老板和他的兄弟是据说重庆第一家国营火锅的锅底掌勺,国营火锅店倒闭后出来兄弟单干。老板是老大,因此也被称作“老大老火锅”。

智博会回来,由于堵车,我们7点半才到了火锅店。路上的时候就在说,这家火锅店脾气怪,下午5点半开门,7点半以后不接客,晚上9点关门,没吃完的话老板要赶客。之前我爸很想加盟这家店,未果。

这家店进门之后就能看出,店面老破小,昏暗的光线与随处可见的油污。换做是外地的或者讲究环境的食客,看到这副景象便没了胃口。不过对于我们这种吃味道而不是吃服务的人来说,这都是不存在的。

这家店是标标准准的老火锅。老火锅用老油是很正常的事情,这家店一看也就是老油。和其他老火锅相比,这家店的锅底真的是特别黑,一种潲水黑的感觉。菜品也特别少,毕竟不卖混汤的菜。

看到这个层面上了,精致的食客可能也不会选择它。但是这火锅神奇之处就在于锅底。

我之前曾经批评过外地的所谓重庆火锅,既不辣也不香,完全没有味道。前几天又批评大队长火锅,味道太单薄而只有辣不香。

这家火锅,油面上飘浮着几个辣椒,吃着第一印象也是不辣。但是仔细平常就发现,虽然不辣,但是味道特别香,就是我之前经常提到的浑厚感,回味起来还有一股甜味。煮了半个小时之后,味道慢慢打开,辣味和咸味就慢慢提上来,形成了不是特别辣的复合型麻辣鲜香口感。

菜品是不是新鲜我吃不出来,不过种类是真的少。结账的时候发现老板只收现金,因此还特意出门取了现金。

吃的时候我就在和我爸及他的朋友聊到。海底捞就是服务的极端,但是其辣锅的味道是重庆人不能接受的。这些火锅店则是另外一个极端,味道好,但是服务、环境特别差。大人们也许吃的是情怀和回忆,现在像我们这种年轻人也许对于服务、环境、菜品拼盘等的重视度大大提高,这种老店也许不久之后便会被历史淘汰 。

下午7点半的网红佩姐火锅门庭若市,排队能排到凌晨,而同一时间的老城门洞火锅店内只有4桌人。老城门洞火锅店内的装潢看着已经十余年没有装修过了,当年想必也是风风火火,如今看上去则很显简陋。我们可以说老板是坚守传统,但坚守传统便意味着跟不上时代前进的脚步。

我的口吻当然是不喜欢这种近乎墨守陈规的传统,但是我也非常不希望这种传统在网红重庆的嘈杂中逐渐消逝。有兴趣的不妨前去体验一番。

0%