我试图创建一个函数来替换文本中的每个单词,并将单词向右移动'k'次。 代码看起来像这样:
void operation_3(char *string, int k){
int len = 0, i;
int string_len = strlen(string);
char *word;
char s[12] = " .,?!\"'";
char *dup;
dup = strdup(string);
word = strtok(dup, s);
while (word != NULL) {
len = strlen(word);
char *new_word = (char *)malloc(len * sizeof(char));
for (i = 0; i < k; i++) {
new_word = shift_to_right(word);
}
string = replace_word(string, word, new_word);
word = strtok(NULL, s);
}
}
shift_to_right是:
char *shift_to_right(char *string){
char temp;
int len = strlen(string) - 1;
int i;
for (i = len - 1; i >= 0; i--) {
temp = string[i+1];
string[i+1] = string[i];
string[i] = temp;
}
return string;
}
replace_word是:
char *replace_word(char *string, char *word, char *new_word) {
int len = strlen(string) + 1;
char *temp = malloc(len * sizeof(char));
int temp_len = 0;
char *found;
while (found = strstr(string, word)) {
if (strlen(found) != strlen(word) || isDelimitator(*(found - 1)) == 1) {
break;
}
memcpy(temp + temp_len, string, found - string);
temp_len = temp_len + found - string;
string = found + strlen(word)
len = len - strlen(word) + strlen(new_word);
temp = realloc(temp, len * sizeof(char));
memcpy(temp + temp_len, new_word, strlen(new_word));
temp_len = temp_len + strlen(new_word);
}
strcpy(temp + temp_len, string);
return temp;
}
和isDelimitator是:
int isDelimitator(char c) {
if(c == ' ' || c == '.' || c == ',' || c == '?' || c == '!' ||
c == '"' || c == '\0' || c == '\'') {
return 0;
}
else return 1;
}
我测试了shift_to_right,replace_word和isDelimitator并且工作正常。但是最终的函数operation_3没有按预期工作。例如,对于输入:“嗨,我是约翰”,对于k = 1,输出为:“嗨,我是约翰”。基本上,operation_3不会修改字符串。有任何建议,更正吗?
答案 0 :(得分:2)
我认为有一些事情可能是错误的原因。
1)在operation_3
中,您执行此操作:new_word = shift_to_right(word);
并且,在char *shift_to_right(char *string)
的定义中,您修改string
本身并返回指向它的指针。因此,如果您调用了shift_to_right(word)
和word = "Hi"
,那么在执行shift_to_right
之后,word
和new_word
现在都指向相同的字符串"iH"
,所以在replace_word
中,当你传递两个单词并检查子串word
时,你总是会得到NULL,因为,没有子串"iH"
。
一种可能的解决方案,在shift_to_right
中添加一个声明,
char *new_string = strdup(string);
而不是交换string
中的字符,现在在new_string
中交换字符并从函数中返回new_string
。
您的代码应如下所示::
char *shift_to_right(char *string){
char temp;
int len = strlen(string) - 1;
char *new_string = strdup(string);
int i;
for (i = len - 1; i >= 0; i--) {
temp = new_string[i+1];
new_string[i+1] = new_string[i];
new_string[i] = temp;
}
return new_string;
}
2)在函数replace_word
中,我们暂时考虑上述错误并未发生,replace_word
使用参数:: {{ 1}}。
因此,当您执行replace_word(string, "Hi", "iH");
时,它会为您提供指向found = strstr(string, word)
开始的第一个字母的指针。因此,在这种情况下,如果您的字符串为Hi
,那么您将获得指向第一个"Hi I am John"
的指针,当您执行H
时,您将获得strlen(found)
(长度为{1}}字符串从指针开始离开)作为输出,12
将始终更少(除非strlen(word)
指向字符串中的最后一个字),因此在大多数情况下,您的found
条件变为如果没有任何交换,你就可以从循环中断开。
此外,正如您自己在评论中指出的那样if
将返回strstr
,如果您想要一个子串Johns
,唯一的解决办法就是运行一个循环,检查John
之后的string
是否存在分隔符,如果没有分隔符,则不是您需要的子字符串。
John
看起来像这样::
replace_word
我认为这个void replace_word(char *string, char *word, char *new_word) {
char *found = strstr(string, word);
int len = strlen(word);
while(found) {
char temp = *(found + len);
if(isDelimeter(temp) == 0) {
break;
} else {
found = strstr(found + len + 1);
}
}
if(found != NULL) {
for(int i = 0; i < len; i++) {
*(found + i) = new_word[i]; // *(found + i) is accessing the i^th, character in string from the pointer found
}
}
}
可以正常工作,您可以直接修改replace_word
,并且不需要实际生成string
字符串并将其返回。这减少了分配新内存和保存指针的需要。
我希望这可以提供帮助!
EDIT :: 由于我们在代码中使用temp
,因此动态分配字符串大小的内存以及strdup
字符的额外块,我们将明确地释放它,所以根据我在退出函数之前在\0
中释放已分配的内存将是一个好主意,因为replace_word
在它之后是没用的。
此外,我在你的代码::
中看到了一个声明 1)new_word
在你开始转换单词之前,我希望你明白你不需要这样做。 char *new_word = (char *)malloc(len * sizeof(char));
只是一个指针,因为我们现在在new_word
中为它分配了内存,所以我们不需要这样做。甚至在此之前,考虑到您编写的代码,没有理由为strdup
分配内存,因为您返回的数组的地址已经在堆栈中,并且将保留在堆栈中直到结束程序的执行。
答案 1 :(得分:1)
此代码比您拥有的代码简单,它会打印输入字符串中的所有单词分隔符。而不是寻找特定的标点字符,而是检查字母数字。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
char instr[] = "Hi! I am 'John' ;)";
int lennin = strlen(instr);
int shifts, i, len, index, start, next;
printf("Working with %s\n", instr);
for(shifts=0; shifts<5; shifts++) { // various examples
printf("Shifts = %d ", shifts);
start = 0;
while(start < lennin) {
while (start < lennin && !isalnum(instr[start])) { // find next alphanum
printf("%c", instr[start]); // output non-alphanum
start++;
}
next = start + 1;
while (isalnum(instr[next])) // find next non-alphanum
next++;
len = next - start;
for(i=0; i<len; i++) { // shift the substring
index = i - shifts;
while(index < 0) index += len; // get index in range
printf("%c", instr[start + (index % len)]); // ditto
}
start = next; // next substring
}
printf("\n");
}
return 0;
}
节目输出:
Working with Hi! I am 'John' ;)
Shifts = 0 Hi! I am 'John' ;)
Shifts = 1 iH! I ma 'nJoh' ;)
Shifts = 2 Hi! I am 'hnJo' ;)
Shifts = 3 iH! I ma 'ohnJ' ;)
Shifts = 4 Hi! I am 'John' ;)