程序设计-20161027

10月27日 · 2016年
jxtxzzw

16级程序设计基础实践第一次月考
Begin Time: 2016-10-27 13:00:00
End Time: 2016-10-27 14:45:00
Judge: By File

第一次上机考试,题目不难,但是对于初学者来说确实不是很容易AC,毕竟初学者出现错误以后没有办法快速准确地自己看出问题所在。

我做完以后一直等到考试时间结束,期间看着Submitted数字不断地上升,而Accepted数字几乎不动,直到考试结束前半分钟,我记下了这次考试的数据。

A Lab04_01 39.52%(132/334)
B Lab04_02 7.88%(32/406)
C Lab04_03 8.55%(33/386)
D Lab04_04(选做) 25.71%(18/70)

第一题,最简单。

Problem A:Lab04_01
Time Limit:1000MS Memory Limit:30000KB
Description
输入两个整数,第1行输出这两个数的逻辑或的值;第2行输出这两个数的位或的值;第3行输出这两个数的位异或的值。
Input
输入两个整数
Output
第1行输出这两个数的逻辑或的值;第2行输出这两个数的位或的值;第3行输出这两个数的位异或的值。
Sample Input
1 1
Sample Output
1
1
0

直接给出代码,没有需要注意的地方。

#include <stdio.h>
#include <stdlib.h>

int main() {
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d\n",a||b);
    printf("%d\n",a|b);
    printf("%d\n",a^b);
    return 0;
}

第二题,也不难。

Problem B:Lab04_02
Time Limit:1000MS Memory Limit:30000KB
Description
输入一个非负int类型整数,在一行中输出该数的二进制表示中值为1的位数,以及最简分数表示的占比(格式分子:方母,如1:16,1:1等),位数与占比之间用一个逗号分隔。
例如:
Input:
3
Output:
2,1:16
Note:
示例数据的输出以某个32位的机器为例
Input
输入一个非负int类型整数
Output
在一行中输出该数的二进制表示中值为1的位数,以及最简分数表示的占比(格式分子:方母,如1:16,1:1等),位数与占比之间用一个逗号分隔。
Sample Input
0
Sample Output
0,0:32

二进制转换的具体操作可以参见我前一篇文章《程序设计-20161024》的EOJ3085。

最大公约数采用的是递归写法的辗转相除法,可以参见前面的文章《程序设计-20161020》。

这里直接给出代码。

#include <stdio.h>
#include <stdlib.h>
int gcd(int a, int b) {
    if (b==0) {
        return a;
    } else {
        return gcd(b,a%b);
    }
}

int main() {
    unsigned int num;
    int i=0,count=0,a[100]= {0};
    scanf("%ud",&num);
    while (num>0) {
        a[i]= num % 2;
        num = num / 2;
        i++;
    }
    num=i;
    while (i>=0) {
        if (a[i]==1) count++;
        i--;
    }

    if (count==0) {
        printf("%d,%d:%d\n",0,0,32);
    } else {
        int div =gcd (count,32);
        printf("%d,%d:%d\n",count,count/div,32/div);
    }
    return 0;
}

需要注意的有这么几点:

1、数组a开到了100,有点浪费了。

2、这里的输入数字num采用的是unsigned int。

3、计数的过程与前一篇略有差异,这里采用的是从数组最后一位往前的方法。

4、由于任何数都是0的因数,所以0与32的最大公约数是32,因此需要单独考虑count为0的情形。

5、约分到最简,就是分子分母同时除以最大公约数。

6、输出结果需要有换行符。

7、变量一定要记得初始化,这里都是赋初值0。

第三题,与上次作业题类似,简单。

Problem C:Lab04_03
Time Limit:1000MS Memory Limit:30000KB
Description
统计并输出一段文字中大写字母开头的单词个数。
例如:
Input:
The C
programming language
Output:
2
Note:
在一行中,单词与单词之间用一个或多个空格分隔,每行末尾有一个换行符
Input
输入一段文本
Output
输出文字中大写字母开头的单词个数
Sample Input
This is a exmaple
there are SOME Books
Sample Output
3

直接给出代码。

#include <stdio.h>
#include <stdlib.h>

int main() {
    char ch;
    int isnew=1,count=0;

    while (scanf("%c",&ch)==1) {
        if (ch>='A' && ch <='Z') {
            if (isnew) {
                count++;
                isnew=0;
            }
        } else {
            isnew=0;
            if (ch==' '|| ch=='\n'|| ch=='\t') {
                isnew=1;
            }
        }
    }
    printf("%d\n",count);
    return 0;
}

需要注意的有这么几点:

1、因为空格有一个或多个,所以不能单纯地以flag=!flag这种方法来更改逻辑值。

2、判断是否文件结束仍旧采用的是scanf的返回值,参见《程序设计-20161015》。

3、

