🦄 refactor(C14, C15):

This commit is contained in:
lzy
2024-05-16 21:57:14 +08:00
parent 60d670d130
commit b66e536177
34 changed files with 2 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TIMESTRSIZE 128
/**
* @brief 找出100天以后是哪一天
* @details
*
* @param argc
* @param argv
*
* @return int
*/
int main(int argc, char **argv)
{
time_t stamp;
struct tm *tm;
char timestr[TIMESTRSIZE];
time(&stamp);
tm = localtime(&stamp);
strftime(timestr, TIMESTRSIZE, "Now: %Y-%m-%d", tm);
puts(timestr);
tm->tm_mday += 100;
// mktime 会先调整tm溢出的情况
mktime(tm);
strftime(timestr, TIMESTRSIZE, "100 days later: %Y-%m-%d", tm);
puts(timestr);
exit(0);
}

View File

@@ -0,0 +1,205 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#if 1
# define debug(fmt, args...) printf(fmt, ##args)
#else
# define debug(fmt, args...)
#endif
/**
* @brief 读取一行
* @details
* 循环读入一个字符
* 如何判断读完一行? 读到0x0d, 0x0a
*
* @param fd
* @param buf
*
* @return int 读到的一行数据的数据个数( n>=0 )
* -1: 读到文件尾部或者出错
*/
static int read_line(int fd, unsigned char *buf)
{
unsigned char c;
int len;
int i = 0;
int err = 0;
while (1)
{
len = read(fd, &c, 1);
if (len <= 0)
{
err = -1;
break;
}
else
{
if (c != '\n' && c != '\r')
{
buf[i] = c;
i++;
}
else /* 碰到回车换行 */
{
err = 0;
break;
}
}
}
buf[i] = '\0';
if (err && (0 == i))
/* 读到文件尾部且无有效数据 */
return -1;
else
return i;
}
/**
* @brief 处理一行的数据, 计算出总分和评价
* @details
*
* @param data_buf
* @param result_buf
*
* @return int
*/
static void process_data(unsigned char *data_buf, unsigned char *result_buf)
{
/**
* eg1: data_buf=",语文,数学,英语,总分,评价"
* result_buf=",语文,数学,英语,总分,评价"
*
* eg2: data_buf="张三,90,91,92,,"
* result_buf="张三,90,91,92,273,A+"
*
*/
char name[100];
int scores[3];
int sum;
char *levels[] = {"A+", "A", "B"};
int level;
// debug("data_buf[0]: %x\n", data_buf[0]);
if (0xef == data_buf[0]) /* 对于UTF-8, 前三个字符是0xef 0xbb 0xbf */
{
strcpy(result_buf, data_buf);
}
else
{
// debug("data_buf: %s\n", data_buf);
// debug("进入了\n");
/**
* @brief 从字符串得到数据
* @details
* 拆分信息: scanf分隔符
* %[^,]: 读数据直到碰到逗号
*
*/
sscanf(data_buf,
"%[^,],%d,%d,%d,,",
name,
&scores[0],
&scores[1],
&scores[2]);
debug("name: %s, scores: %d, %d, %d\n",
name,
scores[0],
scores[1],
scores[2]);
sum = scores[0] + scores[1] + scores[2];
if (sum >= 270)
level = 0;
else if (sum >= 240)
level = 1;
else
level = 2;
sprintf(result_buf,
"%s,%d,%d,%d,%d,%s",
name,
scores[0],
scores[1],
scores[2],
sum,
levels[level]);
}
}
/**
* @brief 处理csv表格
* @details
* Usage: ./W_process_excel data.csv result.csv
*
* @param argc
* @param argv
*
* @return int
*/
int main(int argc, char **argv)
{
int fd_data, fd_result;
int len;
unsigned char data_buf[1000];
unsigned char result_buf[1000];
if (argc != 3)
{
printf("Usage: %s data.csv result.csv\n", argv[0]);
exit(1);
}
fd_data = open(argv[1], O_RDONLY);
if (fd_data < 0)
{
perror("open data.csv");
exit(1);
}
else
printf("data file fd: %d\n", fd_data);
fd_result = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd_result < 0)
{
perror("open result.csv");
exit(1);
}
else
printf("result file fd: %d\n", fd_result);
while (1)
{
/* 读取1行 */
len = read_line(fd_data, data_buf);
if (-1 == len)
break;
// if (len != 0)
// debug("%s\n\r", data_buf);
if (len != 0)
{
/* 处理1行 */
process_data(data_buf, result_buf);
/* 写入结果文件 */
write(fd_result, result_buf, strlen(result_buf));
write(fd_result, "\r\n", 2);
}
}
close(fd_data);
close(fd_result);
exit(0);
}

