【问题标题】:C - Replace substring in stringC - 替换字符串中的子字符串
【发布时间】:2016-10-10 08:15:39
【问题描述】:

在我学习 C 的过程中,我正在开发几个用于字符串操作的函数。其中之一具有替换字符串中的子字符串的功能,并提出了一些问题。我在 C99 工作;在 Mac OS Sierra 和 FreeBSD 上编译。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *repstr(char input[], char rep[], char new[]) {

    char *output = malloc(strlen(input)*5); // <- Question 2
    int replen = strlen(rep);
    int newlen = strlen(new);
    int a, b, c = 0;

    // printf("input: %ld\t%s\n", strlen(input), input); // <- Question 1

    while(input[a]) {
            if(input[(a+b)] == rep[b]) {
                    if(b == replen - 1) {
                            strcat(output, new);
                            a += replen;
                            c += newlen;
                            b=0;
                    }
                    else b++;
            } else {
                    output[c] = input[a];
                    a++;
                    c++;
            }
    }

    return output;
}


int main() {

    char buffer[] = "This is the test string test string test test string!";
    char rep[] = "test";
    char new[] = "tested";

    int len = strlen(buffer);

    char output[len+5];

    printf("input: %d\t%s\n", len, buffer); // <- Question 1
    strcpy(output, repstr(buffer, rep, new));
    printf("output: %ld\t%s\n", strlen(output), output);

    return 0;
}

问题 1:在 main() 中执行此行时,会导致段错误。但是,当在函数中执行时,一切似乎都正常。为什么?

问题 2:我意识到我需要为输出分配一块相当大的内存才能达到预期效果。 strlen(input)*5 是一个似乎可以工作的任意数字,但是为什么在降低数字时会出现看似“随机”的错误?

注意!由于这是我学习 C 编码过程的一部分,我主要不是对解决问题的(更有效的)预制解决方案感兴趣(已经有了它们),而是解释列出的两个问题 - 这样我就可以解决我自己的问题。

还有;这是我在 SO 论坛上的第一篇文章。你好。

【问题讨论】:

  • strlen 返回size_t,所以使用%zu 表示printf 格式和变量的正确类型。 newc++ 的保留名称,应避免将其用作变量名。
  • 1. %ld 是错误的格式类型。 2.如果先统计子串的出现次数,就可以算出新串的长度。
  • 此外:您必须检查malloc return != NULL(它可能会失败)并由于内存中包含的随机值而初始化分配的内存。否则,您对 strcat 的呼叫是 UB。
  • 顺便说一句,您的分段错误主要是由于:int a, b, c = 0; 应该是 int a=0, b=0, c = 0; 在您的代码中,ab 的值未初始化为零。
  • output in main 不足以容纳结果!

标签: c string


【解决方案1】:

问题 1:在 main() 中执行此行时,会导致段错误。 但是,当在函数中执行时,一切似乎都有效 美好的。为什么?

不,printf("input: %d\t%s\n", len, buffer); // &lt;- Question 1 不是您的段错误的原因。

printf("output: %ld\t%s\n", strlen(output), output);

这部分是,strlen 不返回 int,但它返回 size_t。如 cmets 中所述,使用%zu 将其打印出来。

另外,while(input[a]) 将在 NULL 终止符处停止,这意味着您的 output 将永远不会包含终止符,因此 printf 将继续阅读,您应该在末尾添加它:

output[c] = '\0';

另外,正如@LPs 在 cmets 中所指出的,您应该零初始化您使用的变量:

 int a = 0, b = 0, c = 0;

问题 2:我意识到我需要相当大的内存 分配给输出看起来像预期的那样。 strlen(input)*5 是一个 似乎可行的任意数字,但为什么我似乎得到 降低数字时出现“随机”错误?

可能是因为您没有分配足够的内存。因为字符串长度取决于运行时因素,所以无法知道您应该分配所需的最大内存量:

char *output = malloc(strlen(input) * strlen(new) + 1);

【讨论】:

  • 感谢您的回答。我已经感觉自己聪明了一些。但是: Q1:我已将 %ld 替换为 %zu,现在将 'len' 存储在 size_t 变量中。问题仍然存在,如果我注释掉 main() 中标有问题 1 的行,程序就会正常运行。如果我保持这条线,我仍然会遇到段错误。 Q2:在这个例子中,输入字符串是 53 个字符,输出字符串是 61。例如,如果我分配 strlen(input)*2,我仍然会得到奇怪的行为。
  • @BNauclér 您是否添加了 NULL 终止符并将您的 int 初始化为零?
  • 啊!零初始化似乎是那里的主要问题。我的印象是我的int a, b, c = 0; 会将它们全部初始化为 0。现在它更改为 int a = 0, b = 0, c = 0;,它运行起来就像一个魅力。是的,还插入了 NULL 终止符。谢谢!
猜你喜欢
  • 1970-01-01
  • 2012-04-03
  • 2013-07-23
  • 2014-06-09
  • 2016-02-25
  • 1970-01-01
相关资源
最近更新 更多