代码拉取完成,页面将自动刷新
/*
* @Author: mikey.zhaopeng
* @Date: 2020-11-20 21:11:02
* @Last Modified by: mikey.zhaopeng
* @Last Modified time: 2020-11-20 21:11:02
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
#include <time.h>
#include <locale.h>
#include <io.h>
#include <windows.h>
#include "Calculator.h"
#define DEBUG //!开发者版本
// ?逆波兰表示法计算器
int main (int argc, char * argv[])
{
system("color 02");
system("title C语言 - 逆波兰表示法计算器");
system("VER");
if (setlocale(LC_ALL, "") != NULL) //@使用系统默认的语言
puts(" 本地化设置成功!");
else
puts("本地化设置失败! (Localization setup failed!)");
#ifdef DEBUG
puts(" 现在处于开发者模式!");
#endif
puts("使用过程中按ESC退出程序");
_beginthread(key_esc, 0, NULL);
int input = 0, accuracy = 0, x = 0;
on_or_off accuracy_switch = ON; //精确度读取开关
char *const use_log_file_name = output_log_file_name(argv, 30, "_start_log.txt");//记录启动次数的文件名指针
char *const log_file_name = output_log_file_name(argv, 30, "_log.txt");//记录log的文件名指针
double user_time = 0.0;//用户使用时间
struct strat_and_time strat_file;
struct log_data log_file;
use_log(log_file_name); //*记录用户开始使用的时间
if (input_start_log(use_log_file_name, &strat_file) == EOF)
{
puts(" 您好! 新用户");
}
else
{
printf(" Hello! 这是您第%u次使用此程序\n", strat_file.counter);
}
message(45, false);
puts("本计算器采用逆波兰表示法");
puts("格式如下: 数 数 运算符");
puts("实在不行自行百度\n*****本程序支持四则运算和求模运算*****");
puts("请输入要精确到小数点后几位(0 ~ 15)");
program_time();
input_accuracy(&accuracy, &accuracy_switch);
puts("请开始输入...");
throw_chars(); //把额外读取的空格去掉
while ((input = getop(user_input)) != EOF)
{
switch (input)
{
case NUMBER :
push(atof(user_input));
break;
case '+':
push(pop() + pop());
break;
case '-':
x = pop();
push(pop() - x);
break;
case '*':
push(pop() * pop());
break;
case '/':
x = pop();
if (0 == x) //除数是0时重新开始
{
puts("错误: 除数不能等于零");
error = math_error;
break;
}
push(pop() / x);
break;
case '%':
x = pop();
if (0 == x)
{
puts("错误: 求模数不能为0");
error = math_error;
break;
}
push((int)pop() % x);
break;
case '\n':
if (0 == index)
puts("未检测到数字,请输入...");
else if (error == math_error) //除数是0, 求模数是0的错误处理
{
error = off;
for ( ;index > 0; index--) //把存储数的数字归零, 以便重新开始输入, 防止用户按空格时输出数组中的数
continue;
break;
}
else
printf("%.*f\n", accuracy, pop());
break;
default:
printf("暂不支持\n");
break;
}
}
user_time = program_time();
output_start_log(use_log_file_name, &strat_file, user_time);
use_end_log(log_file_name, user_time); //*记录用户结束使用的时间
puts("再见!");
getchar();
return 0;
}
// 返回运算符并保存数字
int getop (char s[restrict])
{
int c = 0;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c;
counter_s i = 0;
if (isdigit(c))
while (isdigit(s[++i] = c = getch()))
;
if (c == '.')
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != ' ' && c != EOF)
buffer(c);
return NUMBER;
}
// 把用户输入的数字保存
void push (const double number)
{
if (index >= MAX_INPUT)
printf("错误: 已到达最大值\n");
else
user_number[index++] = number;
}
// 弹出在其中的数
double pop (void)
{
if (index <= 0)
printf("错误: 没有输入数或缺少数\n");
else
return user_number[--index];
}
counter_s index_buffer = 0;
int getch (void)
{
return (index_buffer > 0) ? buf[--index_buffer] : getchar();
}
// 把用来判断的字符保存
void buffer (const int c)
{
if (index_buffer >= MAX_BUFFER)
printf("错误: 缓冲器已满\n");
else
buf[index_buffer++] = c;
}
//读取精确度
void input_accuracy (int *restrict const prt, bool *restrict const input_switch)
{
while (*input_switch)
{
while (scanf("%d", prt) != 1)
{
while (getchar() != '\n') //如果不是数字时清理缓冲区以便重新读取数字
continue;
puts("错误: 请确保您输入的是数字");
}
if (*prt < 0)
puts("错误: 精确度过小, 请重新输入...");
else if (*prt > 15)
puts("错误: 精确度过大, 请重新输入...");
else
{
puts("设置成功!");
*input_switch = OFF; //关闭循环
}
}
}
/* 输出可执行文件的文件名, max是_log.txt前的最大字符数
/* argv_func是main的argv
/* string是添加的可执行文件的后缀
/* 比如 可执行文件名_log.txt "_log_txt"就是后缀
*/
char * output_log_file_name (char *restrict const argv_func[], const int max, const char *restrict const string)
{
unsigned short int string_lenght = strlen(string) + 1;
char *restrict const log_file_name = (char *) malloc(sizeof(char) * (max + string_lenght));
const char *restrict const remove_path = strrchr(argv_func[0], '\\');//找到 '/' 最后出现的地方
const char *restrict const remove_exe = strrchr(argv_func[0], '.');//找到 '.' 最后出现的地方
unsigned short int length = (remove_exe - remove_path) - 1;
if (length > max)
length = max;
log_file_name[length] = '\0';
strncpy(log_file_name, remove_path + 1, length);//去除路径和.exe, 得到可执行文件名
if (log_file_name == NULL) //*错误处理
{
fprintf(stderr, "错误: 动态内存分配失败\n");
#ifdef DEBUG
if (strcoll(argv_func[1], "-debug") == 0)
fprintf(stderr, "错误函数: %s\n",__func__);
#endif
return NULL;
}
strcat(log_file_name, string);
// !别忘了free
return log_file_name;
}
/*
/* 读取文件中的数据并保存到结构中
/* 如果数据文件不存在则返回
*/
int input_start_log (char *restrict const start_log_file_name, struct strat_and_time * statr_file_all_data)
{
FILE * read;
if (access(start_log_file_name, 0) == EOF) //如果文件不存在, 则返回EOF
return EOF;
if ((read = fopen(start_log_file_name, "r")) == NULL)
{
fprintf(stderr, "错误: 文件%s打开失败\n", start_log_file_name);
#ifdef DEBUG
fprintf(stderr, "错误函数: %s\n",__func__);
#endif
return NULL;
}
fscanf(read, "%*s%u", &statr_file_all_data->counter); //跳过开头的字并读取启动次数
fscanf(read, "%*s%lf", &statr_file_all_data->time); //跳过开头的字并读取运行时间
// !读取double时要用ld
fclose(read);
return 0;
}
//如果不存在, 新建一个log文件,如果存在, 则调用input_start_log中的结构并写入到文件中
int output_start_log (const char *restrict const start_file_name, const struct strat_and_time * statr_file_data, const double time)
{
FILE * write, * read;
unsigned int counter = 0;
double add_time = 0.0;
if (access(start_file_name, 0) == EOF) //如果不存在, 新建一个log文件
{
if ((write = fopen(start_file_name, "w")) == NULL)
{
fprintf(stderr ,"错误: 文件%s创建失败\n", start_file_name);
fprintf(stderr, "错误函数: %s\n",__func__);
return NULL;
}
fprintf(write, "启动次数: %u\n运行时间: %.2f秒", 1, time);
fclose(write);
return NEW_FILE;
}
else //如果存在, 则调用input_start_log中的结构并写入到文件中
{
if ((write = fopen(start_file_name, "w")) == NULL)
{
fprintf(stderr, "错误: 文件%s打开失败\n",start_file_name);
fprintf(stderr, "错误函数: %s\n",__func__);
return NULL;
}
fprintf(write, "启动次数: %u\n运行时间: %.2f秒",statr_file_data->counter + 1, (statr_file_data->time + time));
fclose(write);
}
return 0;
}
//*记录用户开始使用的时间
int use_log (char *restrict const log_file_name)
{
char time_date_buf[80];
FILE * read, * write, * write_start;
if (access(log_file_name, 0) == EOF) //*如果文件不存在, 则创建文件, 否则写入
{
if ((write_start = fopen(log_file_name, "w")) == NULL)
{
fprintf(stderr, "错误: 文件%s打开失败\n", log_file_name);
fprintf(stderr, "错误函数: %s\n",__func__);
return NULL;
}
time_data(time_date_buf, 80);
fprintf(write_start, "运行时间: %s ",time_date_buf);
fclose(write_start);
}
else
{
if ((write = fopen(log_file_name, "a+")) == NULL)
{
fprintf(stderr, "错误: 文件%s打开失败\n", log_file_name);
fprintf(stderr, "错误函数: %s\n",__func__);
return NULL;
}
time_data(time_date_buf, 80);
fprintf(write, "运行时间: %s ",time_date_buf);
if (fclose(write) == EOF) //@错误处理
{
fprintf(stderr, "错误: 文件%s关闭失败\n", log_file_name);
fprintf(stderr, "错误函数: %s\n",__func__);
return EOF;
}
}
return 0;
}
//*记录用户结束使用的时间
int use_end_log (char *restrict const log_file_name, const double time)
{
FILE * read_end, * write_end;
char time_date_end[80];
if ((write_end = fopen(log_file_name, "a+")) == NULL) //@错误处理
{
fprintf(stderr, "错误: 文件%s打开失败\n", log_file_name);
fprintf(stderr, "错误函数: %s\n",__func__);
return NULL;
}
time_data(time_date_end, 80);
fprintf(write_end, "关闭于%s, 共使用了%.1f秒\n", time_date_end, time);
if (fclose(write_end) == EOF) //@错误处理
{
fprintf(stderr, "错误: 文件%s关闭失败\n", log_file_name);
fprintf(stderr, "错误函数: %s\n",__func__);
return EOF;
}
}
double program_time (void)
{
static counter_r number = 0;
static clock_t a = 0, b = 0;
static double c = 0.0;//秒
number++;
if (1 == number)
{
a = clock();
}
if (2 == number)
{
b = clock();
b = b - a;
c = (double)b / CLOCKS_PER_SEC;
number = 0;
}
// *错误处理
if (EOF == a || EOF == b)
{
perror("错误: 读取时间失败\n");
fprintf(stderr, "错误函数: %s\n",__func__);
return EOF;
}
return c;
}
//往数组里放日期和时间
void time_data (char *restrict const string[], int max)
{
struct tm *prt;
time_t lt;
lt = time(NULL);
char* str = ctime(<);
prt = localtime(<);
strftime(string, max, "%Y-%m-%d %X", prt);
}
void message (const unsigned int number, const bool user_input_error)
{
struct tm *prt;
time_t lt;
char time_array[MAX_TIME];
for (counter_s a = 0; a < number; ++a)
putchar('*');
lt = time(NULL);
char* str = ctime(<);
prt = localtime(<);
strftime(time_array, MAX_TIME, "%Y-%m-%d %X", prt);
printf("\n 此程序共有%d行代码", __LINE__ + 16 + 48);
printf("\n 当前编译器标准: %ld\n 最后编译时间: %s\n", __STDC_VERSION__, time_array);
for (counter_s b = 0; b < number; b++)
putchar('*');
printf("\n");
if (user_input_error)
{
printf(" 注意!\n");
printf(" 此程序没有输入验证功能!\n");
printf(" 如果不按照提示输入,将会导致程序崩溃!!!\n");
for (counter_s b = 0; b < number; b++)
putchar('*');
}
printf("\n");
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。