为什么我的代码给我分段错误?

时间:2019-01-30 17:45:30

标签: c

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

void concatena(char *, char *, char *);
void conta_consonanti(char [], int *);
void copy_string(char [], char [ ], int);

int main(void) {
    char *input1, *input2, *output;
    input1 = "sdaeteruiop";
    input2 = "eiyearteoiana";
    concatena(input1, input2, output);
    printf("%s\n", output);
    free(output);
    return 0;
}

void concatena(char *input1, char *input2, char *output) {
    int num_cons1 = 0, num_cons2 = 0, dim_input1, dim_input2;
    conta_consonanti(input1, &num_cons1);
    conta_consonanti(input2, &num_cons2);
    if (num_cons1 < num_cons2) {
        dim_input1 = strlen(input1) + strlen(input2);
        output = malloc(dim_input1 * sizeof(char));
        copy_string(output, input1, 0);
        copy_string(output, input2, strlen(input1));
    } else if (num_cons2 < num_cons1) {
        dim_input2 = strlen(input2) + strlen(input1);
        output = malloc(dim_input2 * sizeof(char));
        copy_string(output, input2, 0);
        copy_string(output, input1, strlen(input2));
    }
}

void conta_consonanti(char vect[], int *num_cons) {
    int dim = strlen(vect), i;
    for (i = 0; i < dim; i++)
        if (vect[i] != 'a' && vect[i] != 'e' && vect[i] != 'i' && vect[i] != 'o' && vect[i] != 'u')
            *num_cons++;
}

void copy_string(char output[], char input [ ], int offset) {
    int dim, i;
    dim = strlen(input);
    for (i = 0; i < dim; i++) {
        output[offset] = input[i];
        offset++;
    }
}

为什么我的代码给我分段错误?

程序应将两个字符串连接起来并将结果字符串存储在output中,但它给我分段错误。为什么?

辅音较少的字符串首先存储。

3 个答案:

答案 0 :(得分:2)

 concatena(input1, input2, output);
 printf("%s\n", output);

输出的值被 concatena 保持不变,因此您打印未初始化的字符* =>崩溃或任何其他未定义的行为

您需要将输出设为输出变数,因此void concatena(char *input1, char *input2, char **output)等如下:

int main(void){
    char *input1, *input2, *output;
    input1 = "sdaeteruiop";
    input2 = "eiyearteoiana";
    concatena(input1, input2, &output);
    printf("%s\n", output);
    free(output);
    return 0;
}

void concatena(char *input1, char *input2, char **output){
    int num_cons1 = 0, num_cons2 = 0, dim_input1, dim_input2;
    conta_consonanti(input1, &num_cons1);
    conta_consonanti(input2, &num_cons2);
    if(num_cons1 < num_cons2){
        dim_input1 = strlen(input1) + strlen(input2);
        *output = malloc(dim_input1 + 1);
        strcpy(*output, input1);
        strcat(*output, input2);
    }else {
        dim_input2 = strlen(input2) + strlen(input1);
        *output = malloc(dim_input2 + 1);
        strcpy(*output, input2);
        strcat(*output, input1);
    }
}

我还修复了您的malloc,您为空终止符错过了1个字符

如果未设置num_cons2 == num_cons1 *输出并且仍打印未初始化,则发出警告,您需要将其设置为NULL并测试该大小写,然后再进行打印,或更可能用else if(num_cons2 < num_cons1)替换else(这是我上面所做的)

还请注意dim_input1dim_input2的值相同,无法区分它们

copy_string的第一个调用可以用strcpy替换,第二个调用可以用strcat替换,除了copy_string缺少最后一个空字符之外,< / strong>。我删除了使用copy_string

警告声明void concatena(char *, char *, char *);必须更新为void concatena(char *, char *, char **);

执行:

eiyearteoianasdaeteruiop

valgrind 下:

pi@raspberrypi:~ $ valgrind ./a.out
==15629== Memcheck, a memory error detector
==15629== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==15629== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==15629== Command: ./a.out
==15629== 
eiyearteoianasdaeteruiop
==15629== 
==15629== HEAP SUMMARY:
==15629==     in use at exit: 0 bytes in 0 blocks
==15629==   total heap usage: 2 allocs, 2 frees, 1,049 bytes allocated
==15629== 
==15629== All heap blocks were freed -- no leaks are possible
==15629== 
==15629== For counts of detected and suppressed errors, rerun with: -v
==15629== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

答案 1 :(得分:2)

您的代码中存在多个问题:

  • 您通作的目的地阵列(第三参数)未初始化的指针concatena。 API不正确:您应该使concatena返回指向新分配的数组的指针作为返回值。当前实现覆盖第三个参数output这个分配的值永远不会返回给调用者。 C没有 output 参数的概念,您可以将指针传递给调用者的output指针,类型为char **,但是使用返回值要简单得多。
  • concatena执行的分配是错误的:您应为null终止符分配一个额外的字节,并且sizeof(char)根据定义为1

    output = malloc(dim_input1 + 1);
    
  • conta_consonanti也不正确:必须将num_cons++*num_cons写成(*num_cons)++所指向的数字递增。 *num_cons++;递增指针,而不是所指向的值。此外,正如汤姆·兰德尔(Tom Randall)所评论的那样,辅音的数量不一定与非元音的数量相同,因为字符串可能包含非字母。另外算上所有大写字母为辅音,这似乎不正确了。

  • 如果两个字符串具有相同数量的辅音,则代码将具有未定义的行为,您应指定在这种情况下发生的情况(并实现)。

  • copy_string未在目标缓冲区中设置空终止符。可以在此处进行设置,也可以在concatena中手动进行设置。

这是经过更正(简化)的版本:

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

char *concatena(const char *s1, const char *s2);
int conta_consonanti(const char *vect);
void copy_string(char *output, const char *intput);

int main(void) {
    const char *input1 = "sdaeteruiop";
    const char *input2 = "eiyearteoiana";
    char *output = concatena(input1, input2);
    printf("%s\n", output);
    free(output);
    return 0;
}

char *concatena(const char *input1, const char *input2) {
    int len1 = strlen(input1);
    int len2 = strlen(input2);
    int num_cons1 = conta_consonanti(input1);
    int num_cons2 = conta_consonanti(input2);
    char *output = malloc(len1 + len2 + 1);
    if (output != NULL) {
        if (num_cons1 <= num_cons2) {
            copy_string(output, input1, 0);
            copy_string(output, input2, len1);
        } else {
            copy_string(output, input2);
            copy_string(output, input1, len1);
        }
        output[len1 + len2] = '\0';  // set the null terminator
    }
    return output;
}

int conta_consonanti(const char *vect) {
    int i, num_cons = 0;
    for (i = 0; vect[i] != '\0'; i++) {
        /* counting ASCII consonants, upper and lowercase */
        /* our French friends will miss the ç and our Spanish ones the ñ */
        if (strchr("BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz", vect[i])
            num_cons++;
    }
    return num_cons;
}

void copy_string(char *output, const char *input, int offset) {
    int i;
    for (i = 0; input[i] != '\0'; i++) {
        output[offset] = input[i];
        offset++;
    }
}

答案 2 :(得分:0)

您尝试释放main中的output,但未分配任何值。 concatena中的分配不会返回到main。从concatena内部返回已分配的缓冲区并将其分配给output,然后最后对其进行清理,会更有意义。