多文件編程,《Linux編程》上機作業 ·004【文件I/O操作】

 2023-10-21 阅读 27 评论 0

摘要:注:前言、目錄見 https://blog.csdn.net/qq_44220418/article/details/108428971 友情提醒:僅供參考理解,請勿直接復制粘貼 友情提醒:僅供參考理解,請勿直接復制粘貼 友情提醒:僅供參考理解,請勿直接復制粘貼 文章目錄第一題

注:前言、目錄見 https://blog.csdn.net/qq_44220418/article/details/108428971

友情提醒:僅供參考理解,請勿直接復制粘貼

友情提醒:僅供參考理解,請勿直接復制粘貼

友情提醒:僅供參考理解,請勿直接復制粘貼

文章目錄

  • 第一題
  • 第二題
  • 第三題

第一題

模擬Linux的cp命令
編寫一個C語言程序,該程序產生的可執行文件名為cpx,其功能類似于cp命令。


當執行cpx A BAB為任意兩個文件名)時,會將文件A復制為文件B
cpx后面沒有跟文件名做參數,或是沒有跟兩個文件名,則報錯

/** 思路:一邊讀一邊寫,模擬復制* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>#define LEN 10005
#define RD_ONCE 100char error[LEN] = "";
char buf[RD_ONCE] = "";int main(int argc, char *argv[])
{// 如果沒有傳入的參數少于2個,則報錯if (argc < 3){perror("錯誤:傳入的參數個數少于2個");exit(1);}// 測試復制的目標文件是否存在if (access(argv[2], F_OK) != -1){sprintf(error, "錯誤:目標文件 %s 已存在", argv[2]);perror(error);exit(2);}// 打開文件int fd1 = open(argv[1], O_RDONLY);int fd2 = open(argv[2], O_RDWR | O_CREAT, 0755);if (fd1 == -1){sprintf(error, "錯誤:源文件 %s 打開失敗", argv[1]);perror(error);exit(3);}if (fd2 == -1){sprintf(error, "錯誤:目標文件 %s 創建失敗", argv[2]);perror(error);exit(4);}// 讀取文件,同時寫入while (read(fd1, buf, sizeof(buf) - 1)){write(fd2, buf, strlen(buf));// 每次操作完成使用memset函數把字符串清空// 避免讀取字節數少于字符串容量時報錯memset(buf, 0, RD_ONCE);}// 關閉文件close(fd1);close(fd2);return 0;
}

示例截圖
在這里插入圖片描述

第二題

編寫C程序sortx.c,完成將一個無序的數據文件userdata.txt遞增(A)或遞減(D)排序后輸出到指定的磁盤文件中。


如:
\qquaduserdata.txt內容為:34 -3 8 -12 6
\qquad執行sortx D myorder.txt后,myorder.txt文件的內容為:34 8 6 -3 -12

/** 生成輸入字符串后,思路同【作業003】第2、3題* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>#define N 1000      // 假定文件總的輸入的整數個數少于1000
#define I_N 10      // 假定文件總的輸入的整數長度少于10
#define LEN 500     // 假定文件每個的輸入的整數字符串長度少于500假定文件總的輸入的整數長度少于10
#define ERR_LEN 500 // 假定文件每個的輸入的整數字符串長度少于500char file_str[LEN]; // 文件讀取的輸入字符串int a[N];           // 存儲整數的數組
int cnt = 0;        // 存儲輸入整數的個數size_t len = 0;     // 切割字符串長度參數
char *part;         // 存儲切割部分的字符串char num[N];        // 存儲要每次寫入的內容字符串char error[ERR_LEN] = "";   // 報錯字符串// 比較函數1(用于降序排列)
int cmp1(const void*a, const void*b)
{return *(int*)(b)-*(int*)(a);
}// 比較函數2(用于升序排列)
int cmp2(const void*a, const void*b)
{return *(int*)(a)-*(int*)(b);
}int main(int argc, char *argv[])
{// 參數獲取、判斷if (argc < 3){perror("錯誤:參數個數少于2個");exit(1);}// 讀取參數文件的數組字符串int fd1 = open("userdata.txt", O_RDONLY);if (fd1 == -1){perror("錯誤:文件 userdata.txt 打開失敗");exit(2);}read(fd1, file_str, sizeof(file_str) - 1);close(fd1);// 用strsep函數切割C式字符串char* buff = file_str;while ((part = strsep(&buff, " ")) != NULL)a[cnt++] = atoi(part);  // 用atoi函數將C式字符串轉換為int并存入數組// 根據第一個參數A/D,用qsort函數降序排列if (strcmp(argv[1], "A") == 0)qsort(a, cnt, sizeof(int), cmp2);else if (strcmp(argv[1], "D") == 0)qsort(a, cnt, sizeof(int), cmp1);else{sprintf(error, "錯誤:排序選項參數 %s 有誤", argv[1]);perror(error);exit(3);}// 將數組寫入文件int fd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0755);if (fd == -1){sprintf(error, "錯誤:文件 %s 打開失敗", argv[2]);perror(error);exit(2);}for (int i = 0; i < cnt; ++i){int bytes = sprintf(num, "%d ", a[i]);write(fd, num, bytes);}write(fd, "\n", strlen("\n"));close(fd);return 0;
}

示例截圖
在這里插入圖片描述

第三題

編寫C程序listdir.c,執行listdir sub1完成將當前目錄下子目錄如sub1中的所有文件名列出(列表字段為:權限碼 文件名 長度)

/** 思路同【作業003】的第4題* 不過當時寫的思路2直接切換工作目錄并沒有與考慮到目錄不存在不會產生錯誤,現在已糾正*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>#define LEN 1000  // 假定路徑字符串長度少于1000char path[LEN] = "";
char acc[11];  // 全局變量(堆區)存儲函數 getAccess 要返回的字符串
const char acc_init[11] = "----------";   // 每次用acc_init初始化accchar error[LEN] = "";   // 錯誤字符串// 獲取文件類型對應字符
char getType(__mode_t mode)
{if (S_ISDIR(mode)) return 'd';if (S_ISCHR(mode)) return 'c';if (S_ISBLK(mode)) return 'b';if (S_ISSOCK(mode)) return 's';if (S_ISFIFO(mode)) return 'p';if (S_ISLNK(mode)) return 'l';return '-';
}// 獲取文件權限字符串
const char* getAccess(__mode_t mode)
{// 文件類型strcpy(acc, acc_init);acc[0] = getType(mode);// 文件權限// 判斷用戶權限if (mode & S_IRUSR) acc[1] = 'r';if (mode & S_IWUSR) acc[2] = 'w';if (mode & S_IXUSR) acc[3] = 'x';// 判斷組權限if (mode & S_IRGRP) acc[4] = 'r';if (mode & S_IWGRP) acc[5] = 'w';if (mode & S_IXGRP) acc[6] = 'x';// 判斷其他用戶權限if (mode & S_IROTH) acc[7] = 'r';if (mode & S_IWOTH) acc[8] = 'w';if (mode & S_IXOTH) acc[9] = 'x';return acc;
}int main(int argc, char *argv[])
{// 如果沒有傳入參數,則默認選擇當前目錄if (argc < 2)strcpy(path, ".");elsestrcpy(path, argv[1]);// 判斷目錄是否存在if (access(path, F_OK) == -1){sprintf(error, "錯誤:目標目錄 %s 不存在", path);perror(error);exit(1);}// 切換當前工作目錄int res = chdir(path);// 打開指定目錄DIR * dir_ptr = opendir(".");struct dirent * dir;if (dir_ptr == NULL){sprintf(error, "錯誤:目標目錄 %s 打開失敗", path);perror(error);exit(2);}// 讀取每一個目錄項,構造stat獲取其屬性struct stat buf;printf("%-20s%-30s%-30s\n", "access", "filename", "length(Byte)");printf("----------------------------------------------------------------------\n");while ((dir = readdir(dir_ptr)) != NULL){// 構造stat,讀取文件屬性int res = lstat(dir->d_name, &buf);if (res == -1){sprintf(error, "錯誤:讀取目標文件 %s 的屬性失敗", dir->d_name);perror(error);exit(3);}printf("%-20s%-30s%-30ld\n", getAccess(buf.st_mode), dir->d_name, buf.st_size);}return 0;
}

示例截圖
在這里插入圖片描述

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/156078.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息