我有一个包含许多字符的链表,我从输入(what is the weather today?
)中输入这些字符,并将其替换为另一个字符串(例如,what
替换为how
,因此得到how is the weather today?
)。
但是如果给定的单词彼此紧邻,例如whatwhat
,则它将更改为howwhat
,而忽略第二部分。
我认为问题出在比较函数中,但是我不知道如何修复它,但是替换的逻辑应该是这样的:
如果我的列表中的单词和需要的单词相同,那么继续迭代到应该改变的单词的下一个节点的位置(不需要的单词)应为(几乎是单词的结尾),然后我创建一个新的链表,其中包含所需单词的字符,并将temp连接到列表的开头,将列表的next连接到需要更改的单词(不需要的单词)的下一个字符所在的位置,这是我在第一个循环中找到的。
也不要烤我的input()
函数,我知道它是不安全的,我只是想看看什么是不安全的意思与我自己的眼睛,而我仍然没有什么损失。
下面是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int value_c;
struct node *next_c;
struct node *prev_c;
};
typedef struct node string;
int compare(string *head, char *word) {
int counter = 0;
string *temp = head;
for (int i = 0; i < strlen(word); i++) {
if (temp->value_c == word[i]) {
temp = temp->next_c;
counter++;
}
}
if (counter == strlen(word))
return 1;
else
return 0;
}
void print_c(string *head) {
while (head != NULL) {
printf("%c", head->value_c);
head = head->next_c;
}
}
void append_c(string **head, char thing) {
string *newNode = (string *)malloc(sizeof(string));
newNode->value_c = thing;
newNode->next_c = NULL;
if (*head == NULL) {
*head = newNode;
newNode->prev_c = NULL;
return;
}
string *temp = *head;
while (temp->next_c != NULL)
temp = temp->next_c;
temp->next_c = newNode;
newNode->prev_c = temp;
}
string *replace_all1(string *head, char *what, char *with_what) {
string *temp = head;
while (temp != NULL) {
printf("%c ", temp->value_c);
if (compare(temp, what) == 1) {
printf("%i ", 1);
printf("%c ", temp->value_c);
string *new = temp;
for (int i = 0; i < strlen(what) - 1; i++) {
new = new->next_c;
}
string *word = NULL;
for (int i = 0; i < strlen(with_what); i++) {
append_c(&word, with_what[i]);
}
string *word_temp = word;
while (word_temp->next_c != NULL) {
word_temp = word_temp->next_c;
}
word_temp->next_c = new->next_c;
if (temp->prev_c != NULL) {
temp->prev_c->next_c = word;
} else {
head = word;
print_c(head);
temp = word;
print_c(temp);
word->prev_c = NULL;
}
}
temp = temp->next_c;
}
printf("\n");
return head;
}
string *String(char *str) {
string *st = NULL;
int i = 0;
while (str[i] != '\0') {
append_c(&st, str[i]);
i++;
}
return st;
}
string *input() {
char *a = (char *)malloc(sizeof(char));
scanf("%[^\n]", a); //maximum of 1408
string *stri = String(a);
return stri;
free(a);
}
int main() {
string *list = NULL;
string *big_boy_string = input();
//printf("%c", big_boy_string->value_c);
//print_c(big_boy_string);
//printf("\n");
//printf("%i", compare(big_boy_string, "what"));
//printf("%i ", len(big_boy_string));
//printf("\n");
//print_c(slice(big_boy_string, 1, 10));
//print_c(replace(big_boy_string, 'h', 'a'));
//printf("\n");
//print_c(reverse(big_boy_string));
print_c(replace_all1(big_boy_string, "a", "b"));
//getline();
}
2条答案
按热度按时间epggiuax1#
第一条语句只分配1个字节的内存,所以最大值不是1408,而是1,它可以存储一个
char
,如果是字符串,则可以存储空终止符,但不能存储更多。接下来,
scanf()
将写入超出边界的内存,并调用未定义的行为。后续函数都依赖于此未定义的行为,所以我不打算查看它们。但是,在同一个函数中会出现内存泄漏。
在释放分配的内存之前执行
return
。对free()
的调用永远不会执行。malloc()
的返回值也会被忽略。如果后续的取消引用发生在NULL
指针上,则代码可能会出现未定义的行为。旁白:强制类型转换没有意义,可能会隐藏一个bug。
malloc()
和family返回一个void *
,它被隐式转换为正确的类型。回复:也不要烤我的输入()函数,我知道它不安全,我只是想看看什么是不安全的意思与我自己的眼睛。
如果你已经意识到这一点,那么你就不应该问为什么你的代码不工作,你是在依赖未定义的行为(玩火)。
rdrgkggo2#
除了
input
函数外,没有必要看得更远:它有未定义的行为或最坏的类型,因为你试图将输入字符串读入一个非常小的数组,分配给一个字节。你必须首先修复这个问题。既然你知道你的输入字符串的最大长度,你可以使用这个:以下是使用
getchar()
代替scanf()
的替代方案,后者相当棘手且容易出错:比较函数不正确:一旦比较失败,它应该返回false,并且必须测试字符串的结尾(
temp == NULL
):replace_all1()
函数也有问题:what
是空字符串,for (int i = 0; i < strlen(what) - 1; i++)
将导致未定义的行为,因为strlen(what) - 1
在这种情况下与值SIZE_MAX
无符号,导致循环进行很长时间,远远超过new
所指向的列表的结尾。while (word_temp->next_c != NULL)
将导致未定义的行为,因为word_temp
将是NULL
。temp
以指向被替换节点之后的节点,这可以通过将temp
设置为word_temp
来实现。以下是修改后的版本:
示例会话: