【问题标题】:What's wrong with my c code? (it's probably the malloc call) [closed]我的c代码有什么问题? (这可能是 malloc 调用)[关闭]
【发布时间】:2016-04-07 22:09:45
【问题描述】:

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

#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; 
}

【问题讨论】:

  • @M.M 说了什么,加上请使用制表符,我几乎无法分辨出该功能中有什么,没有什么,不容易阅读。话虽如此,请查看如何使用malloc。 tutorialspoint.com/c_standard_library/c_function_malloc.htm
  • 哇。太粗鲁了。代码在我的文本编辑器中正确显示。对不起,这里的格式错误。我已经尝试查找如何使用 malloc,显然我不明白,否则我不会在这里发布。感谢您的帮助...
  • while(i++ &lt; i*n) => while (i++ &lt; length) 并在每个 while (j++ &lt; n) 之前将 j 重置为 0
  • 当我放#号时,导致include被加粗,而不是正常显示。是否需要包含格式代码以使我的代码显示在文本编辑器中的样子?
  • 娜奥米,请阅读MarkDown。还有@MattClark ......如果你要去edit posts to fix the formatting,那么不要只是缩进4并将其保留为双倍行距并在文本中留下cmets,如“#&lt;不会' t 出现”,但字符仍然丢失。 :-/

标签: c string pointers malloc


【解决方案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]charstring 可以“衰减”为 @ 987654344@与&amp;string[0]同义:

Is an array name a pointer?

   while(i++ < i*n)

对“i”的操作可能未定义

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

但是把它放在一边。你在这里打算做什么?去掉++ 的细微差别......那么while (i &lt; i * n) 呢?什么时候会是假的?为什么它与解决问题相关?

查看您的代码,或许可以尝试对其进行更多评论。什么是“不变量”,或者您可以对每行都为真的变量声明哪些内容?如果你被要求为代码工作的原因辩护——没有编译器来运行它来查看——什么会让你确信它做了正确的事情?

然后使用调试器和示例逐步完成它,并检查您的直觉。如果您越过一条线但没有得到您期望的结果,那么可能是时候开始考虑一个问题,该问题将焦点吸引到该线。

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

【讨论】:

  • 措辞非常好@HostileFork,我认为“char * string[100]”读取,字符指针数组,但我不记得你是否必须这样做C。应该与我的直觉一致,你在 C++ 中处理 char 数组的方式与 C 相同。但我现在对将来如果我在编译时遇到问题如何自己提出问题有了更好的理解。
猜你喜欢
  • 1970-01-01
  • 2015-02-23
  • 2013-04-30
  • 1970-01-01
  • 2022-06-10
  • 2013-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多