20200910-3 命令行和控制台编程
此作业的要求参见: 作业要求 20200910-3 命令行和控制台编程
1.熟悉 命令行 和 控制台/标准输入和标准输出
(1)假设在当前目录下存在应用程序 a.exe 和 文件文件 b.txt,请以数据流图并辅助以文字说明下述控制台命令的作用是什么。(5分)
a.exe < b.txt > c.txt
A: 该指令运行了程序a.exe,并将b.txt的文件内容重定向为a.exe的输入,之后,又将a.exe的输出重定向到文件c.txt(新建c.txt或覆盖c.txt原有内容)。
数据流图如下:
(2)请用C语言开发应用程序d.exe,从控制台指令读入命令行参数,并在控制台分别打印出a、b、c的值。运行效果形如下面的示例(6分)
d.exe a=1 b=2 c=3
1
2
3
d.exe a=11 b=22 c=33
11
22
33
A: 该题的要点在于使用main函数的参数获取到运行程序时提供的输入,代码如下:
#include <stdio.h>
#include <string.h>
// Command Line Arguments of C Language
// argc: nuber of arguments;
// argv: string array of arguments.
int main(int argc, char *argv[]){
// cat all string in string array argv as one string.
char *argStr = (char *)calloc(1, sizeof(char));
for(int ii = 1; ii < argc; ii++){
argStr = strcat(argStr, argv[ii]);
argStr = strcat(argStr, " ");
}
// get number in argStr which converted from arguments input.
int a, b, c;
sscanf(argStr, "a=%d b=%d c=%d", &a, &b, &c);
printf("\n%d\n\n%d\n\n%d", a, b, c);
return 0;
}
运行效果如下:
2.熟悉 测试用例
(1)请在网站 [https://pintia.cn/]注册账号。(0分)
A: 已注册。
(2)在题目集 PAT (Basic Level) Practice (中文) 中任选3道题目完成。截图如下,要求包括1.红色对号、2.标号、3.用户名(此例中为 Young)。(30分)
注意,需要读完本作业全部题目才能开始做题,有对时间记录和代码解读的要求。
A:
截图如下:
(3)代码解读 (20分)
Q: 发表博客,介绍上述3个题目代码中重点/难点,展示重要代码片断,给出执行效果截图,展示你感觉得意、突破、困难的地方。
代码片断要求1 凡不缩进的,此题目拒绝接收。不知道什么是“缩进”的同学,请自行补课,不接受以“不知道”作为理由。
代码片断要求2 要求使用cnblogs代码控件,参见往届同学黄兴、宫成荣的作业。凡粘贴IDE中的代码截图,或者贴文字而没有关键字高亮或彩色的,0分。
[http://www.cnblogs.com/huangxman/p/5871201.html]
[http://www.cnblogs.com/gongcr/p/5873493.html]
A:
I. 1001 害死人不偿命的(3n+1)猜想 (15point(s))
题目详细描述见链接。
本题难度较低,使用循环对数据反复求解即可,需要注意的是循环条件是 n!= 1
, 而不是 n != 0
。代码如下:
#include <stdio.h>
int main(){
// get int number which named n from std input.
int n;
scanf("%d", &n);
// counter
int count = 0;
// test count in loop until n is less or equal 1
while(n != 1){
if( n % 2 == 0){ // n is enev, n = n / 2
n = n / 2;
}else{ // n is odd, n = (3 * n + 1) / 2
n = (3 * n + 1) / 2;
}
// count ++
count++;
}
// output count
printf("%d", count);
}
II. 1002 写出这个数 (20point(s))
题目详细要求见链接。
本题有如下几个要点需要关注:
-
输入的数字可能会超出
int
类型的范围,故最好使用字符串来保存输入的数字; -
在C语言中,数字字符转换为对应的数字只需要减去字符‘0’,即
int num = num_ch - '0'; // num_ch 是一个数字字符
; -
对于计算结果的数字输出,需要按从左到右的顺序,这需要一个数组来保存输出结果字符串的指针,以便于结果输出。
实现代码如下:
#include <stdio.h>
int main(){
// get input number as a string(char array)
char n[101];
scanf("%s", &n);
// calc sum of each digit
int sum = 0, n_i = 0;
while(n[n_i] != '\0'){
// char of number to int number
// ch - '0'
sum = sum + (n[n_i++] - '0');
}
// alphabets string table
char alphabets[][5] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
// fix out strings
char *reout[10];
int reout_i = 0;
while(sum > 0){
reout[reout_i++] = alphabets[sum % 10];
sum = sum / 10;
}
// print
while(reout_i > -1){
printf("%s", reout[--reout_i]);
if(reout_i > 0){
printf(" ");
}
}
}
III. 1003 我要通过! (20point(s))
题目详情见链接。
题目中提到字符串符合要求的条件是,
字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符;
任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串;
如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。
通过分析,可以将判定正确的条件分解如下:
-
只包括字符
A
、P
和T
, 不得出现其他字符; -
字符
A
、P
和T
都至少有一个; -
字符
T
必须出现在字符A
之后; -
对于字符
A
的数量有要求,要求如下: 将字符A
在字符P
之前的数量记为C1
, 在P
和T
之间的数量记为C2
,在T
之后的数量记为C3
,存在关系C1 * C2 = C3
实现代码如下:
#include <stdio.h>
int judge(char *str)
{
int A_befor_P = 0, A_in_PT = 0, A_after_T = 0, P = 0, T = 0, flag = 1;
while (*str != '\0')
{
if (*str == 'A')
{
if (P == 0)
{
A_befor_P++;
}
else if (P > 0 && T == 0)
{
A_in_PT++;
}
else if (P > 0 && T > 0)
{
A_after_T++;
}
}
else if (*str == 'P')
{
if (P == 0)
{
// first 'P'
P++;
}
else
{
// break
flag = 0;
break;
}
}
else if (*str == 'T')
{
if (T == 0 && P == 1)
{
// first 'T' after 'P'
T++;
}
else
{
// break
flag = 0;
break;
}
}
else
{
// have char not 'A', 'P' or 'T'
// faild and stop loop
flag = 0;
break;
}
str++;
}
if (!(flag != 0 && P > 0 && T > 0 && A_in_PT > 0 && A_befor_P * A_in_PT == A_after_T))
flag = 0;
return flag;
}
int main()
{
// get lines number
int n;
scanf("%d", &n);
char str[101];
for (int ii = 0; ii < n; ii++)
{
// get line
scanf("%s", str);
// judge this string
if (1 == judge(str))
{
printf("YES");
}
else
{
printf("NO");
}
// just print newline (\n) before last one
if (ii < n - 1)
{
printf("\n");
}
}
}
(4)控制台应用 (15分)
要求在博客中给出测试数据。
参照上一题中“控制台”的知识,给出运行时从控制台读入测试数据和向控制台输出的截图。
A:
更多题目描述和代码实现等信息,请查看2.(3)
。
I. 1001 害死人不偿命的(3n+1)猜想 (15point(s))
输入如下:
3
输出如下:
5
运行截图如下(结尾的%
字符是终端表示输出已经结束的标识符,并非程序本身的输出):
II. 1002 写出这个数 (20point(s))
输入如下:
1234567890987654321123456789
输出如下:
yi san wu
运行截图如下:
III. 1003 我要通过! (20point(s))
输入如下:
8
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA
输出如下:
YES
YES
YES
YES
NO
NO
NO
NO
运行截图如下:
由于是截图,无法区分输入输出。在图例中,除第一行数字的输入外,其他的内容都是两行一组,一组中,第一行为输入,第二行为输出。
该程序已经通过PTA OJ系统测试,属于正确处理。
图表过小、字迹不清、错别字、句子不通顺的,教师会因为读不懂而对此题扣分。
(5) PSP(8分)
在同一篇博客中,参照教材第35页表2-2和表2-3,为上述3个题目制作PSP阶段表格。
PSP阶段表格第1列分类,如功能1、功能2、测试功能1等。
A:
题目 | 预计花费时间 | 实际花费时间 | 花费时间差距 | 原因 |
---|---|---|---|---|
1001 | 15min | 14min | -1min | 题目较为简单,描述清晰,较快完成任务。 |
1002 | 15min | 20min | +5min | 没有注意到题目描述中对数字的限制范围,导致使用int 保存输入而需要重构。 |
1003 | 20min | 40min | +20min | 题目难度较高,分析条件有一定难度。同时,编码时忽略了一个条件,导致一个测试用例一直没法通过,检查花费了较长时间。 |
要求1 估算你对每个功能 (或/和子功能)的预计花费时间,填入PSP阶段表格,时间颗粒度为分钟。 |
要求2 记录词频统计项目实际花费时间,填入PSP阶段表格,时间颗粒度要求分钟。
要求3 对比要求1和要求2中每项时间花费的差距,分析原因。