【问题标题】:Reversing words in a string using three pointers?使用三个指针反转字符串中的单词?
【发布时间】:2018-05-02 18:22:23
【问题描述】:

我正在尝试反转字符串中的单词,并且我相信我已经编写了正确的逻辑,但是在调试时我开始知道我放入 new_array char 指针变量的值丢失了?而且我似乎不知道为什么?

你能告诉我我犯了什么错误以及可以做些什么来纠正它吗?

#include <stdio.h>

void reverse_words(char *arr, int size) {
    char *ptr = arr;
    char *new_array = (char*)malloc(sizeof(char*) * size);

    while (*ptr != '\0') {
        ptr++;
    }
    ptr--;

    for (int i = size - 1; i >= 0; i--) {
        if (*ptr != ' ') {
            ptr--;
        } else {
            char *temp = ptr;
            temp++;
            //
            // Problem is in this block new_array value is lost when i increment it                                
            while (*temp != ' ' && *temp != '\0') {
                *new_array = *temp;
                new_array++;
                temp++;
            }
            if (i != 0) {
                *new_array = *ptr;
                ptr--;
            }
        }
    }
    *new_array = '\0';
    strcpy(arr, new_array);
    return;
}

int main() {
    char arr[] = "My job is coding";
    int size = sizeof(arr);
    reverse_words(arr, size);
    printf("%s", arr);
    return 0;
}

【问题讨论】:

  • “丢失”是什么意思?
  • 值不存在,我使用 *temp;
  • @user3405439 当循环失败时不要执行 new_array++ bcz new_array 指向 NULL 并且您正在将 NULL 复制到 arr
  • 递增new_array 的代码会更改其值。这就是递增的作用。在以后的代码中,您不能指望new_array 会神奇地恢复到其原始值。顺便说一句:如果您要做的只是将字符串反转到位,则不需要 malloc() 调用。
  • 注意:您不需要分配字符串的副本。您可以就地反转,只交换字符。

标签: c arrays string algorithm pointers


【解决方案1】:

你的代码太复杂,有几个问题:

  • 您分配了太多内存:(char*)malloc(sizeof(char*) * size); 分配了size 倍于指针大小。使用malloc(size); 分配size 字节。
  • 您的指针操作存在错误,
  • 您忘记释放分配的内存,导致内存泄漏。
  • 您不需要传递数组的大小,字符串的长度是通过扫描空终止符来计算的,只需为空终止符分配一个额外的字节。

有一种替代解决方案可以在不分配内存的情况下将字符串中的单词反转:

  • 对于每个单词,反转单词
  • 最后一步:反转字符串

下面是使用实用函数的代码:

#include <stdio.h>

void reverse_mem(char *str, int size) {
    for (int i = 0, j = size; i < --j; i++) {
        char c = str[i];
        str[i] = str[j];
        str[j] = c;
    }
}

void reverse_words(char *arr) {
     for (int i = 0, j = 0;; i = j) {
        for (; str[i] == ' '; i++)
            continue;
        if (str[i] == '\0')
            break;
        for (j = i; str[j] != '\0' && str[j] != ' '; j++)
            continue;
        reverse_mem(str + i, j - i);
    }
    reverse_mem(str, size);
}

int main(void) {
    char arr[] = "My job is coding";
    reverse_words(arr);
    printf("%s\n", arr);
    return 0;
}

【讨论】:

    【解决方案2】:

    由于此语句,您没有得到预期的输出..

    *new_array = *temp; //2nd time new_array is not pointing previous location  so how will you retrieve data 
       new_array++;// you lost previous data bcz pointers no longer holds previous address
    

    当主循环失败时,new_array 指针将指向最后,但它应该保存起始地址。而不是直接增加new_array

    * (new_array + j) =  *temp
    

    我将您的代码修改为 . .

    void reverse_words(char *arr,int size)
    {
            char * ptr = arr;
            char *new_array = (char*)malloc(sizeof(char*) * size);
            printf("initial : %u \n",ptr);
            while(*ptr != '\0')
            {
                    ptr++;
            }
            int j=0;
            ptr--;
            printf("first : %c : %u  \n",*ptr,ptr);
            for(int i = size-1;i >=0;i--)
            {
                    if(*ptr != ' ' ) //&& i!=0)
                    {
                            ptr--;//from last to back
    
                    }
                    else
                    {
                            char * temp = ptr;
                            temp++;
                            while(*temp != '\0' && *temp!=' ')
                            {
                                    new_array[j++]=*temp;
                                    temp++;
    
                            }
                            if(i!=0)
                            {
                                    new_array[j++] = *ptr;
                                    ptr--;
                            }
                    }
    
            }
            new_array[j] = '\0';
            printf("new = %s \n",new_array);
            strcpy(arr,new_array);
    
    }
    

    我希望你知道哪里出了问题,修改first 单词的条件,因为一旦i 变为0,你就没有为此编写任何逻辑。

    根据您的要求我的解决方案

    void reverse_words(char *arr,int size) {
            char *new_array = malloc(size * sizeof(char));
            int i,j,k=0;
            for(i = size-1 ;i >= -1 ; i--) {
                    if(arr[i] ==' ' || i == -1)
                    {
                            for(j=i+1;arr[j]!=' ' && arr[j]!='\0'; j++)
                                    new_array[k++] = arr[j];
                            new_array[k++] = ' ';
                    }
            }
            new_array[k] = '\0';
            strcpy(arr,new_array);
    }
    

    【讨论】:

    • 感谢您的回答,但这不是将连续存储分配给new_array,还是我正在尝试更改new_array的基地址?你能解释一下吗?
    • @user3405439 是的,您正在尝试更改 new_array 的基地址。
    猜你喜欢
    • 1970-01-01
    • 2012-05-05
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    • 2012-06-26
    • 1970-01-01
    相关资源
    最近更新 更多