添加作者信息、介绍与时间于任意文件末尾 --正在更新(自定义C语言练习(一))

目录

  • 程序功能简述
    • 需求/原因
    • 目的
  • 源代码结构
    • main.c -- 主代码
    • data.c -- 数据类型等
    • data.h
    • info.c -- 介绍信息等
    • info.h
    • fent.c -- 文件事件等
    • fent.h
  • 程序功能介绍
    • 程序相关指令
    • 程序的使用介绍
  • 未来程序改善

                         QQ:3020889729                                                                                 小蔡

程序功能简述

在这里插入图片描述
添加作者信息、介绍与时间于任意文件末尾 --正在更新(自定义C语言练习(一))_第1张图片

需求/原因

  1. 为了解决文件或者文本在提交时,附加文本备注信息–比如作者
  2. 鉴于对C语言设计流程逻辑的训练,基本实现字符串操作,指针,标准文件IO与时间相关操作的练习
  3. 熟悉模块化编程,设计一定的数据结构以锻炼代码思维

目的

  • 提高对C语言程序的熟练度
  • time.h, stdlib.h, string.h, stdio.h有更多的了解
  • 熟悉宏连接,##, 在一定环境下提高命名的规范性
  • 简单了解一个程序的完整:①对异常的处理;②可执行完成任务;③能给用户一定的使用反馈信息等

源代码结构

main.c – 主代码

代码结构:

  1. 完成主要功能的组合与实现
  2. 指令匹配
  3. 文件打开、写入与关闭
  4. 相关异常信息的输出
#include 
#include "info.h"    // 介绍相关
#include "data.h"    // 数据相关
#include "fent.h"	 // 文件相关

int main(int argc, char * argv[])
{
	FILE* fp[argc];  													// start_index~argc-1  -- 文件指针
	char order_set[SET_SIZE][ORDER_SIZE] = {"-h", "-v", "-a", "-ha"};	// 指令集--程序当前拥有的指令
	char order_now[ORDER_SIZE] = {0};									// 当前匹配的指令
	order_list order_task = NULL;  										// 程序的指令任务 -- 未设计(更新)
	int start_index = 0;  												// 第一个文件所在参数的索引号
	int check_flag = 0;   												// 检查是否为指令的标志
	int auto_flag = 0;													// 是否自动添加相关信息到指定文件的标志
	char info_str[2][128] = {0};										// 作者信息与相关信息的buf
	char model[] = Model_info;  // 模板数据
	
	if(argc == 1)  // 判断是否输入相关指令和参数
	{
		printf("Please enter anothor element!(more than 1...)\n");
		return -1;
	}
	else
	{
		do  // 指令排查
		{
			if(check_flag != 0) ;  // 待添加指令任务节点,链表操作
			start_index++;
			if(start_index == argc) break;
			check_flag = _match_order(order_now, argv[start_index], order_set, SET_SIZE);
			if(check_flag == 3) {printf("The order %s is wrong!\n", argv[start_index]);return -1;}  // 存在伪指令退出
			if(check_flag == 2) auto_flag = 1;
		}while(check_flag);
		
		// 如果auto_flag=1, 则说明应该开启自动化添加----自动化功能待添加
		// 如果auto_flag=0,  则将前两个参数作为author 与 function_info 数据
		if(!auto_flag)
		{
			if(argc >= (start_index+1))
			{
				info_create(argv[start_index], strlen(argv[start_index]),argv[start_index+1], strlen(argv[start_index+1]), info_str);   // 创建完整的介绍信息:author + function_info + model
				start_index += 2;  // 移动文件起始index往后
			}
		}
		else
		{
			printf("Auto_function has finished!\n");
		}
		
		// 打开文件--并返回文件流指针
		// 读写文件
		for(int i = start_index; i < argc; ++i)
		{
			if(!open_file(argv[i], &fp[i])) printf("Open the %s false!(please check the path.)\n", argv[i]);   // FILE** file 作为文件参数:方可修改指针的值(一级指针只能修改指针指向的内容)
			else 
			{
				printf("Open the %s ok!\n", argv[i]);
				write_file(fp[i], info_str, model, strlen(model));  // 写入信息
			}
		}
	}

	for(int i = start_index; i < argc; ++i)   // 关闭所有打开的文件 -- 注意本身未被使用的文件流不要打开
	{
		if(!close_file(fp[i])) printf("Close the FP[%d] false!\n", i);
	}
	
	printf("\nPRPGRAM OVER!");
	return 0;
}

data.c – 数据类型等

代码结构:

  1. 完成介绍信息配置的info_create函数
  2. 完成当前时间字符串的获取
