gpt4 book ai didi

c - 从文件中读取时,新行会破坏我的入队和推送方法

转载 作者:行者123 更新时间:2023-11-30 14:39:23 24 4
gpt4 key购买 nike

    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 = " \f\n\r\t\v";
char* tokenS = strtok(input, space);

while (tokenS != NULL) {
printf("test %s\n", 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

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

编辑:通过 strdup 解决了 tokenS 的值。谢谢!

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

最佳答案

正如上面评论中所解释的,在标记 input 时与 tokenStokenS 持有的地址指向 input 范围内的地址。当您调用fgets时同样,之前的所有指针最终都指向 input 中的新信息。因为您已经覆盖了 input 中的内容下次调用fgets .

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

如果您有 POSIX strdup可用,可以在一次调用中提供分配和复制。 (但请注意: strdup() 分配,因此您应该检查分配是否成功,就像您自己调用 malloc() 一样。

strdup()你可以这样做:

#define DELIM " \f\n\r\t\v"

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 %s\n", 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 " \f\n\r\t\v" 被用来代替 const char *space = " \f\n\r\t\v"; 只是因为 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 %s\n", tokenScpy);
queue = enqueue(queue, tokenScpy);
stack = push(stack, tokenScpy);
tokenS = strtok(NULL, DELIM);
}

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

        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 %s\n", tokenScpys, tokenScpyq);
queue = enqueue(queue, tokenScpyq);
stack = push(stack, tokenScpys);
tokenS = strtok(NULL, DELIM);
}
}

关于c - 从文件中读取时,新行会破坏我的入队和推送方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56104438/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com