题目描述
输入1进入log功能界面
log功能界面
1:文件log保存功能
2:文件log打印功能
0:返回上一级菜单
输入 1 进入 文件log保存功能
文件log保存功能描述:读取1个数字 假如是3
将"[index]get_num = 3\r\n"这句话打印到文件中 从文件后面追加
如第一次保存log 创建文件log.txt
文件里面的内容为:
1 get_num=3
第二次调用保存log功能 假如输入值为1
文件里面的内容应该为
1 get_num=3
2 get_num=1
假如第三到第十次的输入值均为2
文件里面的内容为:
1 get_num=3
2 get_num=1
3 get_num=2
4 get_num=2
5 get_num=2
6 get_num=2
7 get_num=2
8 get_num=2
9 get_num=2
10 get_num=2
要求一:文件最多保存的log数量为10条 当有第11条log的时候 应该覆盖第1条log
假如第11次输入值为4 文件里面的内容为:
11 get_num=4
2 get_num=1
3 get_num=2
4 get_num=2
5 get_num=2
6 get_num=2
7 get_num=2
8 get_num=2
9 get_num=2
10 get_num=2
要求二:再次进入文件log保存功能时 当文件存在的时候应该也往后追加
如上一次退出log保存功能时 文件内容为:
11 get_num=3
2 get_num=1
3 get_num=2
4 get_num=2
5 get_num=2
6 get_num=2
7 get_num=2
8 get_num=2
9 get_num=2
10 get_num=2
再次进入文件log保存功能 输入值为5 此时文件的内容为:
11 get_num=3
12 get_num=1
3 get_num=2
4 get_num=2
5 get_num=2
6 get_num=2
7 get_num=2
8 get_num=2
9 get_num=2
10 get_num=2
自己的思路
我使用了一个队列,里面记录了index 和 后面的num,打算是当index超过11是,用fgets和sscanf函数去获取对应文本内index确定写入行号,然后用fseek函数偏移文件指针去写入数据
相关代码
主要功能写在log_save函数
/*
* @Descripttion : log function
* @Author : Ethan.liang
* @Date : 2022-07-18 09:20:36
* @LastEditors : Do not Edit
* @LastEditTime : 2022-07-24 10:05:34
*/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef int dataType;
dataType log_ret = -1;
dataType log_num = -1;
dataType log_cnt = 1;
dataType log_index = 0;
dataType log_sel = -1;
dataType line_len = 0;
dataType len = 0;
char str_temp[512] = {0};
char linebuffer[512] = {0};
char log_buffer[512] = {0};
#define QUEUEMAX 10
typedef struct QueueNode
{
dataType _data; //用来存储数据
dataType _index;
struct QueueNode *_next; //用来指向下一个结构体
} QueueNode, *P_Node;
typedef struct Queue
{
QueueNode *_head; //存放整个队列的队头
QueueNode *_tail; //存放整个队列的队尾
} Queue, *P_Queue;
int log_window();
int log_save(P_Queue log_que);
int log_print();
//初始化
P_Queue QueueInit(P_Queue log_que);
//销毁
P_Queue QueueDestory(P_Queue log_que);
//入队
P_Queue QueuePush(P_Queue log_que, dataType log_num);
//出队
P_Queue QueuePop(P_Queue log_que);
//访问队首的元素
dataType QueueFront(Queue *log_que);
//访问对尾的元素
dataType QueueBack(Queue *log_que);
//返回1是空,返回0是非空
int QueueEmpty(Queue *log_que);
//获取数据的个数
int QueueSize(Queue *log_que);
//初始化
P_Queue QueueInit(P_Queue log_que)
{
assert(log_que); //判断指针的有效性
// log_que->_head->_index = 1;
log_que->_head = log_que->_tail = NULL; //队头和队尾指向空指针
return log_que;
}
//销毁
P_Queue QueueDestory(P_Queue log_que)
{
assert(log_que);
QueueNode *cur = log_que->_head;
while (cur)
{
QueueNode *next = cur->_next;
free(cur);
cur = next;
}
log_que->_head = log_que->_tail = NULL;
return log_que;
}
//入队
P_Queue QueuePush(P_Queue log_que, dataType log_num)
{
assert(log_que);
P_Node newnode = (P_Node)malloc(sizeof(P_Node)); //为新节点申请内存空间
if (newnode == NULL) //判断内存空间是否申请成功
{
printf("内存不足!\n");
exit(-1);
}
newnode->_data = log_num; //新节点储存数据
newnode->_next = NULL; //新节点的下一个指向NULL,即新节点作为队尾
if (log_que->_head == NULL) //将新节点入队
{
log_que->_head = log_que->_tail = newnode;
}
else
{
log_que->_tail->_next = newnode;
log_que->_tail = newnode;
}
return log_que;
}
//出队
P_Queue QueuePop(P_Queue log_que)
{
assert(log_que);
assert(log_que->_head);
if (log_que->_head == NULL)
{
// printf("%d\n",__LINE__);
free(log_que->_head);
log_que->_head = log_que->_tail = NULL;
}
else
{
QueueNode *next = log_que->_head->_next;
// printf("%d\n",__LINE__);
free(log_que->_head);
// printf("%d\n",__LINE__);
log_que->_head = next;
}
// printf("%d\n",__LINE__);
return log_que;
}
//访问队首的元素
dataType QueueFront(Queue *log_que)
{
assert(log_que);
assert(log_que->_head);
return log_que->_head->_data;
}
//访问队尾的元素
dataType QueueBack(Queue *log_que)
{
assert(log_que);
assert(log_que->_tail);
return log_que->_tail->_data;
}
//返回1是空,返回0是非空
int QueueEmpty(Queue *log_que)
{
assert(log_que);
return log_que->_head == NULL ? 1 : 0;
}
// 获取数据的个数
int QueueSize(Queue *log_que)
{
assert(log_que);
QueueNode *cur = log_que->_head;
int size = 0;
while (cur)
{
++size;
cur = cur->_next;
}
return size;
}
dataType log_save(P_Queue log_que)
{
char log_info[64];
printf("请输入要保存的数:\n");
log_ret = scanf("%d", &log_num);
if (log_ret)
{
getchar();
}
else
{
printf("请输入数字!\n");
return 0;
}
FILE *fp;
log_index++;
if (log_cnt <= QUEUEMAX)
{
fp = fopen("./log.txt", "a+");
if (NULL == fp)
{
perror("open log.txt error>>>");
exit(1);
}
QueuePush(log_que, log_num);
// printf("%d\n",__LINE__);
// getchar();
log_que->_tail->_index = log_index;
log_que->_tail->_data = log_num;
// snprintf(log_info, sizeof(log_info), "[ %d ]get_num=%d\n", log_que->_tail->_index, log_que->_tail->_data);
// fwrite(log_info, strlen(log_info), 1, fp);
// snprintf(str_temp, sizeof(str_temp), "%d get_num= %d\n", log_que->_tail->_index, log_que->_tail->_data);
// fputs(str_temp, fp);
fprintf(fp, "%d get_num= %d \n", log_que->_tail->_index, log_que->_tail->_data);
printf("QueueBack:%d, num:%d\n ", log_que->_tail->_index, QueueBack(log_que));
printf("QueueFront:%d, num:%d\n", log_que->_head->_index, QueueFront(log_que));
log_cnt++;
fclose(fp);
}
else
{
// rewind(fp);
// log_cnt = 0;
fp = fopen("./log.txt", "r+");
if (NULL == fp)
{
perror("open log.txt error>>>");
exit(1);
}
QueuePush(log_que, log_num);
// printf("%d\n",__LINE__);
// getchar();
log_que->_tail->_index = log_index;
log_que->_tail->_data = log_num;
while (fgets(linebuffer, 513, fp))
{
log_ret = ftell(fp);
printf("log_ret:%d\n", log_ret);
printf("linebuffer:%s", linebuffer);
line_len = strlen(linebuffer);
printf("line_len:%d\n", line_len);
len += line_len;
printf("len:%d\n", len);
dataType index_tmp, num_tmp;
sscanf(linebuffer, "%d%s%d", &index_tmp, str_temp, &num_tmp);
index_tmp = index_tmp % 10;
printf("index_tmp:%d\n", index_tmp);
int que_idx_tmp = (log_que->_tail->_index) % 10;
printf("que_idx_tmp:%d\n", que_idx_tmp);
printf("que_idx_tmp:%d\n", que_idx_tmp);
sleep(1);
if ( index_tmp == que_idx_tmp )
{
len -= strlen(linebuffer);
printf("len:%d\n", len);
log_ret = fseek(fp, len , SEEK_SET);
if(log_ret < 0)
{
perror("fseek");
return -1;
}
fprintf(fp, "%dget_num= %d \n", log_que->_tail->_index, log_que->_tail->_data);
// snprintf(str_temp, sizeof(str_temp), "%d get_num= %d\n", log_que->_tail->_index, log_que->_tail->_data);
// fputs(str_temp, fp);
log_ret = fseek(fp, 0, SEEK_SET);
if(log_ret < 0)
{
perror("fseek");
return -1;
}
// fprintf(fp, " ");
// flen = ftell(fp);
// printf("flen:%d\n", flen);
// fseek(fp, -(flen - line_len), SEEK_CUR);
QueuePop(log_que);
printf("QueueBack:%d, num:%d\n ", log_que->_tail->_index, QueueBack(log_que));
printf("QueueFront:%d, num:%d\n", log_que->_head->_index, QueueFront(log_que));
break;
}
}
fclose(fp);
log_cnt++;
// log_cnt = 0;
}
}
int log_window()
{
// system("clear");
printf("|***********log功能界面************|\n");
printf("| 1:文件保存log功能 |\n");
printf("| 2:文件log打印功能 |\n");
printf("| 0:返回上一级菜单 |\n");
printf("|**********************************|\n");
}
int main(int argc, char const *argv[])
{
// index = 1;
// P_Node head = new_node(0, 0);
P_Queue log_que;
QueueInit(log_que);
dataType log_sel = -1;
while (1)
{
log_window();
log_ret = scanf("%d", &log_sel);
if (-1 == log_ret)
{
printf("请重新输入!\n");
return log_ret;
}
else
{
getchar();
}
printf("puts:%d\n", log_sel);
switch (log_sel)
{
case 1:
log_save(log_que);
break;
case 2:
// log_print();
break;
default:
return 0;
}
}
free(log_que);
return 0;
}
你期待的结果是什么?实际看到的错误信息又是什么?
现在问我输入地是一个数据时,能成功写入,但文件的下一行会莫名消失几个字符
如果我在第一行输入字符比第十一行多的话情况又不同:
比如我在第一行输入111111:
十一行写入1
想知道为什么会这样,解决的方法又是怎样的
如果某位置有数据,直接在该位置写入新数据的话,会覆盖(替换)旧数据
原来的内容是这样
写入第 11 个后就变成
同理,原来的内容是这样
写入第 11 个后就变成
因此正确的做法是,先读取后面的数据,然后写入新数据,再重新写入后面的数据,注意文件总大小要调整
当然,不用
r+
模式,用w
模式也是可以的,把数据存到循环队列里(用数组即可,不必用链表),每次把队列写入一遍即可