#include "data.h"

// functions:合并输入的自定义介绍信息
// input: 作者信息以及长度, 功能介绍信息以及长度, 整和的字节数据
// return: void
void info_create(const char* author, const int author_len, const char* function_infos, const int function_len, char str[INFO_LEN][INFO_SIZE])
{
	for(int i = 0; i < author_len; ++i)  // 将数据按字符依次写入第一维
	{
		str[0][i] = author[i];
	}
	for(int i = 0; i < function_len; ++i)  // 将数据按字符依次写入第二维
	{
		str[1][i] = function_infos[i];
	}
}

// functions:获取时间字符串
// input: char *
// return: void
void get_time_str(char * str)
{
	time_t local_t = 0;
	struct tm *time_st = NULL;
	char * weekdays[7] = {"Sunday", "Monday", "Tuesday", "Wednsday", "Thursday", "Friday", "Saturday"};  // 用于遍历星期几
	local_t = time(0);  // 当前时间的secs
	time_st = localtime(&local_t);  // 转换为tm结构体
	sprintf(str, "%d-%d-%d %02d:%02d:%02d %s", time_st->tm_year + 1900, time_st->tm_mon + 1, time_st->tm_mday, time_st->tm_hour, time_st->tm_min,time_st->tm_sec, weekdays[time_st->tm_wday]);  // 获取字符串
}

data.h

代码结构:

  1. 完成data.c函数的声明
  2. 完成相关数据宏的声明以及主要数据类型的声明
  3. 完成介绍基本模板的宏创建
#ifndef _DATA_CONFIG_
#define _DATA_CONFIG_

#include 
#include 
#include 

#define INFO_LEN							2
#define INFO_SIZE							128
#define SET_SIZE							4
#define ORDER_SIZE							4
#define ok 									1
#define false 								0
#define Model_info							"\n------------------------------------\n------------------------------------\n/*\n*  Author: \n*  Function: \n*  Time: \n*/\n------------------------------------\n------------------------------------"

typedef unsigned char state;  // 函数状态
typedef struct order_lists{
	char * order;	// 指令
	int len;    	// 指令长度
	struct order_lists* next;   // 下一个指令节点
}* order_list;   // 指令集合



void info_create(const char* author, const int author_len, const char* function_infos, const int function_len, char str[2][128]);  // 创建完整介绍信息
void get_time_str(char * str);  // 获取时间字符串

#endif

info.c – 介绍信息等

代码结构:

  1. 完成相关介绍信息展示函数的定义
  2. void _help_order_info();
  3. void _version_order_info(void);
  4. void _auto_order_info(void);
  5. 完成指令匹配的函数的定义
  6. state _match_order(char * order_now, const char* order, const char (*order_set)[ORDER_SIZE], int set_len);
#include "info.h"


/**************************************************/

				/*	0.指令部分	*/

/**************************************************/

// functions:展示程序帮助信息
// input: void
// return: void
void _help_order_info(void)
{
	// 这里采用简单c风格字符串
	// 可使用结构体进行链表式创建
	char INFO(0)[] = "\nThe -h order:\n";
	char INFO(1)[] = "The input and output of the program:\n\n\t -order\n\t author function_info file_paths\n\n";
	char INFO(2)[] = "Program instructions use a normal format:\n\n\t program -h\n\t program -v\n\t program -a info_path file_paths\n\t program author function_info file_paths\n\n";
	char INFO(3)[] = "Method of application:\n\n\t 1. If you are using the default template, enter the author name with the specified file to be added (avoid Spaces and carriage returns)\n(The introduction will wrap itself)\n\t\t program author function_info file_paths\n\t 2. If you want to use a custom template, create a specific text file and use the -a directive to specify the path:\n\t\t program -a info_txt_path file_paths\n\n";
	char MODEL(1)[] = "Model:\n1.FIRST:\n\n\"\n/*\n*  Author: xxxxxx\n*  Functions: xxxxxx\n*  Time: xxxxxx\n*/\n\"\n";
	
	printf("%s%s%s%s%s", INFO(0), INFO(1), INFO(2), INFO(3), MODEL(1));
}

// functions:展示程序版本信息
// input: void
// return: void
void _version_order_info(void)
{
	char INFO(0)[] = "\nThe -v order:\n";
	char INFO(1)[] = "The program version(user) : 1.0.0\n";
	char INFO(2)[] = "(more infomation is waiting to add!)\n\n";
	printf("%s%s%s", INFO(0), INFO(1), INFO(2));
}

