目录
1.作业一
标准IO函数时候讲解的时钟代码,要求输入quit字符串后,结束进程
// 标准IO函数时候讲解的时钟代码,要求输入quit字符串后,结束进程
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
void get_time();
/// @brief 线程体
void* startcountDown(void*);
int main(int argc, const char *argv[])
{
pthread_t tid;
if(pthread_create(&tid, NULL, startcountDown, NULL) != 0){
printf("pthread_create error\n");
return -1;
}
char buf[24] = "";
while (strcmp(buf, "quit")){
fgets(buf, 5, stdin);
}
return 0;
}
void get_time()
{
time_t ts; // 保存当前时间(秒)
struct tm* tm_p = NULL; // 保存当前格式化时间
// 获取当前时间
while (1) {
ts = time(NULL);
if (ts == -1) {
perror("time");
return;
}
// 4.格式化当前时间
tm_p = localtime(&ts);
if (NULL == tm_p) {
perror("localtime");
return;
}
// 5.格式化字符串
fprintf(stderr, "%d-%02d-%02d %02d:%02d:%02d\r", tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday, tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec);
// 6.刷新缓冲区
// fflush(stdout);
sleep(1);
}
}
void* startcountDown(void*)
{
get_time();
}
2.作业二
// 要求定义一个全局变量 char buf[] = "1234567",创建两个线程,不考虑退出条件。
// A线程循环打印buf字符串,
// B线程循环倒置buf字符串,即buf中本来存储1234567,倒置后buf中存储7654321. 不打印!!
// 倒置不允许使用辅助数组。
// 要求A线程打印出来的结果只能为 1234567 或者 7654321 不允许出现7634521 7234567
// 不允许使用sleep函数
#include <pthread.h>
#include <stdio.h>
char buf[] = "1234567";
/// @brief 线程体A
void* taskA(void*);
/// @brief 线程体B
void* taskB(void*);
int main(int argc, const char* argv[])
{
pthread_t tidA;
if (pthread_create(&tidA, NULL, taskA, NULL) != 0) {
printf("pthread_create tidA error\n");
return -1;
}
// 阻塞等待线程A退出
pthread_join(tide, NULL);
return 0;
}
void* taskA(void*)
{
pthread_t tidB;
while (1) {
// 创建线程B
if (pthread_create(&tidB, NULL, taskB, NULL) != 0) {
printf("pthread_create tidB error\n");
break;
}
// 阻塞等待线程B退出
pthread_join(tidB, NULL);
// 打印buf
printf("%s\n", buf);
}
}
void* taskB(void*)
{
int start = 0; // 第一个字符下标
int end = sizeof(buf) - 2; // 最后一个字符下标
// 逆置
while (start < end) {
buf[start] = buf[start] ^ buf[end];
buf[end] = buf[start] ^ buf[end];
buf[start] = buf[start] ^ buf[end];
start++;
end--;
}
// 退出线程B
pthread_exit(NULL);
}
3.作业三
要求用两个线程拷贝一张图片。A线程拷贝前半部分,B线程拷贝后半部分,不允许使用sleep函数
// 要求用两个线程拷贝一张图片。A线程拷贝前半部分,B线程拷贝后半部分,不允许使用sleep函数
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
// 定义回调函数需要的参数结构体
typedef struct data {
const char* destfile; // 目标文件名
const char* srcfile; // 源文件名
int start; // 光标开始位置
int len; // 数据长度
} task_t;
/// @brief 初始化目标文件
/// @param destfile 目标文件路径及名字
/// @return 成功0 失败-1
int init_destfile(const char* destfile);
/// @brief 计算文件大小
/// @param filename 文件路径及名字
/// @return 成功返回文件大小 失败返回-1
int get_size_file(const char* filename);
/// @brief 拷贝文件
/// @param destfile 目标文件
/// @param srcfile 源文件
/// @param start 光标开始位置
/// @param len 数据长度
/// @return 成功0 失败-1
int copy_file(const char* destfile, const char* srcfile, int start, int len);
/// @brief 线程体A
void* taskA(void* arg);
/// @brief 线程体B
void* taskB(void* arg);
int main(int argc, const char* argv[])
{
// 1.校验参数
if (argc != 3) {
printf("input error\n");
printf("usage: ./a.out srcFileName destFileName\n");
return -1;
}
// 2.初始化目标文件
if (init_destfile(argv[2])) {
return -1;
}
// 3.获取源文件大小
int size = get_size_file(argv[1]);
if (-1 == size) {
return -1;
}
// 4.定义回调函数所需参数
task_t data_A = { argv[2], argv[1], 0, size / 2 };
// 5.创建线程A
pthread_t tidA;
if (pthread_create(&tidA, NULL, taskA, &data_A) != 0) {
printf("pthread_create tidA error\n");
return -1;
}
// 6.阻塞等待线程A退出
pthread_join(tide, NULL);
return 0;
}
int init_destfile(const char* destfile)
{
// 1.打开文件
int fd = open(destfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (-1 == fd) {
perror("init_destfile open destfile");
return -1;
}
// 2.关闭文件
close(fd);
return 0;
}
int get_size_file(const char* filename)
{
// 1.打开文件
int fd = open(filename, O_RDONLY);
if (-1 == fd) {
perror("get_size_file open filename");
return -1;
}
// 2.移动光标,计算大小
int size = lseek(fd, 0, SEEK_END);
// 3.关闭文件
close(fd);
// 4.返回大小
return size;
}
int copy_file(const char* destfile, const char* srcfile, int start, int len)
{
// 1.打开两个文件
int destfd = open(destfile, O_RDWR);
if (-1 == destfd) {
perror("copy_file open destfile");
return -1;
}
int srcfd = open(srcfile, O_RDONLY);
if (-1 == srcfd) {
perror("copy_file open srcfile");
return -1;
}
// 2.设置光标位置
lseek(srcfd, start, SEEK_SET);
lseek(destfd, start, SEEK_SET);
int ret = 0; // 保存每次读取的字节数
int count = 0; // 保存已经读取的数据大小
char buf[128] = ""; // 保存读取到的数据
// 3.循环读取数据
while (1) {
// 4.读取数据
ret = read(srcfd, buf, sizeof(buf));
// 5.累加读取的数据大小
count += ret;
// 6.判断已经读取的数据大小是否超过len
if (count >= len) {
// 减去超出的数据
write(destfd, buf, ret - (count - len));
// 全部写完,退出循环
break;
}
// 7.写入数据
write(destfd, buf, ret);
}
// 8.关闭文件
close(srcfd);
close(destfd);
return 0;
}
void* taskA(void* arg)
{
// 1.获取参数
task_t* data_A = (task_t*)arg;
// 2.创建线程B回调函数所需参数
task_t data_B = {data_A->destfile, data_A->srcfile, data_A->len, data_A->len * 2 - data_A->len};
// 3.创建线程B
pthread_t tidB;
if (pthread_create(&tidB, NULL, taskB, &data_B) != 0) {
printf("pthread_create tidB error\n");
return NULL;
}
// 4.拷贝前半部分
copy_file(data_A->destfile, data_A->srcfile, data_A->start, data_A->len);
// 5.阻塞等待线程B退出
pthread_join(tidB, NULL);
// 6.退出线程A
pthread_exit(NULL);
}
void* taskB(void* arg)
{
// 1.获取参数
task_t* data_B = (task_t*)arg;
// 2.拷贝后半部分
copy_file(data_B->destfile, data_B->srcfile, data_B->start, data_B->len);
// 3.退出线程B
pthread_exit(NULL);
}