我正在编写一个将读入两个文件的程序(hw8.data和codex.data)hw8.data包含一首诗,codex.data包含要在该诗中替换的单词。我已经将文件加载并保存在链表中。我无法找到匹配的单词并替换它们。另外,我无法将hw8中的标点符号转换为新替换的单词。 hw8:Hello World。,codex:World sup,所以诗中的新词是Hello sup。 这是hw8.data
Eye have a spelling chequer,
It came with my Pea Sea.
It plane lee marks four my revue,
Miss Steaks I can knot sea.
Eye strike the quays and type a whirred,
And weight four it two say,
Weather eye am write oar wrong,
It tells me straight aweigh.
Eye ran this poem threw it,
Your shore real glad two no.
Its vary polished in its weigh.
My chequer tolled me sew.
A chequer is a bless thing,
It freeze yew lodes of thyme.
It helps me right all stiles of righting,
And aides me when eye rime.
Each frays come posed up on my screen,
Eye trussed too bee a joule.
The chequer pours over every word,
Two cheque sum spelling rule.
Codex.data(不是全部)
Eye I
eye I
chequer checker
Pea P
Sea C
plane plainly
lee skip
four for
revue review
Miss Mistakes
Steaks skip
knot not
sea see
quays keys
.
.
.
这是我的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node {
char * word;
struct node* next;
};
struct codex {
char *word1;
char *word2;
struct codex *next;
};
struct node *loadWords(FILE *stream);
struct codex *loadCodex(FILE *stream);
struct node *exchange(struct node *head, struct codex *headC);
int main()
{
FILE *stream = NULL;
struct node *head;
struct node *temp;
struct node *loop;
struct codex *headC;
struct codex *tempC;
struct codex *loopC;
head = loadWords(stream);
if (head == NULL) {
return 1;
}
temp = head;//print each word
while (temp != NULL) {
//printf ( "%s\n", temp->word);
temp = temp->next;
}
headC = loadCodex(stream);
if (headC == NULL) {
return 1;
}
tempC = headC;//print each word
while (tempC != NULL) {
//printf ( "%s %s\n", tempC->word1, tempC->word2);
tempC = tempC->next;
}
struct node *exchangedHead;
struct node *temp2;
exchangedHead = exchange(head, headC);
if (exchangedHead == NULL) {
return 1;
}
temp2 = exchangedHead;//print each word
while (temp2 != NULL) {
//printf ( "%s ", temp2->word);
temp2 = temp2->next;
}
temp = head;// free memory
while(temp != NULL) {
loop = temp->next;
free ( temp->word);
free ( temp);
temp = loop;
}
tempC = headC;// free memory
while (tempC != NULL) {
loopC = tempC->next;
free ( tempC->word1);
free ( tempC->word2);
free ( tempC);
tempC = loopC;
}
return 0;
}
/*
* This function will go through and load the words from the text file and save it to
* the struct and link the current struct to the next one
*/
struct node *loadWords(FILE *stream) {
struct node *loop = NULL;
struct node *temp = NULL;
struct node *head = NULL;
char *words = NULL;
char *currentWord;
size_t chrCount = 0;
if ((stream = fopen("hw8.data", "r")) == NULL) {
printf ("could not open file\n");
return NULL;
}
while(getline( &words, &chrCount, stream) > 0) {//read a line from file
currentWord = strtok(words, " ");//get first token
while (currentWord != NULL) {//loop through tokens
if((temp = calloc(1, sizeof(struct node))) == NULL) {
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
temp->word = strdup ( currentWord);//allocate memory and copy token to word
if ( head == NULL) {
head = temp;//first structure
}
else {
loop = head;
while ( loop->next != NULL) {//loop to last structure
loop = loop->next;//add structure to end
}
loop->next = temp;
}
currentWord = strtok(NULL, " ");//next token
}
free (words);//release memory
chrCount = 0;//so readline will allocate memory for next line
words = NULL;
}
return head;
}
/*
* This function will go through and load the words from the text file and save it to
* the struct and link the current struct to the next one
*/
struct codex *loadCodex(FILE *stream) {
struct codex *loop = NULL;
struct codex *temp = NULL;
struct codex *head = NULL;
char *words = NULL;
char *currentWord;
char *currentWord2;
size_t chrCount = 0;
if (( stream = fopen("codex.data", "r")) == NULL) {
printf ("could not open file\n");
return NULL;
}
while(getline( &words, &chrCount, stream) > 0) {//read a line from file
currentWord = strtok(words, " ");//get first token
currentWord2 = strtok(NULL, "\n");
while (currentWord != NULL && currentWord2 != NULL) {//loop through tokens
if((temp = calloc(1, sizeof(struct node))) == NULL) {
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
temp->word1 = strdup ( currentWord);//allocate memory and copy token to word
temp->word2 = strdup ( currentWord2);
if (head == NULL) {
head = temp;//first structure
}
else {
loop = head;
while ( loop->next != NULL) {//loop to last structure
loop = loop->next;//add structure to end
}
loop->next = temp;
}
currentWord = strtok(NULL, " ");//next token
}
free (words);//release memory
chrCount = 0;//so readline will allocate memory for next line
words = NULL;
}
return head;
}
struct node *exchange(struct node *head, struct codex *headC) {
struct node *temp;
temp = head;
while(head != NULL && headC != NULL) {
if(strcmp(head->word, headC->word1)) {
head->word = relloc(head->word, strlen(headC->word2));
head->word = headC->word2;
head->next = temp->next;
headC = headC->next;
temp = temp->next;
}
}
}
答案 0 :(得分:0)
您在exchange
中遇到的问题(错误拼写realloc
并且未能返回值)未能为null-terminating
上的realloc
字符分配空间。 (注意我还没有检查列表操作的正确性)
head->word = realloc(head->word, strlen(headC->word2));
应该是
head->word = realloc(head->word, strlen(headC->word2) + 1);
这可以解释为什么你在每行末尾丢失1-char
标点符号。
如果重新分配成功,您还应该realloc
到tmp
指针,并且只分配head->word = tmp;
。 (否则您将丢失head->word
的原始内容)此外,如果您不打算从exchange
返回值,只需创建函数void
(否则返回head
) 。如果这不能解决问题,请告诉我,我会深入挖掘。
更多问题
查看代码,我看到了几个问题(一些重要的问题)。主要是,您的exchange
功能是火车残骸。通常,在迭代链表时,您创建一个迭代的临时指针,而不是使用列表地址(就像您在main
中所做的那样)。为什么你没有交换呢?鉴于此,我取消了交换并重写了它。它包括在下面。在您的阅读功能中,明智地选择使用getline
,但无需重置chrCount = 0;
或words = NULL;
,以便getline
分配下一行。它自动完成。
但是,当你将words
行发送到strtok
时,你犯了一个犯规 - 没有先复制。为什么? getline
分配了空间并需要管理/释放它分配的内存块。当您将words
发送到strtok
时,它会修改内存,插入null-terminating
字符,这会导致getline
尝试free/realloc
阻止时出现杂散错误。 始终在将行发送到getline
之前复制strtok
分配的行。此外,由于你必须释放副本,因此请为您的副本创建pointer
,以便保留内存块的起始地址,以便在完成后传递到free
无需将未打开的FILE*
指针传递给您的读取函数。这可以在函数中声明。您需要传递的是filename
,因此您的阅读功能可以知道要打开的内容。我更改了main
以包含其参数,因此您现在将/ codex文件名作为参数传递。
注意:我刚刚使用您的示例codex值进行测试。
查看修改和评论中的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct node {
char * word;
struct node* next;
};
struct codex {
char *word1;
char *word2;
struct codex *next;
};
struct node *loadWords(char *filename);
struct codex *loadCodex(char *filename);
struct node *exchange(struct node *head, struct codex *headC);
int main (int argc, char **argv)
{
if (argc < 3) {
fprintf (stderr, "error: insufficient input. Usage: %s nodefile codexfile\n", argv[0]);
return 1;
}
// FILE *stream = NULL;
struct node *head;
struct node *temp;
struct node *loop;
struct codex *headC;
struct codex *tempC;
struct codex *loopC;
head = loadWords(argv[1]);
if (head == NULL) {
return 1;
}
printf ("\nOriginal:\n\n");
temp = head;//print each word
while (temp != NULL) {
printf ( " %s", temp->word);
temp = temp->next;
}
printf ("\n");
headC = loadCodex(argv[2]);
if (headC == NULL) {
return 1;
}
tempC = headC;//print each word
while (tempC != NULL) {
// printf ( "%s %s\n", tempC->word1, tempC->word2);
tempC = tempC->next;
}
struct node *exchangedHead;
struct node *temp2;
exchangedHead = exchange(head, headC);
if (exchangedHead == NULL) {
return 1;
}
printf ("\nExchanged:\n\n");
temp2 = exchangedHead;//print each word
while (temp2 != NULL) {
printf ( " %s", temp2->word);
temp2 = temp2->next;
}
printf ("\n");
temp = head;// free memory
while(temp != NULL) {
loop = temp->next;
free ( temp->word);
free ( temp);
temp = loop;
}
tempC = headC;// free memory
while (tempC != NULL) {
loopC = tempC->next;
free ( tempC->word1);
free ( tempC->word2);
free ( tempC);
tempC = loopC;
}
return 0;
}
/*
* This function will go through and load the words from the text file and save it to
* the struct and link the current struct to the next one
*/
struct node *loadWords(char *filename) {
FILE *stream = NULL;
struct node *loop = NULL;
struct node *temp = NULL;
struct node *head = NULL;
char *words = NULL;
char *currentWord;
size_t chrCount = 0;
ssize_t nchr = 0;
if ((stream = fopen(filename, "r")) == NULL) {
printf ("could not open file\n");
return NULL;
}
while((nchr = getline (&words, &chrCount, stream)) != -1) {//read a line from file
char *wtemp = strdup (words); /* copy words, strtok will modify */
char *sp = wtemp; /* save wtemp address, pass sp */
currentWord = strtok(sp, " ");//get first token
while (currentWord != NULL) {//loop through tokens
if((temp = calloc(1, sizeof(struct node))) == NULL) {
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
temp->word = strdup (currentWord);//allocate memory and copy token to word
if ( head == NULL) {
head = temp;//first structure
}
else {
loop = head;
while ( loop->next != NULL) {//loop to last structure
loop = loop->next;//add structure to end
}
loop->next = temp;
}
currentWord = strtok(NULL, " ");//next token
}
if (wtemp) free (wtemp);
wtemp = NULL;
// chrCount = 0; //so readline will allocate memory for next line (***NOT REQUIED***)
// words = NULL; (***NOT REQUIED***)
}
if (words) free (words);//release memory
if (stream) fclose (stream);
return head;
}
/*
* This function will go through and load the words from the text file and save it to
* the struct and link the current struct to the next one
*/
struct codex *loadCodex(char *filename) {
FILE *stream = NULL;
struct codex *loop = NULL;
struct codex *temp = NULL;
struct codex *head = NULL;
char *words = NULL;
char *currentWord;
char *currentWord2;
size_t chrCount = 0;
ssize_t nchr = 0;
if (( stream = fopen(filename, "r")) == NULL) {
printf ("could not open file\n");
return NULL;
}
while(getline( &words, &chrCount, stream) > 0) {//read a line from file
while (nchr > 0 && (words[nchr-1] == '\n' || words[nchr-1] == '\r'))
words[--nchr] = 0; /* strip newline or carriage rtn */
char *wtemp = strdup (words); /* copy words, strtok will modify */
char *sp = wtemp; /* save wtemp address, pass sp */
currentWord = strtok(sp, " ");//get first token
currentWord2 = strtok(NULL, "\n");
while (currentWord != NULL && currentWord2 != NULL) {//loop through tokens
if((temp = calloc(1, sizeof(struct node))) == NULL) {
printf("ERROR - Could not allocate memory.\n");
exit(0);
}
temp->word1 = strdup ( currentWord);//allocate memory and copy token to word
temp->word2 = strdup ( currentWord2);
if (head == NULL) {
head = temp;//first structure
}
else {
loop = head;
while ( loop->next != NULL) {//loop to last structure
loop = loop->next;//add structure to end
}
loop->next = temp;
}
currentWord = strtok(NULL, " ");//next token
}
if (wtemp) free (wtemp);
wtemp = NULL;
// chrCount = 0;//so readline will allocate memory for next line
// words = NULL;
}
if (words) free (words);//release memory
if (stream) fclose (stream);
return head;
}
// struct node *exchange(struct node *head, struct codex *headC) {
// struct node *temp;
// temp = head;
// while(head != NULL && headC != NULL) {
// if(strcmp(head->word, headC->word1)) {
// head->word = realloc(head->word, strlen(headC->word2));
// head->word = headC->word2;
// head->next = temp->next;
// headC = headC->next;
// temp = temp->next;
// }
// }
// }
struct node *exchange(struct node *head, struct codex *headC)
{
struct node *temp = head;
while(temp != NULL)
{
char *wtemp = NULL;
struct codex *tempC = headC;
while (tempC != NULL)
{
if (strcmp(temp->word, tempC->word1) == 0) {
size_t tclen = strlen(tempC->word2);
wtemp = realloc(temp->word, tclen + 1); /* add 1 for null-term */
if (!wtemp) {
fprintf (stderr, "%s() error: realloc failed.\n", __func__);
return head;
}
temp->word = wtemp;
memcpy (temp->word, tempC->word2, tclen + 1); /* copies the null-term also */
}
tempC = tempC->next;
}
temp = temp->next;
}
return head;
}
<强>输出强>
$ ./bin/ll_single_replace_w dat/ll_replace_poem.txt dat/ll_replace_codex.txt
Original:
Eye have a spelling chequer,
It came with my Pea Sea.
It plane lee marks four my revue,
Miss Steaks I can knot sea.
Eye strike the quays and type a whirred,
And weight four it two say,
Weather eye am write oar wrong,
It tells me straight aweigh.
Eye ran this poem threw it,
Your shore real glad two no.
Its vary polished in its weigh.
My chequer tolled me sew.
A chequer is a bless thing,
It freeze yew lodes of thyme.
It helps me right all stiles of righting,
And aides me when eye rime.
Each frays come posed up on my screen,
Eye trussed too bee a joule.
The chequer pours over every word,
Two cheque sum spelling rule.
Exchanged:
I have a spelling chequer,
It came with my P Sea.
It plainly skip marks for my revue,
Mistakes skip I can not sea.
I strike the keys and type a whirred,
And weight for it two say,
Weather I am write oar wrong,
It tells me straight aweigh.
I ran this poem threw it,
Your shore real glad two no.
Its vary polished in its weigh.
My checker tolled me sew.
A checker is a bless thing,
It freeze yew lodes of thyme.
It helps me right all stiles of righting,
And aides me when I rime.
Each frays come posed up on my screen,
I trussed too bee a joule.
The checker pours over every word,
Two cheque sum spelling rule.