if (ch>='A' && ch <='Z') { //如果这是大写字母
            if (isnew) { //判断是不是一个新单词的开头
                count++; //如果是,就让计数器加1
                isnew=0; //并且把isnew设置为false
            }

4、在else的部分,有一句isnew=0。这里详细说说这句话的含义。

题目说的很清楚,“大写字母开头的单词”,也就是说大写字母必须在首位才是计数的,例如Apple是计数的,SOME是仅记一次(而不是四次),heLLo是不计数的。

但是事实上,在OJ判断的时候,似乎只考虑了Apple、apple、APPLE这样的情况,并没有考虑到aPPlE这样的情况,所以这句话不写竟然也被OJ认为是通过的。这句话应该是要写的。

else {  //否则(也就是不是大写字母)
      isnew=0; //一个字符不是大写字母//不论是小写字母还是其他的//都认为之后遇到的不是一个新单词//把isnew设置为false//即便是空格,也先这样处理,之后再改
      if (ch==' '|| ch=='\n'|| ch=='\t') {
            isnew=1;
//如果是空格,那么之后遇到的就应该是新一个单词了
      }
}

5、输出最后要有换行符。

第四题,选做题,难度确实最大,但是只要知道牛顿二项式定理,直接写就是了,没有难度。

Problem D:Lab04_04(选做)
Time Limit:1000MS Memory Limit:30000KB
Description
使用Newton-Raphson算法求解方程:2χ3-4χ2+3χ-6=0在1.5附近的根(保留3位小数)。在一行中输出根的值。
本题没有输入,也不提供示例输出。
直接输出答案的,一律判为0分。
Note:
参考曲线
(注:图略)
Input

Output
在一行中输出根的值(保留三位小数)。
Sample Input

Sample Output
不给

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double f(double x) {
    return (2*pow(x,3)-4*pow(x,2)+3*x-6);
}
//原函数

double f1(double x) {
    return (6*pow(x,2)-8*x+3);
}
//导数

int main() {
    double x=1.5;
//从1.5开始试
    while (fabs(f(x))>0.00001) {
//精度要求
        x=(-(f(x)))/(f1(x))+x;
//N-R定理
    }
    printf("%0.3f\n",x);
//场宽(域宽)
    return 0;
}

//特别注意,绝对值是fabs(),不是abs()

关于牛顿二项式“高级版”的代码,可以参见新一篇文章《程序设计-20161028》。

正文完。

然后给出闫壮的第二题做法。

先给出代码,然后详细说明。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main()
{
    int p,i,n,t,x,y,u;
    scanf("%d",&p);
    i=0;
    n=0;
    t=1;
    while(n<32)
    {
        if((p&t)==t)
        {
            i++;
        }
        else
        ;
        n++;
        t=pow(2,n);
    }
    if(i==0||i==1)
    {
        y=i;
        u=32;
    }
    else if(i%2!=0)
    {
        y=i;
        u=32;
    }
    else
    {
        for(x=2; i>=x;)
        {
            if(i%x==0)
            {
                y=i/x;
                u=32/x;
            }
            x=2*x;
        }
    }
    printf("%d,%d:%d\n",i,y,u);
    return 0;
}

首先值得肯定的是,在没有学过用递归写最大公约数的情况下,能够针对“32是2的5次幂”来分类约分,是很不容易的。并且分类的方法是对的,也就是说,约分部分的程序是对的。

但是,程序的可读性极差。大括号的对齐习惯不是最主要的原因,主要是因为变量名毫无意义,一堆a、b、c、i、p、u,没有人知道是什么意思。

所以,下面说说一般情况下被广为接受的惯用命名法。初学者应该特别注意变量的命名,绝对不能取没有意义的变量名,并且建议不要把循环变量i用作计数器(除非很清楚自己在做什么),以及写上必要的注释。当然,每个人也都会有自己的偏好习惯,所以这些命名法仅供参考。

数组
a[]
arr[]
array[]
data[]
e[]
m[]
mat[]
mtx[]
matrix[]

最终答案的临时存储
ans
answer

平均值
ave
avg
average

普通数值
a
b

计数器
c
cnt
count
counter
tot
total

字符
ch

距离
dist

磁盘
disk

深度优先搜索
dfs

被除数
dividend

除数
divisor

动态规划
dp

编辑
edt
edit
editor

没有明确含义的布尔逻辑值(必要时要加注释)
f
flag

有明确含义的布尔逻辑值
isXXX
并且用1表示something is XXX,用0表示something is not XXX
如:
isnew
isprime
isexist
isopen
isfinished
ismore

没有明确含义的函数(必要时要加注释)
f
fac
fact
fct
func

群组
g
grp
gpe
group

最大公约数
gcd

循环变量
i
ii
j
jj
k
kk

定位符
loc
location

长度
len
length

需要输入获取的数据
m
n
num

最大值
max

最小值
min

管理
mgmt
management

指针
p
pt
lnk
link

快速排序
qs
qsort
q_sort
quicksort

余数
rest

返回值
ret

字符串
s
st
str

累加
sum

临时变量
t
tmp
temp

计时器
t
time
mmt
moment

未知量(常见于函数参数表)
x
y
z

并且,变量一般用小写字母,如ans;常量一般用大写字母,如NUMBER、PI、BEGIN;逻辑真与逻辑假一般用全大写,如TRUE、FALSE。

以上信息不定期更新
最近更新日期:2016-11-04

附陆幼利老师的示例程序(来源OctPracticeTest.mp4)

sp161029_153333

sp161029_153355

sp161029_153442

sp161029_153451

2016-10-27_20-14一稿

2016-10-28_13-06二稿

2016-10-29_15-40三稿

1 条回应
  1. 闫 壮2016-10-27 · 20:28

    你写的我们好像。。。你懂得