指针

本文介绍了C语言中指针与数组、指针与函数的关系,通过具体实例展示了如何使用函数指针来实现灵活的代码控制流程。特别是getfile函数利用填充值和跳过数据的策略处理文件备份和恢复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

指针与数组

输出数组名,数组名是固定的,指向数组的指针变量却是灵活可变的

指针与函数

输出函数名,函数名是固定的,指向函数的指针变量却是灵活可变的

在下面的例子中,getfile函数用来在备份/还原过程中处理文件,它接受两个参数,fill和skip(都是指向函数的指针)。这两个参数用来指示如何读取或跳过数据。

/*
 * Extract a file from the tape.
 * When an allocated block is found it is passed to the fill function;
 * when an unallocated block (hole) is found, a zeroed buffer is passed
 * to the skip function.
 */
void
getfile(fill, skip)
    void    (*fill) __P((char *, long));
    void    (*skip) __P((char *, long));
{
    int i;
    int curblk = 0;
    quad_t size = spcl.c_dinode.di_size;
    static char clearedbuf[MAXBSIZE];
    char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
    char junk[TP_BSIZE];

#ifdef __GNUC__         /* XXX: to shut up gcc warnings */
    (void)&curblk;
    (void)&size;
#endif

    if (spcl.c_type == TS_END)
        panic("ran off end of tape\n");
    if (spcl.c_magic != NFS_MAGIC)
        panic("not at beginning of a file\n");
    if (!gettingfile && setjmp(restart) != 0)
        return;
    gettingfile++;
loop:
    for (i = 0; i < spcl.c_count; i++) {
        if (spcl.c_addr[i]) {
            readtape(&buf[curblk++][0]);
            if (curblk == fssize / TP_BSIZE) {
                (*fill)((char *)buf, (long)(size > TP_BSIZE ?
                     fssize : (curblk - 1) * TP_BSIZE + size));
                curblk = 0;
            }
        } else {
            if (curblk > 0) {
                (*fill)((char *)buf, (long)(size > TP_BSIZE ?
                     curblk * TP_BSIZE :
                     (curblk - 1) * TP_BSIZE + size));
                curblk = 0;
            }
            (*skip)(clearedbuf, (long)(size > TP_BSIZE ?
                TP_BSIZE : size));
        }
        if ((size -= TP_BSIZE) <= 0) {
            for (i++; i < spcl.c_count; i++)
                if (spcl.c_addr[i])
                    readtape(junk);
            break;
        }
    }
    if (gethead(&spcl) == GOOD && size > 0) {
        if (spcl.c_type == TS_ADDR)
            goto loop;
        dprintf(stdout,
            "Missing address (header) block for %s at %d blocks\n",
            curfile.name, blksread);
    }
    if (curblk > 0)
        (*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size));
    findinode(&spcl);
    gettingfile = 0;
}

借助函数指针,开发者还可以参数化代码体的控制流程,在下面的例子中,closefunc保存着关闭fin流时需要调用的函数指针。在运行时,实际调用的函数取决于fin流的打开方式。

void
retrieve(cmd, name)
    char *cmd, *name;
{
    FILE *fin = NULL, *dout;
    struct stat st;
    int (*closefunc) __P((FILE *)) = NULL;
    int log;

    log = (cmd == 0);
    if (cmd == 0) {
        fin = fopen(name, "r"), closefunc = fclose;
        if (fin == NULL)
            cmd = do_conversion(name);
    }
    if (cmd) {
        char line[BUFSIZ];

        (void)snprintf(line, sizeof(line), cmd, name), name = line;
        fin = ftpd_popen(line, "r", 1), closefunc = ftpd_pclose;
        st.st_size = -1;
        st.st_blksize = BUFSIZ;
    }
    if (fin == NULL) {
        if (errno != 0) {
            perror_reply(550, name);
            if (log) {
                LOGCMD("get", name);
            }
        }
        return;
    }
    byte_count = -1;
    if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
        reply(550, "%s: not a plain file.", name);
        goto done;
    }
    if (restart_point) {
        if (type == TYPE_A) {
            off_t i, n;
            int c;

            n = restart_point;
            i = 0;
            while (i++ < n) {
                if ((c=getc(fin)) == EOF) {
                    perror_reply(550, name);
                    goto done;
                }
                if (c == '\n')
                    i++;
            }
        } else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
            perror_reply(550, name);
            goto done;
        }
    }
    dout = dataconn(name, st.st_size, "w");
    if (dout == NULL)
        goto done;
    send_data(fin, dout, st.st_blksize);
    (void) fclose(dout);
    data = -1;
    pdata = -1;
done:
    if (log)
        LOGBYTES("get", name, byte_count);
    (*closefunc)(fin);
}
基于html+python+Apriori 算法、SVD(奇异值分解)的电影推荐算法+源码+项目文档+算法解析+数据集,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用,详情见md文档 电影推荐算法:Apriori 算法、SVD(奇异值分解)推荐算法 电影、用户可视化 电影、用户管理 数据统计 SVD 推荐 根据电影打分进行推荐 使用 svd 模型计算用户对未评分的电影打分,返回前 n 个打分最高的电影作为推荐结果 n = 30 for now 使用相似电影进行推荐 根据用户最喜欢的前 K 部电影,分别计算这 K 部电影的相似电影 n 部,返回 K*n 部电影进行推荐 K = 10 and n = 5 for now 根据相似用户进行推荐 获取相似用户 K 个,分别取这 K 个用户的最喜爱电影 n 部,返回 K*n 部电影进行推荐 K = 10 and n = 5 for now Redis 使用 Redis 做页面访问次数统计 缓存相似电影 在使用相似电影推荐的方式时,每次请求大概需要 6.6s(需要遍历计算与所有电影的相似度)。 将相似电影存储至 redis 中(仅存储 movie_id,拿到 movie_id 后还是从 mysql 中获取电影详细信息), 时间缩短至:93ms。 十部电影,每部存 top 5 similar movie 登录了 1-6 user并使用了推荐系统,redis 中新增了 50 部电影的 similar movie,也就是说,系统只为 6 为用户计算了共 60 部电影的相似度,其中就有10 部重复电影。 热点电影重复度还是比较高的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值