0.1【练习题 + 其他知识点】

1. 其他知识点

1.1. man 手册

1.2. ctags追踪

ctags索引:

  1. vi -t 要查找的内容,(查找宏,数据类型等)
    输入前面序号,回车
  2. 继续追踪
    将光标定位到要追踪的内容上,ctrl+]
    回退:ctrl+t

1.3. exec函数族 在一个进程里 运行其他进程

int execl(const char *path, const char *arg, ...
                       /* (char  *) NULL */);
int execlp(const char *file, const char *arg, ...
                       /* (char  *) NULL */);
int execle(const char *path, const char *arg, ...
                       /*, (char *) NULL, char * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

代码:在一个进程里 运行其他进程

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

#define SYSTEM_FLAG 1
#define EXEC_FLAG_1 1
#define EXEC_FLAG_2 1

/* 常用的:在一个进程里面,运行其他进程 */
int main(int argc, char *argv[])
{
#if SYSTEM_FLAG //system 族
    system("ls -l");
#endif

#if EXEC_FLAG_1 //exec 族
    /* 进程所在目录、进程文件名字、参数、用NULL结尾 */
    execl("/bin/ls", "ls", "-l", NULL);
#endif

#if EXEC_FLAG_2 //exec 族
    /* 参数为可变参 */
    execl("./", "./a.out", NULL);
#endif
}

1.4. 区别:线程互斥信号量、进程早期信号通知、进程IPC V信号灯集

重点关注,不要混淆

1.4.1. 进程早期信号通知

指的是:系统进程和应用进程等,进程之间通知的信号。

1.4.2. 线程互斥信号量

主要用于PV操作的,单个信号量个体

1.4.3. 进程IPC V信号灯集

线程互斥信号量 的基础上升级,能够以集合的形式,操作多个单体信号量

1.5. 信号灯集、消息队列,返回id为0怎么处理?(共享内存无该问题)

很多种原因,暂时不会解决。

不能总是删了重新运行,这不是个办法


2. 标准IO

2.1. 练习:通过fgetc与fputc函数实现cat功能.

/*  练习:通过fgetc与fputc函数实现cat功能.
    注意:fgetc官方 返回值为int,不用char
    字符补码保存;若变量ch 为char类型读到字符0xFF与EOF(-1)比较时相等,误判为已经读到文件末尾
*/
#include <stdio.h>
int main(int argc, char *argv[])
{
    // argv[0]是文件名字,1是后续第一个参数
    FILE *fp = fopen(argv[1], "r");
    if (NULL == fp)
    {
        perror("fopen err");
        return -1;
    }

    // 不到EOF 且同时 不读出错,则 循环 读取 打印 流
    int ch;
    while (((ch = fgetc(fp)) != EOF) && !ferror(fp))
        fputc(ch, stdout);
    putchar(10);

    // 关闭文件流
    fclose(fp);
}

2.2. 用标准IO实现cp功能

diff 文件名1 文件名2 :对比文件1 与文件2是否有不相同的地方

#include <stdio.h>

int main(int argc, char *argv[])
{
    char buf[32];

    // 打开 源文件(被复制的文件)
    FILE *src = fopen(argv[1], "r");
    if (NULL == src)
    {
        perror("src err");
        return -1;
    }

    // 打开 目标文件(复制后的文件)
    FILE *dest = fopen(argv[2], "w");
    if (NULL == dest)
    {
        perror("dest err");
        return -1;
    }

    // 循环 读源文件 写入 目标文件
    while (fgets(buf, sizeof(buf), src) != NULL)
        fputs(buf, dest);

    // 关闭 流
    fclose(src);
    fclose(dest);
}

2.3. 实现“head -n 文件名”命令的功能 (显示文件前n行)

例:head -3 test.c -> ./a.out -3 test.c

atoi : "1234" -- 1234

atoi:将字符串转化为整型

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

int main(int argc, char *argv[])
{
    char buf[32] = {0};
    if (argc != 3)
    {
        perror("err input");
        return -1;
    }

    FILE *fp = fopen(argv[2], "r");
    if (fp == NULL)
    {
        perror("open err");
        return -1;
    }

    // 读取n行,参数为字符串转换为整形
    // int num = -arot(argv[1]);
    // int num = -1 * arot(argv[1]);
    int num = atoi(argv[1] + 1); //+1为从-的身后数字开始

    // 循环读取 并输出
    // fgets会在读到如下情况停止:\n,文件结束
    // 读到末尾会返回NULL,所以可 不用判断 num等于0,就已经结束了
    while (fgets(buf, 32, fp) != NULL)
    {
        // 字符长度 比 下标大1
        if (buf[(strlen(buf) - 1)] == '\n')
            num--; //几个\n就是输出了几行

        fputs(buf, stdout);
        memset(buf, 0, sizeof(buf) / sizeof(*buf));

        // 还有几行要打印
        if (num == 0)
            break;
    }

    fclose(fp);
    return 0;
}

2.4. 编程读写一个文件test.txt,每隔1秒向文件中写入一行数据

类似这样:

1, 2007-7-30 15:16:42

2, 2007-7-30 15:16:43

该程序应该无限循环,直到按Ctrl+C中断程序。

再次启动程序写文件时可以追加到原文件之后,并且序号能够接续上次的序号,比如:

3, 2007-7-30 15:16:42

4, 2007-7-30 15:16:43

5, 2007-7-30 15:19:02

6, 2007-7-30 15:19:03

7, 2007-7-30 15:19:04

分析:

1. 打开文件fopen,以a+的形式打开,循环往文件写内容

2. 每隔1s写入一行,sleep(1);

3. 计算文件行数,wc -l

4. 计算当前时间,转换成年月日、时分秒,time,localtime

5.字符串拼接函数:strcpy/strcat(dest, src)、sprintf、fprintf

6.全缓冲

//time:计算时间,获取秒数

//localtime:将时间秒数转化成当地年月日时分秒

//fprintf:()

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    // 追加打开 或 创建文件
    FILE *fp = fopen("./test.txt", "a+");
    if (NULL == fp)
    {
        perror("err fopen");
        return -1;
    }

    // 计算文件行数
    char buf[32] = {0};
    int line = 0;
    while (fgets(buf, sizeof(buf), fp) != NULL)
        if (buf[strlen(buf) - 1] == '\n')
            line++;

    // 循环向文件中写
    while (1)
    {
        // 获取 当前时间
        time_t t = time(NULL);

        // 转化 时间秒数 为年月日十分秒
        struct tm *tm = localtime(&t);

        // 向文件写入,属于文件缓冲,需要强制刷新,写入进去
        fprintf(fp, "%d,%d-%d-%d %d:%d:%d\n",
                ++line,
                tm->tm_year + 1900, //在1900基础开始,需要+1900
                tm->tm_mon + 1,     //月份从0开始,需要+1
                tm->tm_mday,
                tm->tm_hour,
                tm->tm_min,
                tm->tm_sec);

        // 强制刷新
        fflush(fp);
        sleep(1);
    }
    // 关闭 文件流
    fclose(fp);
}

3. 文件IO

3.1. 用文件IO实现cp功能。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    char buf[32] = {0};
    ssize_t s = 0;

    // 打开目标文件和源文件
    int src = open(argv[1], O_RDONLY);
    int dest = open(argv[2], O_TRUNC | O_WRONLY | O_CREAT, 0666);
    if (dest < 0 || src < 0)
    {
        perror("open err");
        return -1;
    }

    // 循环读写
    while ((s = read(src, buf, sizeof(buf))) != 0)
    {
        // 读多少,写多少
        write(dest, buf, s);
    }

    close(src);
    close(dest);
}

4. 进程

4.1. cp拷贝 父子进程 文件IO

要求:文件IO cp src dest

通过父子进程完成对文件的拷贝(cp),父进程从文件开始到文件的一半开始拷贝,子进程从文件的一半到文件末尾。

提示:

  1. 长度获取:lseek() 400-->200
  2. 定位到一半lseek
  3. buf[32] 200-32-32 read
  4. fork之前打开文件还是fork之后打开文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#define N 32

int main(int argc, char *argv[])
{
    // 打开 源文件 目标文件
    int src = open(argv[1], O_RDONLY);
    int dest = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值