从文件读取时,新行会中断我的排队和推送方法


FILE *fp = fopen(argv[2], "r");
char input[80];
if (fp == NULL) { 
perror("Error");
exit(1);
fclose(fp);
}
Node* stack = NULL;
Node* queue = NULL;
while (fgets(input, 80, fp)) {
const char *space = " fnrtv";
char* tokenS = strtok(input, space);
while (tokenS != NULL) {
printf("test %sn", tokenS);
queue = enqueue(queue, tokenS);
stack = push(stack, tokenS);
tokenS = strtok(NULL, space);
}
}
printf("--Queue--n");
printList(queue);
printf("--Stack--n");
printList(stack);

读取带有空格分隔的单词的文件时。当文件只有一行时,这有效。一旦我有多行,我就开始得到意想不到的输出。 例如,对于输入

hello world man bye boy
a

我得到输出。

test hello
test world
test man
test bye
test boy
test a
--Queue--
a
world
man
bye
boy
a
--Stack--
a
boy
bye
man
world
a

我假设它与我的循环有关?我不太确定。

编辑: 通过建立代币的价值来解决。谢谢!

while (tokenS != NULL) {
char* data = strdup(tokenS);
printf("%sn",data);
queue = enqueue(queue, data);
stack = push(stack, data);
tokenS = strtok(NULL, space);
}
}

如上面的注释中所述,当用tokenS标记input时,tokenS持有的地址指向input内的地址。当您再次调用fgets时,所有先前的指针最终都指向input中的新信息,因为您已经覆盖了下一次调用fgetsinput中的内容。

要解决此问题,只需为tokenS分配存储(例如在tokenScpy中),然后将副本存储在stackqueue中。每个tokenScpy都将指向具有分配存储持续时间的单独内存块,并且不会受到您对input所做的任何更改的影响。(您还负责释放不再需要内存的每个块)

如果您有可用的 POSIXstrdup,则可以在一次调用中提供分配和复制。(但注意:strdup()分配,所以你应该检查异形体是否成功,就像你自己打电话给malloc()一样。

有了strdup()你可以做到:

#define DELIM " fnrtv"
FILE *fp = fopen(argv[2], "r");
char input[80];
if (fp == NULL) { 
perror("Error");
exit(1);
fclose(fp);
}
Node* stack = NULL;
Node* queue = NULL;
while (fgets(input, 80, fp)) {
const char *space = DELIM;
while (tokenS != NULL) {
char *tokenScpy = strdup (tokenS);
if (!tokenScpy) {   /* strdup allocate, you validate */
perror ("malloc-tokenScpy");
break;
}
printf("test %sn", tokenScpy);
queue = enqueue(queue, tokenScpy);
stack = push(stack, tokenScpy);
tokenS = strtok(NULL, DELIM);
}
}
printf("--Queue--n");
printList(queue);
printf("--Stack--n");
printList(stack);

(注意:使用#define DELIM " fnrtv"而不是const char *space = " fnrtv";只是因为space永远不会改变,无论哪种方式都可以)

如果strdup()不可用,则对mallocmemcpy的简单调用将完成相同的操作,例如

while (tokenS != NULL) {
size_t len = strlen (tokenS);
char *tokenScpy = malloc (len + 1);
if (!tokenScpy) {   /* validate every allocation */
perror ("malloc-tokenScpy");
break;
}
memcpy (tokenScpy, tokenS, len + 1);
printf("test %sn", tokenScpy);
queue = enqueue(queue, tokenScpy);
stack = push(stack, tokenScpy);
tokenS = strtok(NULL, DELIM);
}

注意:正如 Leffler 先生指出的那样,queuestack都将存储相同的tokenScpy副本,只要每个指针上只有一个free()调用,就可以了。如果您的堆栈队列例程各自存储了自己的指针free()- 则需要为每个令牌创建第二个副本,以便每个令牌都有自己的副本。在这种情况下,您可以执行类似于以下操作的操作:

while (fgets(input, 80, fp)) {
const char *space = DELIM;
while (tokenS != NULL) {
char *tokenScpys = strdup (tokenS),
*tokenScpyq = strdup (tokenS);
/* strdup allocate, you validate */
if (!tokenScpys || !tokenScpyq) {
perror ("malloc-tokenScpys/tokenScpyq");
break;
}
printf("tests %s  testq %sn", tokenScpys, tokenScpyq);
queue = enqueue(queue, tokenScpyq);
stack = push(stack, tokenScpys);
tokenS = strtok(NULL, DELIM);
}
}

最新更新