我正在嘗試使用 .txt 檔案從 .txt 檔案初始化鏈接串列strtok()。
但是當我想初始化名稱(我的結構的第一個元素)時,strtok 回傳一個“(空)”。
然而,當我printf()我strElement我得到預期的名稱。
治愈.c
#include "heals.h"
ListeHeals* initHeals()
{
ListeHeals* ListeHeals = malloc(sizeof(*ListeHeals));
char const* const fileName = "items/heals.txt";
FILE* file = fopen(fileName, "r");
if (file == NULL)
{
printf("Fichier non ouvert");
}
char line[256];
const char * separator = "|";
int count = 0;
while (fgets(line, sizeof(line), file)) {
char* strElement = strtok (line, separator);
while (strElement != NULL) {
Heals* heal = malloc(sizeof(*heal));
if(count == 0)
{
printf("%s\n", strElement);
heal->name = strElement;
}
else if(count == 1)
{
heal->heal = atoi(strElement);
ListeHeals->first = heal;
}
strElement = strtok (NULL, separator);
count = 1;
}
count = 0;
}
fclose(file);
return ListeHeals;
}
void printListeHeals(ListeHeals* ListeHeals)
{
if (ListeHeals == NULL)
{
exit(EXIT_FAILURE);
}
Heals* actual = ListeHeals->first;
while (actual != NULL)
{
printf("Nom : %s\n", actual->name);
printf("heal : %d\n\n", actual->heal);
actual = actual->next;
}
printf("NULL\n");
}
輸出 第一行是我的 printf。
這是檔案 heals.txt :
Potion de vie I|30
Potion de vie II|80
Potion de vie III|200
愈合結構(heal.h):
#ifndef heals_h
#define heals_h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Heals
{
char* name;
int heal;
struct Heals* next;
};
typedef struct Heals Heals;
struct ListeHeals
{
struct Heals* first;
};
typedef struct ListeHeals ListeHeals;
ListeHeals* initHeals();
void printListeHeals(ListeHeals* ListeHeals);
#endif
我期望的輸出:
nom : Potion de vie I // I have (null)
heal : 30 // I already have it
歡迎任何幫助謝謝!
uj5u.com熱心網友回復:
有多個問題,您正在做比需要更復雜的事情。
最重要的是:
- 您不會將您的節點加入您的串列中。
- 您不會
count為每個新行重置。這意味著您不會處理任何其他行的名稱。 - 您不會為字串分配記憶體,而只會將指標分配到
line緩沖區中。當函式完成時,這將超出范圍。 - 當您為每個令牌分配新節點時,您最終會得到一個節點保存名稱,一個節點保存另一個值。
更新:為什么這會導致你得到的結果?您為該名稱分配了一個節點,但不要將其排入您的串列中。然后分配另一個節點。該節點不保存名稱,而只保存第二個值。該節點進入串列。當您列印串列的內容時,您只會找到第二個節點。
您還可以使用任何新節點覆寫串列的頭部,而不將它們鏈接在一起。
因此,無論您閱讀多少行,您的串列中都只會得到 1 個節點。而這個節點只會持有heal價值。
固定版本可能如下所示(未經測驗):
ListeHeals* initHeals()
{
ListeHeals* ListeHeals = malloc(sizeof(*ListeHeals));
// TODO: Check for NULL
char const* const fileName = "items/heals.txt";
FILE* file = fopen(fileName, "r");
if (file == NULL)
{
printf("Fichier non ouvert");
// TODO: return with some error indication. You mustn't continue the function.
}
char line[256];
const char * separator = "|";
while (fgets(line, sizeof(line), file)) {
char* strElement = strtok (line, separator);
if (strElement != NULL) {
Heals* heal = malloc(sizeof(*heal));
// TODO: Check for NULL
// Handle the name
printf("%s\n", strElement);
heal->name = malloc(strlen(strElement 1);
strcpy(heal->name, strElement);
// Handle the value
strElement = strtok (NULL, separator);
// TODO: Check for NULL
heal->heal = atoi(strElement);
// enqueue node into front position
heal->next = ListeHeals->first;
ListeHeals->first = heal;
}
else
printf("invalid file content: %s\n", line);
}
fclose(file);
return ListeHeals;
}
uj5u.com熱心網友回復:
這里有幾個問題,@Gerhardh 已經在他們的回答中詳細說明了其中的大部分問題。但實際上導致你問的問題的是
- 您
Heals在內部回圈的每次迭代中創建一個新的,僅為每個成員的一個成員設定一個值,并將每個成員分配為串列的頭部。因此,當您開始列印時,Heals串列頭(串列中唯一的那個)只有它的heal成員集,而不是它的name元素。另一個Heals獲取相應的名稱集,但該名稱隨后被泄露。
看起來 Gerhard 修改后的代碼也修復了這個問題。即使他們沒有列舉這個特定的問題,他們更自然的實作方法也不容易犯這樣的錯誤。
uj5u.com熱心網友回復:
我試過,輸出這個:
Potion de vie I
Potion de vie II
Potion de vie III
Nom : Potion de vie III
heal : 0
Nom : Potion de vie II
heal : 0
Nom : Potion de vie I
heal : 0
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/338858.html