View File

@@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdlib.h>
static void f1(void)
{
puts("f1() is working!");
}
static void f2(void)
{
puts("f2() is working!");
}
static void f3(void)
{
puts("f3() is working!");
}
int main(int argc, char **argv)
{
puts("Begin!");
atexit(f1);
atexit(f2);
atexit(f3);
puts("End!");
exit(0);
}
// out:
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ ./atexit
// Begin!
// End!
// f3() is working!
// f2() is working!
// f1() is working!

34
C14-文件系统/fs/big.c Normal file
View File

@@ -0,0 +1,34 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "Usage:...\n");
exit(1);
}
int fd;
fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0)
{
perror("open()");
exit(1);
}
// 生成一个5G的文件
// !!! 整数溢出
lseek(fd, 5LL * 1024LL * 1024LL * 1024LL - 1LL, SEEK_SET);
// 写入尾0
write(fd, "", 1);
close(fd);
exit(0);
}

View File

@@ -0,0 +1,46 @@
#include <crypt.h>
#include <shadow.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/**
* @brief 加密输入的密码并与shadow文件中的密码进行比较
* @details
* !!! compile: gcc check.c -o check -lcrypt
* !!! 需要root权限运行
*
* @param argc
* @param argv [in] 用户名
*
* @return int
*/
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "Usage:...\n");
exit(1);
}
char *input_pass;
struct spwd *shadowline;
char *crypt_pass;
//* getpass()函数在输入密码时不会回显密码
input_pass = getpass("PassWord: ");
//* getspnam()函数通过用户名获取shadow文件中的密码
shadowline = getspnam(argv[1]);
//* 加密输入的密码
crypt_pass = crypt(input_pass, shadowline->sp_pwdp);
if (0 == strcmp(crypt_pass, shadowline->sp_pwdp))
puts("OK!");
else
puts("Error!");
exit(0);
}

View File

@@ -0,0 +1,4 @@
,语文,数学,英语,总分,评价
张三,90,91,92,,
李四,80,81,82,,
王五,70,71,72,,
1 语文 数学 英语 总分 评价
2 张三 90 91 92
3 李四 80 81 82
4 王五 70 71 72

View File

@@ -0,0 +1,41 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
// !!! 不是int
static off_t flen(char *fname)
{
struct stat statres;
if (stat(fname, &statres) < 0)
{
perror("stat()");
exit(1);
}
return statres.st_size;
}
/**
* @brief 获取文件大小
* @details
* Usage: ./flen filename
*
* @param argc
* @param argv
* @return int
*/
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "Usage:...\n");
exit(1);
}
// !!! 通过makefile指定off_t 64位
printf("%lld\n", flen(argv[1]));
exit(0);
}

View File

@@ -0,0 +1,54 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
static int ftype(const char *fname)
{
struct stat statres;
if (stat(fname, &statres) < 0)
{
perror("stat()");
exit(1);
}
if (S_ISREG(statres.st_mode))
return '-';
else if (S_ISDIR(statres.st_mode))
return 'd';
else if (S_ISSOCK(statres.st_mode))
return 's';
else if (S_ISFIFO(statres.st_mode))
return 'p';
else if (S_ISBLK(statres.st_mode))
return 'b';
else if (S_ISCHR(statres.st_mode))
return 'c';
else if (S_ISLNK(statres.st_mode))
return 'l';
else
return '?';
}
/**
* @brief 获取文件类型
* @details
* Usage: ftype <filename>
*
* @param argc
* @param argv
*
* @return int
*/
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "Usage:...\n");
exit(1);
}
printf("%c\n", ftype(argv[1]));
exit(0);
}

View File

