【问题标题】:strlen() crashes when I call it当我调用它时,strlen() 崩溃
【发布时间】:2022-01-02 12:29:32
【问题描述】:

我正在尝试编写一段简单的代码,将两个字符串以偶数和奇数索引合并在一起。

这是代码

void two_strings(char a[], char b[]) {
    int counta = 0, countb = 0;
    int lena = strlen(a); 
    int lenb = strlen(b);
    int lenab = lena + lenb;
    char ans[lenab];
    for(int i = 0; i<strlen(ans); i++) {
        if(i%2 == 0) {
            ans[i] = a[counta];
            counta++;
        }
        else {
            ans[i] = b[countb];
            countb++;
        }
    }
    printf("%s\n", ans);
}

这是主要的:

int main() {   
    char a[] = "hello";
    char b[] = "bye";
    two_strings(a, b);
    return 0;
}

我已经用 -Wall 编译它并且没有收到任何警告或错误,我也尝试过用 long 而不是 int 来检查这是否是问题所在。当我运行代码时,它不会超过第一个 strlen(a)

【问题讨论】:

  • i&lt;strlen(ans) 不应该是该 for 循环中的条件。该数组中没有以 null 结尾的字符串,因此调用 strlen 会调用 未定义的行为。而且仅供参考,您也没有终止您的字符串,即使您尝试过,您也没有额外的插槽。
  • ans 变量中没有数据。
  • 您希望输出以“hello”和“bye”作为输入是什么?它目前会读到较短字符串的末尾。
  • 这不是唯一的问题。我提到的终止很重要。您还假设两个字符串之间最多有一个字符长度差异,而您的示例数据不符合这一点。
  • @Anic17 — 不要向初学者推荐strncat()。它有一个难以理解的界面,很容易被误用。你知道strncat(buffer, very_long_string, sizeof(buffer)) 是一个自动缓冲区溢出,如果长字符串比缓冲区中剩余的空间长吗?即使缓冲区当前持有一个空字符串?

标签: c


【解决方案1】:

C 中的Strings 定义为一系列非空字节,后跟一个终止空字节 ('\0')。

以下是等价的字符串

char one[] = "hello";
char two[] = { 'h', 'e', 'l', 'l', 'o', '\0' };

这两者的字符串长度都是5,并占用6字节的内存。

标准库中的字符串处理函数需要这个空终止字节,您将通过向它们传递一个非空终止数组来调用Undefined Behaviorstrlenprintf(与 %s)是这类函数的示例。

在您的two_strings 函数中,您没有分配足够的内存来存储空终止字节。您也不会尝试将此以空值结尾的字节放入数组中。

为空终止字节分配一个额外的字节,不要尝试获取未初始化数组的字符串长度。

void two_strings(char a[], char b[]) {
    /* ... */

    size_t length = strlen(a) + strlen(b);
    char string[length + 1];
    
    for (size_t i = 0; i < length; i++) {
        /* ... */
    }

    string[length] = '\0';

    /* ... */
}

还要注意size_t 是处理内存索引时使用的正确类型,并且是strlen 返回的类型。


至于您的算法,如果您输入的字符串长度不同,您将尝试在已经到达其末尾后继续索引其中一个字符串。

您可能希望:仅从较大字符串中获取较小字符串的字符长度,当较小字符串用尽时停止;或者,在较小的字符串用完后,将较大字符串的剩余字符附加到结果中。

第二种方法的简单示例:

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

void zip_strings(const char *a, const char *b) {    
    size_t combined_length = strlen(a) + strlen(b);
    char joined_string[combined_length + 1];
    
    for (size_t i = 0; i < combined_length; i++) {
        const char **src = i & 1 ? &b : &a;

        if (!**src)
            src = &a;
        if (!**src)
            src = &b;

        joined_string[i] = *((*src)++);
    }
    
    joined_string[combined_length] = '\0';

    puts(joined_string);
}

int main(int argc, char **argv) {
    if (argc > 2)
        zip_strings(argv[1], argv[2]);    
}
./a.out hello computer
hceolmlpouter

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 2021-06-17
    • 1970-01-01
    • 2011-04-11
    • 2021-11-19
    • 2018-02-20
    相关资源
    最近更新 更多