이 코드의 while(current != NULL)
를 확인할 수는 (GCC 4.8.2와 맥 OS X 10.9.1에서 테스트) 작동하는 것 같다 : 그렇다 FindPlace()
, CheckNull()
및 NextString()
(및 테스트 드라이버, main()
)처럼 누락 된 함수를 작성하고, 정의에서
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXLETTERS = 32 };
typedef struct dictionary
{
char word[MAXLETTERS];
char **year;
char **synonyms;
char **def;
int countyear;
int countsyn;
int countdef;
struct dictionary *nexdic;
} dictionary;
static void PrintDic(dictionary **head)
{
dictionary *current = *head;
while (current != NULL)
{
printf("%s\n", current->word);
current = current->nexdic;
}
}
static int CheckNull(dictionary *dict)
{
return dict == 0;
}
static char *NextString(char *str)
{
return strchr(str, ',');
}
static dictionary *FindPlace(char *word, dictionary *head)
{
printf("FP: (%p) [%s]\n", (void *)head, word);
dictionary *ohead = 0;
while (head != 0 && printf("HW: (%p) [%s]\n", head, head->word) > 0 && strcmp(head->word, word) < 0)
{
ohead = head;
head = head->nexdic;
}
printf("FP: (%p)\n", (void *)ohead);
return ohead;
}
static void Add(char *word, char *year, int countyear, char *syn, int countsyn,
char *def, int countdef, dictionary **head)
{
// Create new entry
// add new entry
dictionary *newentry = (dictionary *)malloc(sizeof(dictionary));
if (CheckNull(newentry) == 1)
exit(1);
int i;
char *index;
// insert word
strcpy(newentry->word, word);
// insert year
char **toyear = (char **)malloc((countyear + 1) * sizeof(char *));
index = year;
for (i = 0; i <= countyear; i++)
{
toyear[i] = index;
index = NextString(index);
}
newentry->year = toyear;
// insert syn
index = syn;
char **tosyn = (char **)malloc((countsyn + 1) * sizeof(char *));
for (i = 0; i <= countsyn; i++)
{
tosyn[i] = index;
index = NextString(index);
}
newentry->synonyms = tosyn;
// insert definition
index = def;
char **todef = (char **)malloc((countdef + 1) * sizeof(char *));
for (i = 0; i <= countdef; i++)
{
todef[i] = index;
index = NextString(index);
}
newentry->def = todef;
// set counts
newentry->countyear = countyear + 1;
newentry->countsyn = countsyn + 1;
newentry->countdef = countdef + 1;
// Insert new entry in correct place
dictionary *next = FindPlace(newentry->word, *head);
printf("Next = %p; head = %p\n", (void *)next, (void *)*head);
if (next == NULL)
{
printf("-1-\n");
newentry->nexdic = *head;
*head = newentry;
}
else
{
printf("-2-\n");
newentry->nexdic = next->nexdic;
next->nexdic = newentry;
}
}
int main(void)
{
char line[4096];
dictionary *head = 0;
while (fgets(line, sizeof(line), stdin) != 0)
{
size_t offset = 0;
char word[4096];
int nchars;
line[strlen(line)-1] = '\0';
printf("Line: [%s]\n", line);
while (sscanf(line + offset, "%s%n", word, &nchars) == 1)
{
printf("Word: [%s]\n", word);
char *years = "1990,1999";
char *syns = "a,z";
char *defs = "definition1,definition2";
printf("Old Head = %p\n", head);
Add(word, years, 2, syns, 2, defs, 2, &head);
PrintDic(&head);
printf("New Head = %p\n", head);
offset += nchars;
}
}
return 0;
}
FindPlace()
반환 할 때 t을 NULL 것을 그는 새로운 노드가 목록의 머리에 있어야하고, 그렇지 않으면 새로운 노드가 리턴 된 노드 포인터 바로 뒤에 삽입되어야하며, 주요 변경 사항은 필요 이상으로 복잡한 'insert at head'를 처리하는 코드에 달려있다. 있다. 더 이상 존재하지 않는 PrintDic()
에 재미있는 한주기 for
루프가있었습니다. 당신은 수년간의 동의어 및 정의 정보를 포함시킴으로써 우리에게 불편한 과정을 만들었습니다. 아마도이 문제는 현재 당면한 문제에 중요하지 않았을 것입니다. 운전사는 그것들과 가능한 가장 단순한 일을합니다. 전달 된 문자열은 Add()
으로 분할되지 않으므로 첫 해 항목은 모든 항목을 인쇄하고, 두 번째 항목은 첫 번째 항목을 제외한 나머지 항목을 인쇄하는 등의 작업을 수행하며 동의어 및 정의와 유사하게 적용됩니다. 각각의 경우 목록 항목은 쉼표로 구분됩니다.
제자리에 디버그 인쇄 코드가 있습니다. 그것을 제거 할 수 있습니다.
샘플 출력 :
ggg
Line: [ggg]
Word: [ggg]
Old Head = 0x0
FP: (0x0) [ggg]
FP: (0x0)
Next = 0x0; head = 0x0
-1-
ggg
New Head = 0x7f848bc038b0
fff
Line: [fff]
Word: [fff]
Old Head = 0x7f848bc038b0
FP: (0x7f848bc038b0) [fff]
HW: (0x7f848bc038b0) [ggg]
FP: (0x0)
Next = 0x0; head = 0x7f848bc038b0
-1-
fff
ggg
New Head = 0x7f848bc03960
ccc
Line: [ccc]
Word: [ccc]
Old Head = 0x7f848bc03960
FP: (0x7f848bc03960) [ccc]
HW: (0x7f848bc03960) [fff]
FP: (0x0)
Next = 0x0; head = 0x7f848bc03960
-1-
ccc
fff
ggg
New Head = 0x7f848bd00000
ddd
Line: [ddd]
Word: [ddd]
Old Head = 0x7f848bd00000
FP: (0x7f848bd00000) [ddd]
HW: (0x7f848bd00000) [ccc]
HW: (0x7f848bc03960) [fff]
FP: (0x7f848bd00000)
Next = 0x7f848bd00000; head = 0x7f848bd00000
-2-
ccc
ddd
fff
ggg
New Head = 0x7f848bd00000
eee
Line: [eee]
Word: [eee]
Old Head = 0x7f848bd00000
FP: (0x7f848bd00000) [eee]
HW: (0x7f848bd00000) [ccc]
HW: (0x7f848be00000) [ddd]
HW: (0x7f848bc03960) [fff]
FP: (0x7f848be00000)
Next = 0x7f848be00000; head = 0x7f848bd00000
-2-
ccc
ddd
eee
fff
ggg
New Head = 0x7f848bd00000
aaa
Line: [aaa]
Word: [aaa]
Old Head = 0x7f848bd00000
FP: (0x7f848bd00000) [aaa]
HW: (0x7f848bd00000) [ccc]
FP: (0x0)
Next = 0x0; head = 0x7f848bd00000
-1-
aaa
ccc
ddd
eee
fff
ggg
New Head = 0x7f848be000b0
bbb
Line: [bbb]
Word: [bbb]
Old Head = 0x7f848be000b0
FP: (0x7f848be000b0) [bbb]
HW: (0x7f848be000b0) [aaa]
HW: (0x7f848bd00000) [ccc]
FP: (0x7f848be000b0)
Next = 0x7f848be000b0; head = 0x7f848be000b0
-2-
aaa
bbb
ccc
ddd
eee
fff
ggg
New Head = 0x7f848be000b0
zzz
Line: [zzz]
Word: [zzz]
Old Head = 0x7f848be000b0
FP: (0x7f848be000b0) [zzz]
HW: (0x7f848be000b0) [aaa]
HW: (0x7f848bc03a10) [bbb]
HW: (0x7f848bd00000) [ccc]
HW: (0x7f848be00000) [ddd]
HW: (0x7f848bf00000) [eee]
HW: (0x7f848bc03960) [fff]
HW: (0x7f848bc038b0) [ggg]
FP: (0x7f848bc038b0)
Next = 0x7f848bc038b0; head = 0x7f848be000b0
-2-
aaa
bbb
ccc
ddd
eee
fff
ggg
zzz
New Head = 0x7f848be000b0
글쎄, 당신은 당신이 중 하나가 널 포인터가 있거나 배열 범위를 벗어날 색인하는 귀하의 구조가 채워됩니다 어떻게 표시되지 않습니다. 디버거를 사용하는 법을 배울 시간. – OldProgrammer
아마도'current-> def [i]'가 segfaults가있는 시스템상의 해제 된 항목을 가리 키기 때문일 것입니다. – dasblinkenlight
구조가 사용되기 전에 어떻게 초기화하는지 확인하십시오. 아마도 그것은 VS에서 동작하고 리눅스에서는 작동하지 않을 수 있습니다. 왜냐하면 VS는 (특별히 Debug 버전에서)'current-> nexdic'을 NULL로 초기화 할 수 있고 (current-> nexdic == NULL' true) 그리고 리눅스가'else'로 가서 충돌을 일으킨다. –