@@ -0,0 +1,17 @@
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
puts(getenv("PATH"));
getchar();
/**
* ./getenv
* ps axf | grep getenv
* pmap 4938
*/
exit(0);
}

View File

@@ -0,0 +1,46 @@
#include <glob.h>
#include <stdio.h>
#include <stdlib.h>
// #define PAT "/etc/a*.conf"
#define PAT "/etc/*" // 不包括隐藏文件 .*
#if 0
static int errfunc_(const char *errpath, int eerrno)
{
puts(errpath);
fprintf(stderr, "ERROR MSG: %s\n", strerror(eerrno));
return 0;
}
#endif
/**
* @brief ls /etc/a*.conf
* @details
*
* @param argc
* @param argv
*
* @return int
*/
int main(int argc, char **argv)
{
glob_t globres;
int err;
err = glob(PAT, 0, NULL, &globres);
if (err)
{
printf("ERROR CODE = %d\n", err);
exit(1);
}
for (int i = 0; i < globres.gl_pathc; i++)
{
puts(globres.gl_pathv[i]);
}
// !!!
globfree(&globres);
exit(0);
}

99
C14-文件系统/fs/jmp.c Normal file
View File

@@ -0,0 +1,99 @@
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
static jmp_buf save;
static void d(void)
{
printf("%s():Begin.\n", __FUNCTION__);
printf("%s():Jump now.\n", __FUNCTION__);
longjmp(save, 6);
// longjmp(save, 0); // !!! 如果返回0实际会返回1避免与另一种情况冲突
printf("%s():End.\n", __FUNCTION__);
}
static void c(void)
{
printf("%s():Begin.\n", __FUNCTION__);
printf("%s():Call d().\n", __FUNCTION__);
d();
printf("%s():d() returned.\n", __FUNCTION__);
printf("%s():End.\n", __FUNCTION__);
}
static void b(void)
{
printf("%s():Begin.\n", __FUNCTION__);
printf("%s():Call c().\n", __FUNCTION__);
c();
printf("%s():c() returned.\n", __FUNCTION__);
printf("%s():End.\n", __FUNCTION__);
}
static void a(void)
{
int ret;
printf("%s():Begin.\n", __FUNCTION__);
ret = setjmp(save);
if (0 == ret)
{
printf("%s():Call b().\n", __FUNCTION__);
b();
printf("%s():b() returned.\n", __FUNCTION__);
}
else
{
printf("%s():Jumped back here with code %d.\n", __FUNCTION__, ret);
}
printf("%s():End.\n", __FUNCTION__);
}
/**
* @brief jmp
* @details
* d跳回a
*
* @param argc
* @param argv
* @return int
*/
int main(int argc, char **argv)
{
printf("%s():Begin.\n", __FUNCTION__);
printf("%s():Call a().\n", __FUNCTION__);
a();
printf("%s():a() returned.\n", __FUNCTION__);
printf("%s():End.\n", __FUNCTION__);
exit(0);
}
// ! out
// main():Begin.
// main():Call a().
// a():Begin.
// a():Call b().
// b():Begin.
// b():Call c().
// c():Begin.
// c():Call d().
// d():Begin.
// d():Jump now.
// a():Jumped back here with code 6.
// a():End.
// main():a() returned.
// main():End.

View File

@@ -0,0 +1,15 @@
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
printf("argc = %d\n", argc);
// for (int i = 0; i < argc; i++)
for (int i = 0; argv[i] != NULL; i++)
{
puts(argv[i]);
}
exit(0);
}

View File

@@ -0,0 +1,13 @@
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
printf("Hello, World!\n");
return 0;
/*
* echo $?
* 0
*/
}

View File

