pta上目前所遇到的一些坑

刚开始做这些题,用c写的,有的因为语法上或者是一些小细节的问题,导致题目本身逻辑没有问题,但却会出现两种情况:

  1. 编辑器上的结果错误
  2. 编辑器上的结果正确,提交全部错误

下面来整理一下这个大二暑假断断续续做的pta上的题遇到的这些坑。
一、语法上
1、 scanf中没有给存储地址,就会出现异常退出的情况

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

int main()
{
    int val;
    scanf("%d", val); //&val
    printf("%d", val);
    return 0;
}

2、字符串的赋值要用strcpy()函数, 而不能直接将一个字符串赋值给一个字符指针,这样会让编译器认为是将一个字符串赋值给一个地址;比较两个字符串要用到strcmp()函数
3.给一个整型数组赋一个无穷大的值要用memset()的话,要赋的值就用0x3f。
3、向类似sprintf(), bsearch()这些函数,要搞清楚那些参数一个指针,那些不是,传参的时候不要搞错了,否则可能出现一些很迷惑自己的现象。
比如集装箱这道题
4、gets()函数在这里插入图片描述
在做图书这道题时,要读入一个整数,但我用了gets(&val),最后真的惨不忍睹,函数不规范呀,把别的数据都给修改了,一个下午又没了。

二、细节上
1、cnt的值最终是-1, 而不是0

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

int main()
{
    int cnt = 3;
    while (cnt--)
    {
    }
    printf("%d", cnt);
    return 0;
}

2、double由于在程序中不能精确表示,如果对这一类型的数据多次累加可能造成最终结果错误
比如这一道题
3、整型和浮点型的输出问题,其实两个可以混用,我觉得这道题更精确地说是因为自己写的结果输出语句 printf("%.0lf\n", ans[i]); 中对于%.0lf的输出随编译器不同而不同,因为如果改成 printf("%.0lf\n", (ans[i] + 0.5)); 就会有一个测试用例正确。
互评成绩计算
4、读取数据流时,如果用到gets(a),或者scanf("%s", a)时,要注意用getchar()吸收换行,否则可能导致a字符数中是空的
比如检查密码这道题,

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

int main()
{
    char a[81];
    int cnt, n, len, num_flag, alpha_flag, illegal_flag;
    scanf("%d", &n);
    getchar();
    while (n--)
    {
        // getchar();gets()会将一行的所有输入都存下来,包括换行
        // 所以如果是这里getchar()的话,除了第一个密码,其他的都会少第一个字母
        // getchar();
        gets(a);
        // scanf("%s", a);
        printf("pw:%s\n", a);
        cnt = num_flag = alpha_flag = illegal_flag = 0;
        len = strlen(a);

        for (int i = 0; i < len; i++)
        {
            if (isdigit(a[i]))
            {
                num_flag = 1;
            }
            else if (isalpha(a[i]))
            {
                alpha_flag = 1;
            }
            else
            {
                if (a[i] != '.')
                {
                    illegal_flag = 1;
                }
            }
        }

        if (len < 6)
        {
            printf("Your password is tai duan le.");
        }
        else if (illegal_flag)
        {
            printf("Your password is tai luan le.");
        }
        else if (num_flag == 0)
        {
            printf("Your password needs shu zi.");
        }
        else if (alpha_flag == 0)
        {
            printf("Your password needs zi mu.");
        }
        else
        {
            printf("Your password is wan mei.");
        }
        printf("\n");
    }

    return 0;
}

第一个getchar()不能缺少,而且这里不能用scanf()替代gets(),因为密码中可能有空格,而scanf()遇到换行,空格就会终止。

5、对于有些保留小数点后几位的,比如下面的val保留小数点后一位,输出。当值是0.01,应该输出0.0;而当值是-0.1时,没有判断的话会输出-0.0,实际上应该输出0.0

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

int main()
{
    double v = -0.03;
    printf("%.1lf", v);
    return 0;
}

6、变量要赋一个初值,还有的变量在判断中,或者循环中,要再合适的地方重新赋值,否则的话就会出错,比如银行排队,这道题,起初我的代码如下:

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

struct c
{
    int arr_tm;
    int pro_tm;
}time[10004];

int cmp(struct c *a, struct c *b){
    return a->arr_tm - b->arr_tm;
}

int k;
int findService(int *a){ 
    int ind = 0;
    for(int i = 1; i < k; i++){
        if(a[ind] - a[i] > 0){
            ind = i;
        }
    }
    return ind;
}
int main()
{
    int n, ind, cnt, hour, minu, sec;
    int win[100] = {0};
    long long cnt_time;
    
    scanf("%d %d", &n, &k);
    for(int i = 0; i < n; i++){
        scanf("%d:%d:%d %d", &hour, &minu, &sec, &time[i].pro_tm);
        time[i].arr_tm = hour * 3600 + minu * 60 + sec;
        time[i].pro_tm *= 60;
        // printf("hour:%d\n", hour);
    }

    qsort(time, n, sizeof(time[0]), cmp);
    for(int i = 0; i < k; i++){
        win[i] = 8 * 3600;
    }

    ind = 0; 
    cnt = 0;
    //cnt_time = 0; //刚开始时cnt_time没有赋初值,找了半天
    for(int i = 0; i < n; i++){
        
        if(time[i].arr_tm > 17 * 3600){
            break;
        }
        ind = findService(win);
        cnt = i;
        
        if(time[i].arr_tm < win[ind]){ 
            cnt_time += win[ind] - time[i].arr_tm;
            win[ind] += time[i].pro_tm; 
        }
        else{
//             win[ind] += time[i].pro_tm + (time[i].arr_tm - win[ind]);
            win[ind] = time[i].pro_tm + time[i].arr_tm;
        }
        
    }

    printf("%.1lf", cnt_time * 1.0 / (60 * (cnt + 1)));
    return 0;
}

就因为上面的cnt_time变量没有赋初值0,在vscode中用测试数据测试的时候没有问题,而提交的时候全部错误。
三、经验总结
1、如果一个代码盯了很长时间没盯出来,可以过一两个小时之后再盯。
2、如果提交上去的结果出现一两个错误,那一般就是边界问题。注意考虑一些特殊情况,构造特殊测试数据进行测试。
3、如果有的时候输出结果比较奇怪,注意检查前面的计算是和否正确,然后将前面的结果输出看是不是自己想的结果。
4、对于向id这样唯一的东西,需要时可以把这个作为数组的index。有些时候有因为这样在进行排序的时候导致id和index对不上,这个时候可以考虑构造结构体排序。
5、ans是一个字符数组,strcpy(a, ans), printf(ans)等,遇到ans里的空字符0就直接结束了。
6、定义结构体是最好同时用typedef 定义一个别名,否则的话每次使用声明一个结构体变量时都需要在前面加上struct。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值