// functions:展示程序自动信息
// input: void
// return: void
void _auto_order_info(void)
{
	char INFO(0)[] = "\nThe -a order:\n";
	char INFO(1)[] = "The method of auto order:\n\n\t Writes to the specified file by creating a custom template file as an insert.\n\n";
	char INFO(2)[] = "Method of application:\n\n\t program -a info_txt_path file_paths\n\t (info_txt_path: Custom Template;  file_paths: File To Insert)\n";
	char MODEL(1)[] = "Model:\n1.FIRST:\n\n\"\n/*\n*  Author: xxxxxx\n*  Functions: xxxxxx\n*  Time: xxxxxx\n*/\n\"\n";
	printf("%s%s%s%s", INFO(0), INFO(1), INFO(2), MODEL(1));
}

// functions:匹配指令
// input: 当前匹配成功的指令, 待匹配指令, 指令集, 指令集长度----注:指向数组的指针->即指针值为一个数组的地址==二维数组:数组的数组,所以二维数组名就是多个一维数组的首地址
// return: state / auto_flag
state _match_order(char * order_now, const char* order, const char (*order_set)[ORDER_SIZE], int set_len)
{
	// 输入的待匹配指令与指令集匹配,并将匹配到的指令存入当前指令中,并返回ok
	int order_size = strlen(order);  // 当前匹配指令长度
	memset(order_now, 0, strlen(order_now));  // 置空指令
	int flag = 0;
	int error_flag = 0;
	if(strncmp(order, "-", 1) == 0) error_flag = 1;
	for(int i = 0; i < set_len; ++i)
	{
		if(strncmp(order, order_set[i], order_size) == 0) {strncpy(order_now, order, order_size);                }  			// 匹配成功就退出
		if(strncmp(order_now, "-h", order_size) == 0)     {_help_order_info();       		  flag = 1;break;    }   			// 帮助指令info
		if(strncmp(order_now, "-v", order_size) == 0)     {_version_order_info();    		  flag = 2;break; 	 }				// 版本指令info
		if(strncmp(order_now, "-a", order_size) == 0)     {		    	     				  flag = 3;break;	 }				// 自动指令启动标志
		if(strncmp(order_now, "-ha", order_size) == 0)    {_auto_order_info();	   			  flag = 4;break;	 }				// 自动指令info
	}
	switch(flag)
	{
		case 0:
			if(error_flag == 1)  // 存在假指令使,返回3
				return 3;
			return 0;  // 不能存在时, 返回0, 表示已无指令
			break;  // return后的break可有可无,这里主要是提醒case默认格式是需要加break结尾的
		case 1: // 只要匹配到有的指令就执行相同的return ok
		case 2:
		case 4:
			return ok;
			break;
		case 3:
			return ok +1;
			break;
		default:
			break;
	}
}

info.h

代码结构:

  1. 完成info.c函数的声明
  2. 完成相关数据宏替换–连接的声明:保证命名规范
#ifndef _INFO_CONFIG_
#define _INFO_CONFIG_

#include 
#include 
#include "data.h"

#define INFO(x)  						info_##x
#define MODEL(x) 						model_##x


void _help_order_info(void);  		// 帮助信息
void _version_order_info(void);  	// 版本信息
void _auto_order_info(void); 		// 自动化信息
state _match_order(char * order_now, const char* order, const char (*order_set)[ORDER_SIZE], int set_len);  // 匹配指令


#endif

fent.c – 文件事件等

代码结构:

  1. 完成文件打开关闭函数的定义
  2. state open_file(const char* file_path, FILE** file);
  3. state close_file(FILE* file);
  4. 完成将介绍信息写入文件的函数的定义
  5. state write_file(FILE* file, char info_str[INFO_LEN][INFO_SIZE], const char* information, const int info_size);
#include "fent.h"


/**************************************************/

				/*	1.文件读写部分	*/

/**************************************************/

// functions:文件打开
// input: 文件路径,返回的文件流指针
// return: ok, 打开成功; false,失败
state open_file(const char* file_path, FILE** file)
{
	// 文件打开模式:a+  -- 追加
	*file = fopen(file_path, "r");  // 先用读判断文件是否存在
	if(*file == NULL)  // 判断是否存在该文件
	{
		printf("The %s has opened false!(if it is not exit!)\n", file_path);
		return false;
	}
	else
	{
		fclose(*file);
		*file = fopen(file_path, "a+");   // 重新打开,确定文件存在后按追加打开
	}
	return ok;
} 


// functions:文件关闭
// input: 文件流指针
// return: ok, 关闭成功
state close_file(FILE* file)
{
	fclose(file);
	file = NULL;
	return ok;
}


