我的c代码出了什么问题? (可能是malloc调用)

时间:2016-04-07 22:09:46

标签: c string pointers malloc

当我运行此代码时,我遇到了分段错误。我确定我的指针错了,但我不确定为什么或如何解决它。 我还包括了我试图以图片形式回答的问题。 question

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

char * repeat_characters(char *s, int n) {
    printf("%s", *s);

    char temp;
    int length = 0;
    int i = 0;
    int j = 0;
    int k = 0;
    char * newString;

    while(s[length]) {
        length++;
        printf("%d", length);
    } // finds length of string

    newString = (char*) malloc(length*n*sizeof(char));

    while(i++ < i*n) {
        temp = s[i];
        while (j++ < n) {
            newString[k] = temp;
            printf("%c", temp);
            k++;
        }
    }
    printf("%s", newString); 
    return newString;
}

int main () {
    char * string[100];
    int numReps = 0;

    printf("Enter a string: ");
    scanf("%s", string);

    printf("\nEnter number of repetitions: ");
    scanf("%d", &numReps);

    repeat_characters(*string, numReps);
    return 0; 
}

1 个答案:

答案 0 :(得分:1)

作为提问者的一项工作是shorten your program to the minimum,它表明存在问题。例如,以下内容会产生分段错误:

#include <stdio.h>

char * repeat_characters(char *s, int n) {
    printf("%s", *s);
    return NULL;
}

int main () {
    char * string[100];
    scanf("%s", string);

    repeat_characters(*string, 0);
    return 0; 
}

编译器警告可以指出很多类型的问题。所以转过那些警告。如果您正在使用gcc,那么请尝试gcc -Wall -Wextra -Werror main.c之类的内容(或查看编译器的文档。)

(-Werror会将警告变成错误,让你不小心忽略警告,我认为这对学习者和专家来说都是一个好习惯。)

   printf("%s", *s);
     

格式'%s'需要'char *'类型的参数,但参数2的类型为'int'

这里有一个参数char *s。根据上下文,可以是指向单个字符的指针,也可以是指向多字符序列的第一个字符的指针。

C字符串按照惯例操作,即它是一个多字符序列,并且字符范围最终由'\0'(或0值字符)终止。所以当你调用printf时,你必须确保传入的字符指针是这样一个有效形成的序列。

您正在传递*s,它会取消引用指向字符的指针,使其成为单个字符。如果您要打印单个字符,则需要使用%c,例如printf("%c", *s);。但是你想要打印一个C字符串,所以你应该放弃解除引用*,然后说printf("%s\n", s)。 (您可能希望\n输出换行符,否则您的打印件将全部一起运行。)

(注意:当你传递一个预期有字符指针的字符时,没有警告的C没有抱怨的原因是由于printfscanf等函数的“怪异”他们没有固定数量或类型的参数,因此检查的次数较少......警告有助于弥补这一缺陷。)

   scanf("%s", string);
     

格式'%s'需要'char *'类型的参数,但参数2的类型为'char **'

这里有一个问题,你已经声明s为char * string[100];,这是一个字符指针的数组,而不是一个字符数组。 C数组能够表现得像指向其第一个元素的指针的二元性需要一些习惯,但如果你说char string [100];那么string[0]就是char和{{1} }可以“衰变”为与string同义的char*

Is an array name a pointer?

&string[0]
     

'i'上的操作可能未定义

编译器在这里提出了一个技术投诉,关于在同样使用 while(i++ < i*n) 的表达式中修改变量i。它警告i中的i是否会在增量之前或之后看到值。避免这种表达......如果时间到了你关心你能做什么和不能做什么的时候,请阅读sequence points

但把它放在一边。你打算在这里做了什么?从i*n中取出++的细微差别......仅仅while (i < i * n)怎么样?什么时候会是假的?为什么与解决问题有关?

查看您的代码,或者尝试更多地评论它。什么是“不变量”,或者你可以声称的关于每一行都是真的变量的东西?如果你被要求为代码工作的原因辩护 - 没有编译器可以运行它来查看 - 什么会让你确定它做了正确的事情?

然后使用调试器和示例逐步完成它,并检查您的直觉。如果你跨过一条线并且没有得到你所期望的,那么就是时候开始考虑一个问题,问哪个把焦点放到那条线上。

注释中提出了其他问题(例如,你的malloc()不包含终结符的空间,即使你为该空间添加1,你仍然需要写一个{{1进入它...)。一般来说,您的程序应该执行与'\0'一样多的free() s。等等。但希望这能为你指明正确的任务方向。