如何根据每种情况保留我在文本文件中的位置?
How is it possible to keep the position from where I am in the text files based on each case?
我有 10 个文本文件,其中包含一些数据包,这些数据包由 rollnumber、源、目标和生成时间表示,它们也在一个结构中:
typedef struct Node
{
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
我想在每个时间单位打开每个文件,并能够检查是否生成了任何数据包。这意味着,生成时间必须小于我所在的时间单元。例如,在时间单元 0-1 中,我必须找到一个 0<生成时间<1 的数据包。因此,如果发生这种情况,该数据包将进入一个具有插入功能的列表:
void insert_end ( Node **head, int rollnumber, int src, int dst, double gentime){
struct Node * new_node = NULL;
struct Node * last = NULL;
new_node = (struct Node *)malloc(sizeof(struct Node));
if (new_node == NULL)
{
printf("Failed to insert element. Out of memory");
return;
}
new_node->rollnumber=rollnumber;
new_node->src = src;
new_node->dst=dst;
new_node->gentime=gentime;
new_node->next = NULL;
if( *head == NULL)
{
*head = new_node;
return;
}
last = *head;
while(last->next) last = last->next;
last->next = new_node;
}
我的代码如下:
for (Time=1.0; Time<10.0; Time=Time+1.0){ //the time units checking them per one like: 0-1,1-2 etc..
for(i=1;i<=10;i++){ //because I have 10 text files
char to_open[32];
snprintf(to_open,32, "fptg_%d.txt", i);
printf("\n\nFPTG_%d.txt\n", i);
if ((file = fopen(to_open, "r")) == NULL)
{
break;
}else{
fseek(file , pos[i], SEEK_CUR);
fgets(line, sizeof(line), file);
sscanf(line,"%d %d %d %lf",&rollnumber, &src, &dst, &gentime);
printf("%s", line);
printf("Return value=%d\n",sscanf(line, " %d %d %d %lf", &rollnumber, &src, &dst, &gentime));
printf("gentime=%.1f\n", gentime);
pos[i] = ftell(file);
if(Time<gentime && gentime<Time+1.0){
insert_end ( &link[i], rollnumber, src, dst, gentime );
printf("Time=%0.1f\n", Time);
}else{
//do something else here and in the next time unit check the same packet again
}
}
}
}
}
我的问题是,如果一个数据包没有插入到列表中,我将如何在下一个时间单元检查同一个数据包?如果一个数据包插入到列表中,读取下一个数据包对我想做的是正确的。但是如果一个数据包没有插入到列表中,我不想在下一个时间单位转到下一个。
任何帮助将不胜感激,提前致谢!
最小可重现示例:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LINE_LENGTH 105
typedef struct Node {
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
void
insert_end(Node **head, int rollnumber, int src, int dst, double gentime)
{
struct Node *new_node = NULL;
struct Node *last = NULL;
new_node = (struct Node *) malloc(sizeof(struct Node));
if (new_node == NULL) {
printf("Failed to insert element. Out of memory");
return;
}
new_node->rollnumber = rollnumber;
new_node->src = src;
new_node->dst = dst;
new_node->gentime = gentime;
new_node->next = NULL;
if (*head == NULL) {
*head = new_node;
return;
}
last = *head;
while (last->next)
last = last->next;
last->next = new_node;
}
void
output(Node *head)
{
for (Node *current = head; current != NULL; current = current->next) {
// printf("%d ", current->data);
printf("Roll Number:%2d\t", current->rollnumber);
printf("src:%2d\t", current->src);
printf("dest:%2d\t", current->dst);
printf("gentime:%0.1f\n", current->gentime);
}
}
void
display(Node **set, int i)
{
output(set[i]);
putchar('\n');
}
int
remove_node_in_list(Node **set, size_t pos)
{
int success = set[pos] != NULL;
if (success) {
Node *tmp = set[pos];
set[pos] = set[pos]->next;
free(tmp);
}
return success;
}
#define N 10
int
main(void)
{
char line[MAX_LINE_LENGTH] = { 0 };
int src, dst;
int rollnumber;
double gentime;
int stations = 0;
Node *link[N] = { 0 };
int i = 1;
static unsigned long pos[] = { 0 };
FILE *file;
char filename_format[] = "fptg_%d.txt";
char filename[sizeof(filename_format) + 4];
bool intention[10];
double Time = 12.0;
int lower = 0, upper = 9, count = 1;
srand(time(0));
int num;
int k = 1;
struct node *head = NULL;
// the time units checking them per one like: 0-1,1-2 etc..
for (Time = 1.0; Time < 50.0; Time = Time + 1.0) {
// because I have 10 text files
for (i = 1; i <= 10; i++) {
char to_open[32];
snprintf(to_open, 32, "fptg_%d.txt", i);
printf("\n\nFPTG_%d.txt\n", i);
if ((file = fopen(to_open, "r")) == NULL) {
break;
}
else {
fseek(file, pos[i], SEEK_CUR);
fgets(line, sizeof(line), file);
sscanf(line, "%d %d %d %lf", &rollnumber, &src, &dst, &gentime);
printf("%s", line);
printf("Return value=%d\n", sscanf(line, " %d %d %d %lf", &rollnumber, &src, &dst, &gentime));
printf("gentime=%.1f\n", gentime);
pos[i] = ftell(file);
if (Time < gentime && gentime < Time + 1.0) {
insert_end(&link[i], rollnumber, src, dst, gentime);
printf("Time=%0.1f\n", Time);
for (int j = 0; j < count; j++) {
int num = (rand() % (upper - lower + 1)) + lower;
printf("Random number:%d\n", num);
if (num == 1 || num == 6 || num == 8) {
intention[i] = true;
printf("ok\n");
stations++;
printf("stations=%d\n", stations);
printf("intention[%d]=%d\n", i, intention[i]);
double offtime = gentime + 12.0;
printf("channel off until: %.1f starting from: %.1f\n\n", offtime, gentime);
}
else {
intention[i] = false;
printf("intention[%d]=%d\n", i, intention[i]);
}
}
}
else {
printf("Not in the list\n");
}
}
}
}
if (stations == 1) {
for (int i = 1; i <= 10; i++) {
printf("intention[%d]=%d\n", i, intention[i]);
if (intention[i] == true) {
printf("link[%d]:\n", i);
display(link, i);
printf("i=%d\n", i);
remove_node_in_list(link, i);
printf("NEW:\n");
display(link, i);
}
}
}
stations = 0;
return 0;
}
我第一次&第二次得到的结果是:
FPTG_1.txt
1 1 3 1.6
Return value=4
gentime=1.6
ok
Time=1.0
Random number:2
intention[1]=0
FPTG_2.txt
1 2 4 1.9
Return value=4
gentime=1.9
ok
Time=1.0
Random number:8
ok
stations=1
intention[2]=1
channel off until: 13.9 starting from: 1.9
FPTG_3.txt
1 3 7 1.2
Return value=4
gentime=1.2
ok
Time=1.0
Random number:7
intention[3]=0
FPTG_4.txt
1 4 18 0.2
Return value=4
gentime=0.2
Random number:9
intention[4]=0
FPTG_5.txt
1 5 19 0.2
Return value=4
gentime=0.2
Random number:0
intention[5]=0
FPTG_6.txt
1 6 3 0.1
Return value=4
gentime=0.1
Random number:0
intention[6]=0
FPTG_7.txt
1 7 6 0.0
Return value=4
gentime=0.0
Random number:0
intention[7]=0
FPTG_8.txt
1 8 17 0.5
Return value=4
gentime=0.5
Random number:4
intention[8]=0
FPTG_9.txt
1 9 6 0.1
Return value=4
gentime=0.1
Random number:1
ok
stations=2
intention[9]=1
channel off until: 12.1 starting from: 0.1
FPTG_10.txt
1 10 7 0.1
Return value=4
gentime=0.1
Random number:4
intention[10]=0
FPTG_1.txt
2 1 15 13.9
Return value=4
gentime=13.9
Random number:1
ok
stations=1
intention[1]=1
channel off until: 25.9 starting from: 13.9
FPTG_2.txt
2 2 19 14.0
Return value=4
gentime=14.0
Random number:6
ok
stations=2
intention[2]=1
channel off until: 26.0 starting from: 14.0
FPTG_3.txt
2 3 18 13.4
Return value=4
gentime=13.4
Random number:8
ok
stations=3
intention[3]=1
channel off until: 25.4 starting from: 13.4
FPTG_4.txt
2 4 12 12.8
Return value=4
gentime=12.8
Random number:8
ok
stations=4
intention[4]=1
channel off until: 24.8 starting from: 12.8
FPTG_5.txt
2 5 4 12.3
Return value=4
gentime=12.3
Random number:0
intention[5]=0
FPTG_6.txt
2 6 11 13.1
Return value=4
gentime=13.1
Random number:1
ok
stations=5
intention[6]=1
channel off until: 25.1 starting from: 13.1
FPTG_7.txt
2 7 13 12.8
Return value=4
gentime=12.8
Random number:2
intention[7]=0
FPTG_8.txt
2 8 14 13.5
Return value=4
gentime=13.5
Random number:4
intention[8]=0
FPTG_9.txt
2 9 11 14.0
Return value=4
gentime=14.0
Random number:0
intention[9]=0
FPTG_10.txt
2 10 9 12.1
Return value=4
gentime=12.1
Random number:7
intention[10]=0
下一个时间单位也是如此。例如对于 fptg_4.txt,在第一个时间单位它检查它的第一行:1 4 18 0.2 但在下一个时间单位它转到下一行:2 4 12 12.8,即使它应该有检查同一行,因为前一行表示的数据包没有进入列表。所以,我的问题是这怎么可能?
来自我的热门评论...
你的 MRE 无法编译,因为有一个额外的 } [已通过我的编辑修复]。
static unsigned long pos[] = { 0 };
是错误的(它具有 UB--undefined 行为,因为它太短了)。应该是:static unsigned long pos[11] = { 0 };
您从 1 开始对数组进行索引。这意味着第一个数组元素永远不会被使用,并且所有数组都必须更大(例如 int array[11];
而不是 int array[10];
你可能会更好:for (i = 0; i < 10; i++)
然后:snprintf(to_open, 32, "fptg_%d.txt", i + 1);
使用fseek/ftell是有问题的,因为输入文件是可变长度的文本。你想做什么?我唯一能想到的是你想让你的列表按时间排序?
您总是将 pos[i]
设置为 ftell
值,即使未存储记录也是如此。将 pos[i] = ftell(file);
行移动到 under/after 行 if (Time < gentime && gentime < Time + 1.0) {
行。 (即在 insert_end
调用之上)
完成最后一次更改后,位置问题已解决。我得到 3479 行,而不是 192 行输出。
但是,老实说,虽然我不确定您试图通过 intention/stations
代码获得什么效果,但多次重读文件并不是最好的方法。
我会读取每个文件一次,如果(例如)(gentime >= 1.0) && (gentime <= 50.0)
,则将其添加到列表中,然后在读取所有文件后,根据存储的 gentime 对链表进行排序。
似乎意图代码可以完成 outside/after 读取循环,因为它们不依赖于彼此的数据。
其他错误:
- 你从不做
fclose
所以你有大量悬空的文件流指针。
- 您从未检查
fgets
的 return 值,因此您没有正确处理 EOF。
- 您调用
sscanf
两次 。一次解码行,另一次只是打印 sscanf
的 return 值
- 不要转换
malloc
的 return 值。参见:Do I cast the result of malloc?
这里是 modified/corrected 代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LINE_LENGTH 105
typedef struct Node {
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
void
insert_end(Node **head, int rollnumber, int src, int dst, double gentime)
{
struct Node *new_node = NULL;
struct Node *last = NULL;
new_node = (struct Node *) malloc(sizeof(struct Node));
if (new_node == NULL) {
printf("Failed to insert element. Out of memory");
return;
}
new_node->rollnumber = rollnumber;
new_node->src = src;
new_node->dst = dst;
new_node->gentime = gentime;
new_node->next = NULL;
if (*head == NULL) {
*head = new_node;
return;
}
last = *head;
while (last->next)
last = last->next;
last->next = new_node;
}
void
output(Node *head)
{
for (Node *current = head; current != NULL; current = current->next) {
// printf("%d ", current->data);
printf("Roll Number:%2d\t", current->rollnumber);
printf("src:%2d\t", current->src);
printf("dest:%2d\t", current->dst);
printf("gentime:%0.1f\n", current->gentime);
}
}
void
display(Node **set, int i)
{
output(set[i]);
putchar('\n');
}
int
remove_node_in_list(Node **set, size_t pos)
{
int success = set[pos] != NULL;
if (success) {
Node *tmp = set[pos];
set[pos] = set[pos]->next;
free(tmp);
}
return success;
}
#define N 10
int
main(void)
{
char line[MAX_LINE_LENGTH] = { 0 };
int src, dst;
int rollnumber;
double gentime;
int stations = 0;
Node *link[N] = { 0 };
int i = 1;
static unsigned long pos[N] = { 0 };
FILE *file;
bool intention[N];
double Time = 12.0;
int lower = 0,
upper = 9,
count = 1;
srand(time(0));
// the time units checking them per one like: 0-1,1-2 etc..
for (Time = 1.0; Time < 50.0; Time = Time + 1.0) {
// because I have N text files
for (i = 0; i < N; i++) {
char to_open[32];
snprintf(to_open, 32, "fptg_%d.txt", i + 1);
printf("\n\nFILE/%d: %s Position:%ld (Time: %g)\n",
i,to_open,pos[i],Time);
if ((file = fopen(to_open, "r")) == NULL) {
perror(to_open);
break;
}
fseek(file, pos[i], SEEK_CUR);
#if 0
fgets(line, sizeof(line), file);
#else
char *cp = fgets(line, sizeof(line), file);
fclose(file);
if (cp == NULL)
continue;
#endif
int retval = sscanf(line, "%d %d %d %lf",
&rollnumber, &src, &dst, &gentime);
printf("%s", line);
printf("Return value=%d\n", retval);
printf("gentime=%.1f\n", gentime);
#if 0
pos[i] = ftell(file);
#endif
if (Time < gentime && gentime < Time + 1.0) {
#if 1
pos[i] = ftell(file);
#endif
insert_end(&link[i], rollnumber, src, dst, gentime);
printf("Time=%0.1f\n", Time);
for (int j = 0; j < count; j++) {
int num = (rand() % (upper - lower + 1)) + lower;
printf("Random number:%d\n", num);
if (num == 1 || num == 6 || num == 8) {
intention[i] = true;
printf("ok\n");
stations++;
printf("stations=%d\n", stations);
printf("intention[%d]=%d\n", i, intention[i]);
double offtime = gentime + 12.0;
printf("channel off until: %.1f starting from: %.1f\n\n", offtime, gentime);
}
else {
intention[i] = false;
printf("intention[%d]=%d\n", i, intention[i]);
}
}
}
else {
printf("Not in the list\n");
}
}
}
if (stations == 1) {
for (int i = 0; i < N; i++) {
printf("intention[%d]=%d\n", i, intention[i]);
if (intention[i] == true) {
printf("link[%d]:\n", i);
display(link, i);
printf("i=%d\n", i);
remove_node_in_list(link, i);
printf("NEW:\n");
display(link, i);
}
}
}
stations = 0;
return 0;
}
I saw and did all the changes and thank you a lot! Do you think I should use rewind at any position in my code? Would that be helpful? –
wajaap
没有。 rewind
[有效]只是 fseek
的包装
正如我上面提到的,我一次读入了所有文件的所有行。然后,对列表进行排序。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LINE_LENGTH 105
typedef struct Node {
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
void
insert_end(Node **head, int rollnumber, int src, int dst, double gentime)
{
struct Node *new_node;
struct Node *last = NULL;
new_node = malloc(sizeof(*new_node));
if (new_node == NULL) {
printf("Failed to insert element. Out of memory");
return;
}
new_node->rollnumber = rollnumber;
new_node->src = src;
new_node->dst = dst;
new_node->gentime = gentime;
new_node->next = NULL;
if (*head == NULL) {
*head = new_node;
return;
}
last = *head;
while (last->next)
last = last->next;
last->next = new_node;
}
void
output(Node *head)
{
for (Node *current = head; current != NULL; current = current->next) {
// printf("%d ", current->data);
printf("Roll Number:%2d\t", current->rollnumber);
printf("src:%2d\t", current->src);
printf("dest:%2d\t", current->dst);
printf("gentime:%0.1f\n", current->gentime);
}
}
void
display(Node **set, int i)
{
output(set[i]);
putchar('\n');
}
int
remove_node_in_list(Node **set, size_t pos)
{
int success = set[pos] != NULL;
if (success) {
Node *tmp = set[pos];
set[pos] = set[pos]->next;
free(tmp);
}
return success;
}
typedef struct {
Node *ptr;
} sort_t;
int
sort_cmp(const void *vlhs,const void *vrhs)
{
const sort_t *plhs = vlhs;
const Node *lhs = plhs->ptr;
const sort_t *prhs = vrhs;
const Node *rhs = prhs->ptr;
int cmp;
do {
cmp = -1;
if (lhs->gentime < rhs->gentime)
break;
cmp = 1;
if (lhs->gentime > rhs->gentime)
break;
cmp = 0;
} while (0);
return cmp;
}
void
sort_list(Node **head)
{
size_t count;
size_t idx;
Node *cur;
Node *prev;
// get count of list
count = 0;
for (cur = *head; cur != NULL; cur = cur->next)
++count;
// get flat array of node pointers
sort_t *base = malloc(sizeof(*base) * count);
sort_t *arr;
// fill the array
arr = base;
for (cur = *head; cur != NULL; cur = cur->next, ++arr)
arr->ptr = cur;
qsort(base,count,sizeof(*base),sort_cmp);
// repopulate linked list from array
prev = NULL;
arr = base;
for (idx = 0; idx < count; ++idx, ++arr) {
cur = arr->ptr;
cur->next = NULL;
if (prev != NULL)
prev->next = cur;
else
*head = cur;
prev = cur;
}
free(base);
}
#define N 10
#define TMIN 1.0
#define TMAX 50.0
int
main(void)
{
char line[MAX_LINE_LENGTH] = { 0 };
int src, dst;
int rollnumber;
double gentime;
int stations = 0;
Node *link[N] = { 0 };
int i = 1;
FILE *file;
char *cp;
bool intention[N] = { 0 };
double Time = 12.0;
int lower = 0,
upper = 9,
count = 1;
srand(time(0));
// because I have N text files
for (i = 0; i < N; i++) {
char to_open[32];
snprintf(to_open, 32, "fptg_%d.txt", i + 1);
printf("\nFILE/%d: %s\n",i,to_open);
if ((file = fopen(to_open, "r")) == NULL) {
perror(to_open);
break;
}
while (1) {
cp = fgets(line, sizeof(line), file);
if (cp == NULL)
break;
int retval = sscanf(line, "%d %d %d %lf",
&rollnumber, &src, &dst, &gentime);
printf("%s", line);
printf("Return value=%d\n", retval);
printf("gentime=%.1f\n", gentime);
if ((gentime >= TMIN) && (gentime < TMAX))
insert_end(&link[i], rollnumber, src, dst, gentime);
else
printf("Not in the list\n");
}
fclose(file);
}
// sort all lists
for (i = 0; i < N; i++)
sort_list(&link[i]);
// the time units checking them per one like: 0-1,1-2 etc..
for (Time = TMIN; Time < TMAX; Time = Time + 1.0) {
for (int j = 0; j < count; j++) {
int num = (rand() % (upper - lower + 1)) + lower;
printf("Random number:%d\n", num);
if (num == 1 || num == 6 || num == 8) {
intention[i] = true;
printf("ok\n");
stations++;
printf("stations=%d\n", stations);
printf("intention[%d]=%d\n", i, intention[i]);
double offtime = gentime + 12.0;
printf("channel off until: %.1f starting from: %.1f\n\n",
offtime, gentime);
}
else {
intention[i] = false;
printf("intention[%d]=%d\n", i, intention[i]);
}
}
}
if (stations == 1) {
for (int i = 0; i < N; i++) {
printf("intention[%d]=%d\n", i, intention[i]);
if (intention[i] == true) {
printf("link[%d]:\n", i);
display(link, i);
printf("i=%d\n", i);
remove_node_in_list(link, i);
printf("NEW:\n");
display(link, i);
}
}
}
stations = 0;
return 0;
}
更新:
Very insightfull and helpful, thank you! Why did you put #if 0, #if 1 etc? –
wajaap
我这样做是为了 tutorial/documentation 目的。我使用 cpp
条件来表示旧代码与新代码(例如):
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
这比使用 /*
和 */
注释掉旧代码更不容易出错
在这里,IMO,它让 OP 更容易看到在 line-by-line 基础上发生了什么变化。
我也在生产代码中这样做,如果我有“工作”代码,但想尝试一些新的[大概faster/better]代码,但是新的代码是实验性的,可能无法正常工作。
如果新代码不工作[但应该工作],它提供了一种恢复工作代码的简单方法。我可以处理其他事情,当我想办法让它工作时,再回到更好的代码。
我通常将代码 [(e.g.) 提交到 git
] 并保留条件。然后,我手动编辑 out 已删除的代码并提交再次。这个文件 what/why/how 我到达了最终状态。
请注意,在我的第二个代码示例中 [使用节点排序],我删除了 cpp
条件以显示 clean/final 代码。
我有 10 个文本文件,其中包含一些数据包,这些数据包由 rollnumber、源、目标和生成时间表示,它们也在一个结构中:
typedef struct Node
{
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
我想在每个时间单位打开每个文件,并能够检查是否生成了任何数据包。这意味着,生成时间必须小于我所在的时间单元。例如,在时间单元 0-1 中,我必须找到一个 0<生成时间<1 的数据包。因此,如果发生这种情况,该数据包将进入一个具有插入功能的列表:
void insert_end ( Node **head, int rollnumber, int src, int dst, double gentime){
struct Node * new_node = NULL;
struct Node * last = NULL;
new_node = (struct Node *)malloc(sizeof(struct Node));
if (new_node == NULL)
{
printf("Failed to insert element. Out of memory");
return;
}
new_node->rollnumber=rollnumber;
new_node->src = src;
new_node->dst=dst;
new_node->gentime=gentime;
new_node->next = NULL;
if( *head == NULL)
{
*head = new_node;
return;
}
last = *head;
while(last->next) last = last->next;
last->next = new_node;
}
我的代码如下:
for (Time=1.0; Time<10.0; Time=Time+1.0){ //the time units checking them per one like: 0-1,1-2 etc..
for(i=1;i<=10;i++){ //because I have 10 text files
char to_open[32];
snprintf(to_open,32, "fptg_%d.txt", i);
printf("\n\nFPTG_%d.txt\n", i);
if ((file = fopen(to_open, "r")) == NULL)
{
break;
}else{
fseek(file , pos[i], SEEK_CUR);
fgets(line, sizeof(line), file);
sscanf(line,"%d %d %d %lf",&rollnumber, &src, &dst, &gentime);
printf("%s", line);
printf("Return value=%d\n",sscanf(line, " %d %d %d %lf", &rollnumber, &src, &dst, &gentime));
printf("gentime=%.1f\n", gentime);
pos[i] = ftell(file);
if(Time<gentime && gentime<Time+1.0){
insert_end ( &link[i], rollnumber, src, dst, gentime );
printf("Time=%0.1f\n", Time);
}else{
//do something else here and in the next time unit check the same packet again
}
}
}
}
}
我的问题是,如果一个数据包没有插入到列表中,我将如何在下一个时间单元检查同一个数据包?如果一个数据包插入到列表中,读取下一个数据包对我想做的是正确的。但是如果一个数据包没有插入到列表中,我不想在下一个时间单位转到下一个。 任何帮助将不胜感激,提前致谢!
最小可重现示例:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LINE_LENGTH 105
typedef struct Node {
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
void
insert_end(Node **head, int rollnumber, int src, int dst, double gentime)
{
struct Node *new_node = NULL;
struct Node *last = NULL;
new_node = (struct Node *) malloc(sizeof(struct Node));
if (new_node == NULL) {
printf("Failed to insert element. Out of memory");
return;
}
new_node->rollnumber = rollnumber;
new_node->src = src;
new_node->dst = dst;
new_node->gentime = gentime;
new_node->next = NULL;
if (*head == NULL) {
*head = new_node;
return;
}
last = *head;
while (last->next)
last = last->next;
last->next = new_node;
}
void
output(Node *head)
{
for (Node *current = head; current != NULL; current = current->next) {
// printf("%d ", current->data);
printf("Roll Number:%2d\t", current->rollnumber);
printf("src:%2d\t", current->src);
printf("dest:%2d\t", current->dst);
printf("gentime:%0.1f\n", current->gentime);
}
}
void
display(Node **set, int i)
{
output(set[i]);
putchar('\n');
}
int
remove_node_in_list(Node **set, size_t pos)
{
int success = set[pos] != NULL;
if (success) {
Node *tmp = set[pos];
set[pos] = set[pos]->next;
free(tmp);
}
return success;
}
#define N 10
int
main(void)
{
char line[MAX_LINE_LENGTH] = { 0 };
int src, dst;
int rollnumber;
double gentime;
int stations = 0;
Node *link[N] = { 0 };
int i = 1;
static unsigned long pos[] = { 0 };
FILE *file;
char filename_format[] = "fptg_%d.txt";
char filename[sizeof(filename_format) + 4];
bool intention[10];
double Time = 12.0;
int lower = 0, upper = 9, count = 1;
srand(time(0));
int num;
int k = 1;
struct node *head = NULL;
// the time units checking them per one like: 0-1,1-2 etc..
for (Time = 1.0; Time < 50.0; Time = Time + 1.0) {
// because I have 10 text files
for (i = 1; i <= 10; i++) {
char to_open[32];
snprintf(to_open, 32, "fptg_%d.txt", i);
printf("\n\nFPTG_%d.txt\n", i);
if ((file = fopen(to_open, "r")) == NULL) {
break;
}
else {
fseek(file, pos[i], SEEK_CUR);
fgets(line, sizeof(line), file);
sscanf(line, "%d %d %d %lf", &rollnumber, &src, &dst, &gentime);
printf("%s", line);
printf("Return value=%d\n", sscanf(line, " %d %d %d %lf", &rollnumber, &src, &dst, &gentime));
printf("gentime=%.1f\n", gentime);
pos[i] = ftell(file);
if (Time < gentime && gentime < Time + 1.0) {
insert_end(&link[i], rollnumber, src, dst, gentime);
printf("Time=%0.1f\n", Time);
for (int j = 0; j < count; j++) {
int num = (rand() % (upper - lower + 1)) + lower;
printf("Random number:%d\n", num);
if (num == 1 || num == 6 || num == 8) {
intention[i] = true;
printf("ok\n");
stations++;
printf("stations=%d\n", stations);
printf("intention[%d]=%d\n", i, intention[i]);
double offtime = gentime + 12.0;
printf("channel off until: %.1f starting from: %.1f\n\n", offtime, gentime);
}
else {
intention[i] = false;
printf("intention[%d]=%d\n", i, intention[i]);
}
}
}
else {
printf("Not in the list\n");
}
}
}
}
if (stations == 1) {
for (int i = 1; i <= 10; i++) {
printf("intention[%d]=%d\n", i, intention[i]);
if (intention[i] == true) {
printf("link[%d]:\n", i);
display(link, i);
printf("i=%d\n", i);
remove_node_in_list(link, i);
printf("NEW:\n");
display(link, i);
}
}
}
stations = 0;
return 0;
}
我第一次&第二次得到的结果是:
FPTG_1.txt
1 1 3 1.6
Return value=4
gentime=1.6
ok
Time=1.0
Random number:2
intention[1]=0
FPTG_2.txt
1 2 4 1.9
Return value=4
gentime=1.9
ok
Time=1.0
Random number:8
ok
stations=1
intention[2]=1
channel off until: 13.9 starting from: 1.9
FPTG_3.txt
1 3 7 1.2
Return value=4
gentime=1.2
ok
Time=1.0
Random number:7
intention[3]=0
FPTG_4.txt
1 4 18 0.2
Return value=4
gentime=0.2
Random number:9
intention[4]=0
FPTG_5.txt
1 5 19 0.2
Return value=4
gentime=0.2
Random number:0
intention[5]=0
FPTG_6.txt
1 6 3 0.1
Return value=4
gentime=0.1
Random number:0
intention[6]=0
FPTG_7.txt
1 7 6 0.0
Return value=4
gentime=0.0
Random number:0
intention[7]=0
FPTG_8.txt
1 8 17 0.5
Return value=4
gentime=0.5
Random number:4
intention[8]=0
FPTG_9.txt
1 9 6 0.1
Return value=4
gentime=0.1
Random number:1
ok
stations=2
intention[9]=1
channel off until: 12.1 starting from: 0.1
FPTG_10.txt
1 10 7 0.1
Return value=4
gentime=0.1
Random number:4
intention[10]=0
FPTG_1.txt
2 1 15 13.9
Return value=4
gentime=13.9
Random number:1
ok
stations=1
intention[1]=1
channel off until: 25.9 starting from: 13.9
FPTG_2.txt
2 2 19 14.0
Return value=4
gentime=14.0
Random number:6
ok
stations=2
intention[2]=1
channel off until: 26.0 starting from: 14.0
FPTG_3.txt
2 3 18 13.4
Return value=4
gentime=13.4
Random number:8
ok
stations=3
intention[3]=1
channel off until: 25.4 starting from: 13.4
FPTG_4.txt
2 4 12 12.8
Return value=4
gentime=12.8
Random number:8
ok
stations=4
intention[4]=1
channel off until: 24.8 starting from: 12.8
FPTG_5.txt
2 5 4 12.3
Return value=4
gentime=12.3
Random number:0
intention[5]=0
FPTG_6.txt
2 6 11 13.1
Return value=4
gentime=13.1
Random number:1
ok
stations=5
intention[6]=1
channel off until: 25.1 starting from: 13.1
FPTG_7.txt
2 7 13 12.8
Return value=4
gentime=12.8
Random number:2
intention[7]=0
FPTG_8.txt
2 8 14 13.5
Return value=4
gentime=13.5
Random number:4
intention[8]=0
FPTG_9.txt
2 9 11 14.0
Return value=4
gentime=14.0
Random number:0
intention[9]=0
FPTG_10.txt
2 10 9 12.1
Return value=4
gentime=12.1
Random number:7
intention[10]=0
下一个时间单位也是如此。例如对于 fptg_4.txt,在第一个时间单位它检查它的第一行:1 4 18 0.2 但在下一个时间单位它转到下一行:2 4 12 12.8,即使它应该有检查同一行,因为前一行表示的数据包没有进入列表。所以,我的问题是这怎么可能?
来自我的热门评论...
你的 MRE 无法编译,因为有一个额外的 } [已通过我的编辑修复]。
static unsigned long pos[] = { 0 };
是错误的(它具有 UB--undefined 行为,因为它太短了)。应该是:static unsigned long pos[11] = { 0 };
您从 1 开始对数组进行索引。这意味着第一个数组元素永远不会被使用,并且所有数组都必须更大(例如
int array[11];
而不是int array[10];
你可能会更好:for (i = 0; i < 10; i++)
然后:snprintf(to_open, 32, "fptg_%d.txt", i + 1);
使用fseek/ftell是有问题的,因为输入文件是可变长度的文本。你想做什么?我唯一能想到的是你想让你的列表按时间排序?
您总是将
pos[i]
设置为ftell
值,即使未存储记录也是如此。将pos[i] = ftell(file);
行移动到 under/after 行if (Time < gentime && gentime < Time + 1.0) {
行。 (即在insert_end
调用之上)完成最后一次更改后,位置问题已解决。我得到 3479 行,而不是 192 行输出。
但是,老实说,虽然我不确定您试图通过
intention/stations
代码获得什么效果,但多次重读文件并不是最好的方法。我会读取每个文件一次,如果(例如)
(gentime >= 1.0) && (gentime <= 50.0)
,则将其添加到列表中,然后在读取所有文件后,根据存储的 gentime 对链表进行排序。似乎意图代码可以完成 outside/after 读取循环,因为它们不依赖于彼此的数据。
其他错误:
- 你从不做
fclose
所以你有大量悬空的文件流指针。 - 您从未检查
fgets
的 return 值,因此您没有正确处理 EOF。 - 您调用
sscanf
两次 。一次解码行,另一次只是打印sscanf
的 return 值
- 不要转换
malloc
的 return 值。参见:Do I cast the result of malloc?
这里是 modified/corrected 代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LINE_LENGTH 105
typedef struct Node {
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
void
insert_end(Node **head, int rollnumber, int src, int dst, double gentime)
{
struct Node *new_node = NULL;
struct Node *last = NULL;
new_node = (struct Node *) malloc(sizeof(struct Node));
if (new_node == NULL) {
printf("Failed to insert element. Out of memory");
return;
}
new_node->rollnumber = rollnumber;
new_node->src = src;
new_node->dst = dst;
new_node->gentime = gentime;
new_node->next = NULL;
if (*head == NULL) {
*head = new_node;
return;
}
last = *head;
while (last->next)
last = last->next;
last->next = new_node;
}
void
output(Node *head)
{
for (Node *current = head; current != NULL; current = current->next) {
// printf("%d ", current->data);
printf("Roll Number:%2d\t", current->rollnumber);
printf("src:%2d\t", current->src);
printf("dest:%2d\t", current->dst);
printf("gentime:%0.1f\n", current->gentime);
}
}
void
display(Node **set, int i)
{
output(set[i]);
putchar('\n');
}
int
remove_node_in_list(Node **set, size_t pos)
{
int success = set[pos] != NULL;
if (success) {
Node *tmp = set[pos];
set[pos] = set[pos]->next;
free(tmp);
}
return success;
}
#define N 10
int
main(void)
{
char line[MAX_LINE_LENGTH] = { 0 };
int src, dst;
int rollnumber;
double gentime;
int stations = 0;
Node *link[N] = { 0 };
int i = 1;
static unsigned long pos[N] = { 0 };
FILE *file;
bool intention[N];
double Time = 12.0;
int lower = 0,
upper = 9,
count = 1;
srand(time(0));
// the time units checking them per one like: 0-1,1-2 etc..
for (Time = 1.0; Time < 50.0; Time = Time + 1.0) {
// because I have N text files
for (i = 0; i < N; i++) {
char to_open[32];
snprintf(to_open, 32, "fptg_%d.txt", i + 1);
printf("\n\nFILE/%d: %s Position:%ld (Time: %g)\n",
i,to_open,pos[i],Time);
if ((file = fopen(to_open, "r")) == NULL) {
perror(to_open);
break;
}
fseek(file, pos[i], SEEK_CUR);
#if 0
fgets(line, sizeof(line), file);
#else
char *cp = fgets(line, sizeof(line), file);
fclose(file);
if (cp == NULL)
continue;
#endif
int retval = sscanf(line, "%d %d %d %lf",
&rollnumber, &src, &dst, &gentime);
printf("%s", line);
printf("Return value=%d\n", retval);
printf("gentime=%.1f\n", gentime);
#if 0
pos[i] = ftell(file);
#endif
if (Time < gentime && gentime < Time + 1.0) {
#if 1
pos[i] = ftell(file);
#endif
insert_end(&link[i], rollnumber, src, dst, gentime);
printf("Time=%0.1f\n", Time);
for (int j = 0; j < count; j++) {
int num = (rand() % (upper - lower + 1)) + lower;
printf("Random number:%d\n", num);
if (num == 1 || num == 6 || num == 8) {
intention[i] = true;
printf("ok\n");
stations++;
printf("stations=%d\n", stations);
printf("intention[%d]=%d\n", i, intention[i]);
double offtime = gentime + 12.0;
printf("channel off until: %.1f starting from: %.1f\n\n", offtime, gentime);
}
else {
intention[i] = false;
printf("intention[%d]=%d\n", i, intention[i]);
}
}
}
else {
printf("Not in the list\n");
}
}
}
if (stations == 1) {
for (int i = 0; i < N; i++) {
printf("intention[%d]=%d\n", i, intention[i]);
if (intention[i] == true) {
printf("link[%d]:\n", i);
display(link, i);
printf("i=%d\n", i);
remove_node_in_list(link, i);
printf("NEW:\n");
display(link, i);
}
}
}
stations = 0;
return 0;
}
I saw and did all the changes and thank you a lot! Do you think I should use rewind at any position in my code? Would that be helpful? – wajaap
没有。 rewind
[有效]只是 fseek
正如我上面提到的,我一次读入了所有文件的所有行。然后,对列表进行排序。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LINE_LENGTH 105
typedef struct Node {
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
void
insert_end(Node **head, int rollnumber, int src, int dst, double gentime)
{
struct Node *new_node;
struct Node *last = NULL;
new_node = malloc(sizeof(*new_node));
if (new_node == NULL) {
printf("Failed to insert element. Out of memory");
return;
}
new_node->rollnumber = rollnumber;
new_node->src = src;
new_node->dst = dst;
new_node->gentime = gentime;
new_node->next = NULL;
if (*head == NULL) {
*head = new_node;
return;
}
last = *head;
while (last->next)
last = last->next;
last->next = new_node;
}
void
output(Node *head)
{
for (Node *current = head; current != NULL; current = current->next) {
// printf("%d ", current->data);
printf("Roll Number:%2d\t", current->rollnumber);
printf("src:%2d\t", current->src);
printf("dest:%2d\t", current->dst);
printf("gentime:%0.1f\n", current->gentime);
}
}
void
display(Node **set, int i)
{
output(set[i]);
putchar('\n');
}
int
remove_node_in_list(Node **set, size_t pos)
{
int success = set[pos] != NULL;
if (success) {
Node *tmp = set[pos];
set[pos] = set[pos]->next;
free(tmp);
}
return success;
}
typedef struct {
Node *ptr;
} sort_t;
int
sort_cmp(const void *vlhs,const void *vrhs)
{
const sort_t *plhs = vlhs;
const Node *lhs = plhs->ptr;
const sort_t *prhs = vrhs;
const Node *rhs = prhs->ptr;
int cmp;
do {
cmp = -1;
if (lhs->gentime < rhs->gentime)
break;
cmp = 1;
if (lhs->gentime > rhs->gentime)
break;
cmp = 0;
} while (0);
return cmp;
}
void
sort_list(Node **head)
{
size_t count;
size_t idx;
Node *cur;
Node *prev;
// get count of list
count = 0;
for (cur = *head; cur != NULL; cur = cur->next)
++count;
// get flat array of node pointers
sort_t *base = malloc(sizeof(*base) * count);
sort_t *arr;
// fill the array
arr = base;
for (cur = *head; cur != NULL; cur = cur->next, ++arr)
arr->ptr = cur;
qsort(base,count,sizeof(*base),sort_cmp);
// repopulate linked list from array
prev = NULL;
arr = base;
for (idx = 0; idx < count; ++idx, ++arr) {
cur = arr->ptr;
cur->next = NULL;
if (prev != NULL)
prev->next = cur;
else
*head = cur;
prev = cur;
}
free(base);
}
#define N 10
#define TMIN 1.0
#define TMAX 50.0
int
main(void)
{
char line[MAX_LINE_LENGTH] = { 0 };
int src, dst;
int rollnumber;
double gentime;
int stations = 0;
Node *link[N] = { 0 };
int i = 1;
FILE *file;
char *cp;
bool intention[N] = { 0 };
double Time = 12.0;
int lower = 0,
upper = 9,
count = 1;
srand(time(0));
// because I have N text files
for (i = 0; i < N; i++) {
char to_open[32];
snprintf(to_open, 32, "fptg_%d.txt", i + 1);
printf("\nFILE/%d: %s\n",i,to_open);
if ((file = fopen(to_open, "r")) == NULL) {
perror(to_open);
break;
}
while (1) {
cp = fgets(line, sizeof(line), file);
if (cp == NULL)
break;
int retval = sscanf(line, "%d %d %d %lf",
&rollnumber, &src, &dst, &gentime);
printf("%s", line);
printf("Return value=%d\n", retval);
printf("gentime=%.1f\n", gentime);
if ((gentime >= TMIN) && (gentime < TMAX))
insert_end(&link[i], rollnumber, src, dst, gentime);
else
printf("Not in the list\n");
}
fclose(file);
}
// sort all lists
for (i = 0; i < N; i++)
sort_list(&link[i]);
// the time units checking them per one like: 0-1,1-2 etc..
for (Time = TMIN; Time < TMAX; Time = Time + 1.0) {
for (int j = 0; j < count; j++) {
int num = (rand() % (upper - lower + 1)) + lower;
printf("Random number:%d\n", num);
if (num == 1 || num == 6 || num == 8) {
intention[i] = true;
printf("ok\n");
stations++;
printf("stations=%d\n", stations);
printf("intention[%d]=%d\n", i, intention[i]);
double offtime = gentime + 12.0;
printf("channel off until: %.1f starting from: %.1f\n\n",
offtime, gentime);
}
else {
intention[i] = false;
printf("intention[%d]=%d\n", i, intention[i]);
}
}
}
if (stations == 1) {
for (int i = 0; i < N; i++) {
printf("intention[%d]=%d\n", i, intention[i]);
if (intention[i] == true) {
printf("link[%d]:\n", i);
display(link, i);
printf("i=%d\n", i);
remove_node_in_list(link, i);
printf("NEW:\n");
display(link, i);
}
}
}
stations = 0;
return 0;
}
更新:
Very insightfull and helpful, thank you! Why did you put #if 0, #if 1 etc? – wajaap
我这样做是为了 tutorial/documentation 目的。我使用 cpp
条件来表示旧代码与新代码(例如):
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
这比使用 /*
和 */
在这里,IMO,它让 OP 更容易看到在 line-by-line 基础上发生了什么变化。
我也在生产代码中这样做,如果我有“工作”代码,但想尝试一些新的[大概faster/better]代码,但是新的代码是实验性的,可能无法正常工作。
如果新代码不工作[但应该工作],它提供了一种恢复工作代码的简单方法。我可以处理其他事情,当我想办法让它工作时,再回到更好的代码。
我通常将代码 [(e.g.) 提交到 git
] 并保留条件。然后,我手动编辑 out 已删除的代码并提交再次。这个文件 what/why/how 我到达了最终状态。
请注意,在我的第二个代码示例中 [使用节点排序],我删除了 cpp
条件以显示 clean/final 代码。