malloc中的反向字符串

malloc中的反向字符串,c,string,malloc,strcpy,strcat,C,String,Malloc,Strcpy,Strcat,我需要在这个问题中定义一个“单词”,它是任何不包含空格或空字符的字符序列。 例如,字符串“Hello World”将包含两个单词。然而,一个单词实际上可能是空的 i、 例如,零字符。 一个句子将是由一个空格字符分隔的一系列单词。所以,“Hello World”将是一个 两个单词的句子。ReverseSentence的目标是根据单词来反转句子。 现在,我有一个错误,程序继续调用函数并打印a1到a5。到达a5时,程序似乎中止并转储内核。如果我用空格替换空白,它将读取以前的输入,并根据空格数进行替换。

我需要在这个问题中定义一个“单词”,它是任何不包含空格或空字符的字符序列。 例如,字符串
“Hello World”
将包含两个单词。然而,一个单词实际上可能是空的 i、 例如,零字符。 一个句子将是由一个空格字符分隔的一系列单词。所以,
“Hello World”
将是一个 两个单词的句子。
ReverseSentence
的目标是根据单词来反转句子。 现在,我有一个错误,程序继续调用函数并打印a1到a5。到达a5时,程序似乎中止并转储内核。如果我用空格替换空白,它将读取以前的输入,并根据空格数进行替换。 我哪里做错了

反向内容.c

#include <stdlib.h>  /* malloc */
#include <string.h>  /* strcat, strcpy */

void ReverseSentence(char *str)
{
    char *newSentence;
    int i, j, start, len;
    /* contains the string length of the input */
    len = strlen(str);
    /* position or index in the array */
    start = strlen(str);
    /* malloc */
    newSentence = malloc(len + 1);

    /* loop checks from the right of the sentences */
    for (i = len; i >= 0; i--) {
        /* if index reach the array with a space or zero */
        if (str[i] == ' ' || i == 0) {
            /* allocates memory */
            char *word = malloc((start - i) + 1);
            int c = 0;

            if (i == 0) 
                /* index remains same */
                j = i;
            else
                j = i + 1;

            /* j smaller or equal than the start position */
            for (; j <= start; j++) {
                /*do a incremental*/
                word[c++] = str[j];
            }
            /* hits a null char */
            word[c] = '\0';
            /* string concatenate */
            strcat(newSentence, word);
            /* if index hits a space */
            if (str[i] == ' ')
                strcat(newSentence, " "); /* concatenate space to newSentence */
            else
                strcat(newSentence, "\0");
            start = i - 1;

            /* free memory */
            free(word);
        }
    }
    newSentence[len] = '\0';
    /* string copy */
    /* str is destination, newSentence is the source */
    /* copy new string to original string */
    strcpy(str, newSentence);
    /* free memory */
    free(newSentence);
}
#include <stdio.h>
#include "ReverseSentence.h"

int main()
{
    char a1[] = "Hello World ";
    char a2[] = "abcdefghi ";
    char a3[] = " ";
    char a4[] = "C programming is a dangerous activity";
    char a5[] = "a "; /* a sentence with only empty words */
    ReverseSentence(a1);

    printf("Test case 1:\"%s\"\n", a1); /* prints "World Hello" */
    ReverseSentence(a2);

    printf("Test case 2:\"%s\"\n", a2); /* prints "abcdefghi" */
    ReverseSentence(a3);

    printf("Test case 3:\"%s\"\n", a3); /* prints "" */

    ReverseSentence(a4);
    printf("Test case 4:\"%s\"\n", a4); /* prints "activity dangerous a is pro Cgramming" */

    ReverseSentence(a5);
    printf("Test case 5:\"%s\"\n", a5); /* prints " " */

    return 0;
}

你的代码不安全。您从不初始化
newSentence
,因为
malloc()
只分配内存,而不初始化内存(与
calloc()
相反)。因此,您将从一个垃圾句开始,在这里附加一些新的内容(
strcat()
)。根据垃圾的不同,即使在分配的内存中也可能没有0,您可以访问一些未分配的内存区域。

除了Matthias的回答:您没有分配足够的内存之外,我只是做了一个粗略的猜测,并在传递给
malloc
的参数中添加了1

newSentence = malloc(len + 2);   // +2 instead of +1

现在它不再崩溃了。所以这里肯定有缓冲区溢出