@@ -0,0 +1,109 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define TIMESTRSIZE 1024
#define FMTSTRSIZE 1024
/**
* @brief mydate
* @details
* Usage:
* mydate [-H 12|24] [-y 2|4] [-m] [-d] [-M] [-S]
* Options:
* -y: year 2位,4位
* -m: month
* -d: day
* -H: hour 12小时制,24小时制
* -M: minute
* -S: second
*
* @param argc
* @param argv
*
* @return int
*/
int main(int argc, char **argv)
{
time_t stamp;
struct tm *tm;
char timestr[TIMESTRSIZE];
int c;
char fmtstr[FMTSTRSIZE];
fmtstr[0] = '\0';
FILE *fp = stdout;
time(&stamp);
tm = localtime(&stamp);
while (1)
{
//* 选项传参
// c = getopt(argc, argv, "H:y:MSmd");
//* 加'-',接收非选项传参
c = getopt(argc, argv, "-H:y:MSmd");
if (c < 0)
break;
switch (c)
{
//* 非选项传参返回1
case 1:
if (stdout == fp) //! 先入为主
{
fp = fopen(argv[optind - 1], "w");
if (NULL == fp)
{
perror("fopen()");
fp = stdout;
}
}
break;
case 'H':
if (0 == strcmp(optarg, "12"))
strncat(fmtstr, "%I(%P) ", FMTSTRSIZE - 1);
else if (0 == strcmp(optarg, "24"))
strncat(fmtstr, "%H ", FMTSTRSIZE - 1);
else
fprintf(stderr,
"Usage: %s [-H 12|24] [-y 2|4] [-m] [-d] [-M] [-S]\n",
argv[0]);
break;
case 'M': strncat(fmtstr, "%M ", FMTSTRSIZE - 1); break;
case 'S': strncat(fmtstr, "%S ", FMTSTRSIZE - 1); break;
case 'y':
if (0 == strcmp(optarg, "2"))
strncat(fmtstr, "%y ", FMTSTRSIZE - 1);
else if (0 == strcmp(optarg, "4"))
strncat(fmtstr, "%Y ", FMTSTRSIZE - 1);
else
fprintf(stderr,
"Usage: %s [-H 12|24] [-y 2|4] [-m] [-d] [-M] [-S]\n",
argv[0]);
break;
case 'm': strncat(fmtstr, "%m ", FMTSTRSIZE - 1); break;
case 'd': strncat(fmtstr, "%d ", FMTSTRSIZE - 1); break;
default: break;
}
}
strncat(fmtstr, "\n", FMTSTRSIZE - 1);
strftime(timestr, TIMESTRSIZE, fmtstr, tm);
fputs(timestr, fp);
if (fp != stdout)
fclose(fp);
exit(0);
}

125
C14-文件系统/fs/mydu.c Normal file
View File

@@ -0,0 +1,125 @@
#include <glob.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#define PATHSIZE 1024
static int path_noloop(const char *path)
{
char *pos;
/**
* @brief strrchr
* @details
*
* 找到 path 中最后一个 '/' 字符的位置
*/
pos = strrchr(path, '/');
if (NULL == pos)
exit(1);
if ((0 == strcmp(pos + 1, ".") || 0 == strcmp(pos + 1, "..")))
return 0;
return 1;
}
static int64_t mydu(const char *path)
{
// 优化递归
// 将部分与递归无关的变量拿出栈,用 static 修饰
static struct stat statres;
static char nextpath[PATHSIZE];
glob_t globres;
int64_t sum;
int i;
if (lstat(path, &statres) < 0)
{
perror("lstat()");
exit(1);
}
if (!S_ISDIR(statres.st_mode))
{
/* 非目录 */
return statres.st_blocks;
/*
* st_blocks 代表磁盘块数量一个磁盘块大小为512字节
* 所以除以2才表示多少个1k字节
*/
}
/* 目录 */
/* 例如:/aaa/bbb/ccc/ddd/eee/fff */
strncpy(nextpath, path, PATHSIZE);
strncat(nextpath, "/*", PATHSIZE); //[W]
// if (glob(nextpath, 0, NULL, &globres))
// {
// perror("glob(), 1");
// exit(1);
// }
glob(nextpath, 0, NULL, &globres);
// !!! 要考虑 . 和 .. 目录
strncpy(nextpath, path, PATHSIZE);
strncat(nextpath, "/.*", PATHSIZE); //[W]
/*
* 这个警告是因为 strncat 函数的第三个参数(即 PATHSIZE等于目标字符串
* nextpath 的大小。这可能会导致 nextpath 缓冲区溢出,因为 strncat
* 函数会在目标字符串的末尾添加一个 null 字符('\0')。
*/
// !!! APPEND
// if (glob(nextpath, GLOB_APPEND, NULL, &globres))
// {
// perror("glob(), APPEND");
// exit(1);
// }
glob(nextpath, GLOB_APPEND, NULL, &globres);
sum = statres.st_blocks;
for (i = 0; i < globres.gl_pathc; i++)
{
if (path_noloop(globres.gl_pathv[i]))
{
sum += mydu(globres.gl_pathv[i]);
}
}
// !!!
globfree(&globres);
return sum;
}
/**
* @brief mydu
* @details
* Usage: mydu [FILE]...
*
* 用到了递归的思想
*
* !!! 未考虑权限问题
*
* @param argc
* @param argv
*
* @return int
*/
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "Usage: mydu [FILE]...\n");
exit(1);
}
printf("%lld\n", mydu(argv[1]) / 2);
exit(0);
}