// functions:将模板介绍信息写入指定文件 -- 当前功能仅仅允许在末尾添加
// input: 文件流指针, 介绍内容, 模板信息, 模板字节大小
// return: ok, 关闭成功
state write_file(FILE* file, char info_str[INFO_LEN][INFO_SIZE], const char* information, const int info_size)
{
	char* str = (char *)malloc((info_size + INFO_LEN*INFO_SIZE + 1));    // 数组分布:info_size: 模板长度; 2*128 自定义介绍内容长度; 介绍末尾一个换行
	char* temp = str;
	int len_write = info_size;  // 写入的长度: info_size + info_str中有效数据
	int ret = 0;   // 实际写入
	
	while(*information)  // 遍历模板,开始添加相关自定义信息-author等
	{
		*str = *information;
		if(*information == 'A') // 遍历到Author,进入信息补充
		{
			do
			{
				str++;
				information++;
				*str = *information;
			}while(*information != ':');  // 复制Author:
			
			str++;   
			information++;
			*str = *information;   // 空格复制
			
			int author_index = 0;
			while(info_str[0][author_index] != '\0')  // 复制自定义的author信息
			{
				str++;
				*str = info_str[0][author_index];
				author_index++;
				len_write++;  // 复制一个字符,意味着添加了一个字符的写入内容
			}
		}
		else if(*information == 'F') // 同上
		{
			do
			{
				str++;
				information++;
				*str = *information;
			}while(*information != ':');
			
			str++;   
			information++;
			*str = *information;   // 空格复制
			
			int func_index = 0;
			while(info_str[1][func_index] != '\0')
			{
				str++;
				*str = info_str[1][func_index];
				func_index++;
				len_write++;
			}
		}
		else if(*information == 'T')
		{	
			char time_str[INFO_SIZE] = {0};
			get_time_str(time_str);
			
			do
			{
				str++;
				information++;
				*str = *information;
			}while(*information != ':');
			
			str++;   
			information++;
			*str = *information;   // 空格复制
			
			int time_index = 0;
			while(time_str[time_index] != '\0')
			{
				str++;
				*str = time_str[time_index];
				time_index++;
				len_write++;
			}
		}
		information++;
		str++;
	}
	
	*str = '\n';
	str++;
	len_write++;
	*str = '\0';  // 添加字符串结束符--‘\0’
	
	ret = fwrite((void *)temp, 1, len_write, file);  // 写入指定的长度
	if(!ret)  // 如果写入0个字符,说明写入失败
		printf("Write is false!\n");
}


fent.h

代码结构:

  1. 完成fent.c函数的声明
#ifndef _FENT_CONFIG_
#define _FENT_CONFIG_

#include "info.h"
#include "data.h"

state open_file(const char* file_path, FILE** file);			// 文件以a+打开
state close_file(FILE* file);								// 文件关闭
state write_file(FILE* file, char info_str[2][128], const char* information, const int info_size);  // 写入文件

#endif

程序功能介绍

程序相关指令

  • -h 展示相关帮助信息
  • -v 展示版本信息
  • -ha 展示自动化指令的使用方法
  • -a 启动自动化添加–未实现

程序的使用介绍

windows通过cmd进入编译后程序所在的行,然后在cmd下进入该目录
添加作者信息、介绍与时间于任意文件末尾 --正在更新(自定义C语言练习(一))_第2张图片
尝试启动程序,执行-h,-v指令(未定义的异常指令会报异常,并停止之后的指令读取)
在这里插入图片描述
添加作者信息、介绍与时间于任意文件末尾 --正在更新(自定义C语言练习(一))_第3张图片
尝试写入文件中
在这里插入图片描述
在这里插入图片描述
添加作者信息、介绍与时间于任意文件末尾 --正在更新(自定义C语言练习(一))_第4张图片

未来程序改善


1. 可选择完成在文件首进行添加相关信息(可采用目录操作,使创建的新文件写入完毕后,再移动到添加信息的文件所在的目录下,完成写功能——删除原文件,移入同名的新文件)。

2. 可以添加扫描功能,在文件首尾进行扫描,是否已有文件介绍信息,如果有就添加一行重写时间(reset: 2020-x-x xx:xx:xx 星期x),其它保持不变。

3. 完善auto自动往目录中所有文件添加和检查文件中的介绍信息的功能。

4. 将指令程序引导方式启动转换为,程序启动输入参数启动相关功能。
(program -h 转换为 program 回车 再输入 -h等)

5. 实现多文件添加--当前只允许txt文件~

你可能感兴趣的:(C语言练习,编程语言,c语言,指针)