我现在并不假装程序完全正确。你应该仔细研究一下。你的方法太复杂了。它有几个问题:

  • 您不初始化
    newSentence
    :由于
    malloc
    内存未初始化,因此当您使用
    strcat
    复制其末尾的单词时,将调用未定义的行为。您可以使用
    *newSentence='\0'修复该问题

  • 将单词复制到分配的
    word
    缓冲区时,迭代到并包括
    start
    ,然后在末尾添加一个
    '\0'
    。实际上,最后一个字写的字节太多了(case
    i==0
    )。这将调用未定义的行为

  • strcat(newSentence,“\0”)什么也不做

  • 为找到的每个单词分配缓冲区是浪费时间的,您可以使用
    memcpy
    或简单的
    for
    循环来复制单词

您可以通过以下步骤进行简化:

  • 分配一个缓冲区并将字符串复制到其中
  • 对于字符串中的每个单词,将其复制到目标的末尾,如果不在末尾,则复制其前面的分隔符
  • 释放缓冲区
代码如下:

char *ReverseSentence(char *str) {
    int len = strlen(tmp);    /* length of the string */
    char *tmp = strdup(str);  /* copy of the string */
    int i;        /* index into the copy */
    int j = len;  /* index into the string */
    int n;        /* length of a word */
    for (i = 0; i < len; ) {
        n = strcspn(tmp + i, " ");   /* n is the length of the word */
        j -= n;                      /* adjust destination offset */
        memcpy(str + j, tmp + i, n); /* copy the word */
        i += n;                      /* skip the word */
        if (tmp[i] != '\0') {        /* unless we are at the end */
            j--;
            str[j] = tmp[i];         /* copy the separator */
            i++;
        }
    }
    free(tmp);                       /* free the copy */
    return str;
}
char*ReverseSentence(char*str){
int len=strlen(tmp);/*字符串的长度*/
char*tmp=strdup(str);/*字符串的副本*/
int i;/*索引到副本中*/
int j=len;/*索引到字符串中*/
int n;/*单词的长度*/
对于(i=0;i
新版本的程序中至少有两个问题:

  • 你没有分配足够的内存,你没有考虑零终止符。您应该再分配一个字节

  • 在第一个
    for
    循环中,允许
    i
    变为-1。当
    i
    为零时,循环应该停止:修改
    for
    语句如下:
    for(i=len-1;tr[i]!='&&i>=0;i--)
    。您错误地假设
    str
    缓冲区前面的第一个字节为零,因此
    str[i]!='\0'
    错误。顺便说一句,在
    str
    缓冲区之前访问一个字节会产生未定义的行为

  • 可能还有其他问题


从右到左读取数组,然后在检查命中空格后对单词进行strcat,然后将字符串复制到新的string此处它已与a1崩溃。新版本中至少存在一个问题:
newSentence=malloc(sizeof(char)*strlen(str))
。你没有分配足够的内存,你没有考虑零终止符。您应该再分配一个字节。但还有其他问题。顺便说一句:
sizeof(char)
始终是每个定义的
1
,因此您无需编写它。我还原了上一次编辑:不要覆盖原始帖子,因为这会导致讨论不一致,在最后添加了新版本。不仅不安全,而且错误。在调用
malloc
之后,必须初始化
newSentence
缓冲区,例如
newSentence[0]=0
@michael Walz得到了它。我想出了另一个解决办法。将在Top上编辑我的帖子谢谢你的帮助。我想出了另一个解决办法。将在顶部编辑我的帖子。
char *word = malloc((start - i) + 2);  // +2 instead of +1
char *ReverseSentence(char *str) {
    int len = strlen(tmp);    /* length of the string */
    char *tmp = strdup(str);  /* copy of the string */
    int i;        /* index into the copy */
    int j = len;  /* index into the string */
    int n;        /* length of a word */
    for (i = 0; i < len; ) {
        n = strcspn(tmp + i, " ");   /* n is the length of the word */
        j -= n;                      /* adjust destination offset */
        memcpy(str + j, tmp + i, n); /* copy the word */
        i += n;                      /* skip the word */
        if (tmp[i] != '\0') {        /* unless we are at the end */
            j--;
            str[j] = tmp[i];         /* copy the separator */
            i++;
        }
    }
    free(tmp);                       /* free the copy */
    return str;
}