View File

@@ -0,0 +1,13 @@
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
int main(int argc, char **argv)
{
for (int i = 0; environ[i] != NULL; i++)
puts(environ[i]);
exit(0);
}

View File

@@ -0,0 +1,38 @@
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#define PAT "/etc"
/**
* @brief 解析PAT下文件个数
* @details
*
* @param argc
* @param argv
*
* @return int
*/
int main(int argc, char **argv)
{
DIR *dp;
struct dirent *cur;
dp = opendir(PAT);
if (NULL == dp)
{
perror("opendir()");
exit(1);
}
// !!! 注意括号
while ((cur = readdir(dp)) != NULL)
{
puts(cur->d_name);
}
closedir(dp);
exit(0);
}

View File

@@ -0,0 +1,4 @@
,语文,数学,英语,总分,评价
张三,90,91,92,273,A+
李四,80,81,82,243,A
王五,70,71,72,213,B
1 语文 数学 英语 总分 评价
2 张三 90 91 92 273 A+
3 李四 80 81 82 243 A
4 王五 70 71 72 213 B

View File

@@ -0,0 +1,86 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define FNAME "time.log"
#define BUFSIZE 1024
/**
* @brief 往文件里面输出时间戳
* @details
* 实例格式2019-12-12 12:12:12
*
* @param argc
* @param argv
*
* @return int
*/
int main(int argc, char **argv)
{
FILE *fp;
time_t stamp;
struct tm *tm;
char buf[BUFSIZE];
int count = 0;
fp = fopen(FNAME, "a+");
if (fp == NULL)
{
perror("fopen()");
exit(1);
}
while (fgets(buf, BUFSIZE, fp) != NULL)
count++;
while (1)
{
stamp = time(NULL);
tm = localtime(&stamp);
if (NULL == tm)
{
perror("localtime()");
exit(1);
}
strftime(buf, BUFSIZE, "%Y-%m-%d %H:%M:%S", tm);
fprintf(fp, "%-4d%s\n", ++count, buf);
/*
* 加了sleep(1)之后就没有输出?
* 全缓冲
* 因为缓冲区没有满,没有刷新到文件里面
*/
fflush(fp);
sleep(1);
}
fclose(fp);
exit(0);
}
//! 最终效果
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ ./test
// ^C
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ cat time.log
// 1 2024-05-11 21:53:26
// 2 2024-05-11 21:53:27
// 3 2024-05-11 21:53:28
// 4 2024-05-11 21:53:29
// 5 2024-05-11 21:53:30
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ ./test
// ^C
// *[main][~/Linux-C-Notes/C13-Linux系统编程/fs]$ cat time.log
// 1 2024-05-11 21:53:26
// 2 2024-05-11 21:53:27
// 3 2024-05-11 21:53:28
// 4 2024-05-11 21:53:29
// 5 2024-05-11 21:53:30
// 6 2024-05-11 21:53:35
// 7 2024-05-11 21:53:36
// 8 2024-05-11 21:53:37
// 9 2024-05-11 21:53:38

View File

@@ -0,0 +1,29 @@
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
/**
* @brief 用user id获取用户名
* @details
*
* @param argc
* @param argv
*
* @return int
*/
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "Usage: %s <user id>\n", argv[0]);
exit(1);
}
struct passwd *pwdline;
pwdline = getpwuid(atoi(argv[1]));
puts(pwdline->pw_name);
exit(0);
}