c语言练习【实现终端功能、dup2实现文件拷贝、read write文件加载到链表】
练习1:实现终端功能
请实现一个终端的功能,注意需要带有cd功能
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAX_CMD_LENGTH 1024 // 最大命令长度
#define MAX_ARG_COUNT 64 // 最大参数数量
// 显示提示符,通常是当前工作目录
void print_prompt() {
char cwd[MAX_CMD_LENGTH];
if (getcwd(cwd, sizeof(cwd)) != NULL) {
printf("%s$ ", cwd);
} else {
perror("getcwd");
}
}
// 执行命令
void execute_command(char **args) {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return;
} else if (pid == 0) { // 子进程执行命令
if (execvp(args[0], args) == -1) {
perror("execvp");
}
exit(1); // 如果 execvp 失败,退出子进程
} else { // 父进程等待子进程完成
wait(NULL);
}
}
// 处理用户输入的命令
void handle_command(char *input) {
char *args[MAX_ARG_COUNT];
char *token;
int i = 0;
// 去除输入末尾的换行符
input[strcspn(input, "\n")] = 0;
// 解析命令和参数
token = strtok(input, " ");
while (token != NULL) {
args[i++] = token;
token = strtok(NULL, " ");
}
args[i] = NULL;
// 判断是否是 cd 命令
if (args[0] != NULL && strcmp(args[0], "cd") == 0) {
if (args[1] == NULL) {
fprintf(stderr, "cd: missing argument\n");
} else if (chdir(args[1]) == -1) {
perror("cd");
}
} else if (args[0] != NULL && strcmp(args[0], "exit") == 0) {
// 退出命令
exit(0);
} else {
// 否则执行其他命令
execute_command(args);
}
}
int main() {
char input[MAX_CMD_LENGTH];
while (1) {
print_prompt(); // 打印提示符
if (fgets(input, sizeof(input), stdin) == NULL) {
perror("fgets");
break;
}
handle_command(input); // 处理命令
}
return 0;
}
练习2:dup2 fgets
请使用dup2 + fgets + printf 实现文件拷贝功能
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFFER_SIZE 1024
// 文件拷贝函数
void copy_file(const char *source, const char *destination) {
FILE *src_file = fopen(source, "r");
if (src_file == NULL) {
perror("Failed to open source file");
exit(1);
}
int dest_fd = open(destination, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (dest_fd == -1) {
perror("Failed to open destination file");
fclose(src_file);
exit(1);
}
// 重定向标准输出到目标文件
if (dup2(dest_fd, STDOUT_FILENO) == -1) {
perror("dup2 failed");
fclose(src_file);
close(dest_fd);
exit(1);
}
char buffer[BUFFER_SIZE];
while (fgets(buffer, sizeof(buffer), src_file)) {
// 使用printf输出到标准输出(现在已经被重定向到目标文件)
printf("%s", buffer);
}
fclose(src_file);
close(dest_fd);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <source file> <destination file>\n", argv[0]);
exit(1);
}
copy_file(argv[1], argv[2]);
printf("File copied successfully.\n");
return 0;
}
练习3:read write
请使用read 和 write 实现链表保存到文件,以及从文件加载数据到链表中的功能
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define FILENAME "linked_list.dat"
// 定义链表节点
typedef struct node {
int data;
struct node *next;
} node_t;
// 创建新的链表节点
node_t *create_node(int data) {
node_t *new_node = (node_t *)malloc(sizeof(node_t));
if (!new_node) {
perror("malloc");
exit(1);
}
new_node->data = data;
new_node->next = NULL;
return new_node;
}
// 将链表保存到文件
void save_list_to_file(node_t *head) {
int fd = open(FILENAME, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("open");
exit(1);
}
node_t *current = head;
while (current != NULL) {
// 写入每个节点的 data
if (write(fd, ¤t->data, sizeof(current->data)) == -1) {
perror("write");
close(fd);
exit(1);
}
current = current->next;
}
close(fd);
}
// 从文件加载链表数据
node_t *load_list_from_file() {
int fd = open(FILENAME, O_RDONLY);
if (fd == -1) {
perror("open");
return NULL;
}
node_t *head = NULL;
node_t *tail = NULL;
int data;
while (read(fd, &data, sizeof(data)) > 0) {
node_t *new_node = create_node(data);
if (head == NULL) {
head = new_node;
tail = head;
} else {
tail->next = new_node;
tail = tail->next;
}
}
close(fd);
return head;
}
// 打印链表
void print_list(node_t *head) {
node_t *current = head;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("NULL\n");
}
// 释放链表内存
void free_list(node_t *head) {
node_t *current = head;
while (current != NULL) {
node_t *temp = current;
current = current->next;
free(temp);
}
}
int main() {
// 创建一个链表
node_t *head = create_node(10);
head->next = create_node(20);
head->next->next = create_node(30);
printf("原来的:\n");
print_list(head);
// 保存链表到文件
save_list_to_file(head);
// 释放原链表
free_list(head);
// 从文件加载链表
node_t *loaded_head = load_list_from_file();
printf("\n加载后的:\n");
print_list(loaded_head);
// 释放加载的链表
free_list(loaded_head);
return 0;
}