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
中的新信息,因为您已经覆盖了下一次调用fgets
时input
中的内容。
要解决此问题,只需为tokenS
分配存储(例如在tokenScpy
中),然后将副本存储在stack
和queue
中。每个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()
不可用,则对malloc
和memcpy
的简单调用将完成相同的操作,例如
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 先生指出的那样,queue
和stack
都将存储相同的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);
}
}