修改C中的const char *

时间:2015-10-21 15:36:29

标签: c pointers pass-by-reference

我正在练习面试。我目前坚持的问题是在C中反转一个常量字符串。我知道因为str2是const,我可以修改str2指向的位置,但不能修改它的值。我有一个名为reverse_const的函数。它会将const char * str_const反转并打印出来。但是,当我尝试从main方法反转后打印st2时,字符串不再反转。它就像reverse_const()暂时改变了str2的内存位置。我在这里做错了什么?

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

void reverse(char *str){
    int c_size = strlen(str);
    char *c_begin = str, *c_end = str + (c_size - 1);

    int i;
    for(i = 0; i < c_size / 2; i++){
        *c_begin ^= *c_end;
        *c_end ^= *c_begin;
        *c_begin ^= *c_end;

        c_begin++;
        c_end--;
    }
}

void reverse_const(const char *str_const){
    int c_size = strlen(str_const);
    char str[c_size];
    strcpy(str, str_const);
    char *c_begin = str, *c_end = str + (c_size - 1);

    int i;
    for(i = 0; i < c_size / 2; i++){
        *c_begin ^= *c_end;
        *c_end ^= *c_begin;
        *c_begin ^= *c_end;

        c_begin++;
        c_end--;
    }

    str_const = str;
    printf("%s\n", str_const);
}

int main(){
    char str1[] = "Indiana";
    char *str2 = "Kentucky";
    printf("TESTS:\nString 1 pre-reversal: %s\n", str1);
    reverse(str1);
    printf("String 1 post-reversal: %s\n", str1);
    printf("Constant string 2 pre-reversal: %s\n", str2);
    reverse_const(str2);
    printf("Constant string 2 post-reversal: %s\n", str2);
}

4 个答案:

答案 0 :(得分:2)

当你通过参数传递时,函数会获得一个副本。 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input type='number' id='Amount' value='Amount convert' step='0.01'> <input type='button' id='Validate' value='Check decimals'> <output></output>分配给该副本。您可以将指针传递给指针,以便能够在函数外部更改指针的值,但是您要在堆栈上分配字符串副本,因此一旦离开{{1}的范围,字符串副本就会变为无效所以这在这里没有意义。

如果您想要一个在str_const = str;结束时保留的字符串副本,请使用reverse_const分配数组,或者使用reverse_const进行分配和复制。您必须以某种方式返回malloc指针(通过指针指向参数的返回值),然后调用者将负责strdup malloc'ed'内存一次free它已经完成了。

答案 1 :(得分:2)

您需要编写函数,以便有一些方法可以返回修改后的参数。

其中一个解决方案是传递引用

void reverse_const(const char **str_const){
    const char *in = *str_const;
    char *out = malloc(strlen(in)+1);

    /* write to out */

    *str_const = out;
}

但更好的方法是使用返回值:

char *reverse_const(const char *str_const){
    const char *in = str_const;
    char *out = malloc(strlen(in)+1);

    /* write to out */

    return out;
}

返回类型可以是const char *,但这是一个不必要的限制,因为您知道可以安全地修改返回的字符串。

请注意,这两个示例均使用malloc。数组不能以这种方式传回数组,因为它们存在于堆栈中并在函数退出时被销毁。

每当一个长时间运行的程序使用malloc时,代码中的某个地方确实应该匹配free,否则你会发生内存泄漏。这是一种痛苦,但所有C程序员都必须掌握它。

答案 2 :(得分:2)

如果您希望将if(!(errorList.Cotains(1) || errorList.Contains(-1)))反转回str2,则需要将足够大的缓冲区传递给main()以保留反向字符串,否则您需要动态分配在reverse_const中存储它(一个局部可变长度数组不会这样做):

reverse_const

<强>输出

#include <stdlib.h>
...
void reverse_const (const char **str_const)
{
    int c_size = strlen (*str_const);
    char *str = calloc (c_size + 1, sizeof *str);
    strcpy (str, *str_const);
    char *c_begin = str, *c_end = str + (c_size - 1);

    int i;
    for (i = 0; i < c_size / 2; i++) {
        *c_begin ^= *c_end;
        *c_end ^= *c_begin;
        *c_begin ^= *c_end;

        c_begin++;
        c_end--;
    }

    *str_const = str;
    printf ("%s\n", *str_const);
}

int main (void) {

    char str1[] = "Indiana";
    char *str2 = "Kentucky";

    printf ("TESTS:\nString 1 pre-reversal: %s\n", str1);

    reverse (str1);

    printf ("String 1 post-reversal: %s\n", str1);
    printf ("Constant string 2 pre-reversal: %s\n", str2);

    reverse_const ((const char **)&str2);

    printf ("Constant string 2 post-reversal: %s\n", str2);

    free (str2);

    return 0;
}

返回指针

您还有一个选项可以将指针返回$ ./bin/revconststr TESTS: String 1 pre-reversal: Indiana String 1 post-reversal: anaidnI Constant string 2 pre-reversal: Kentucky ykcutneK Constant string 2 post-reversal: ykcutneK 以分配到str中的str2。这是您通常希望看到的更多内容。如果您有任何问题,请与我联系:

main()

答案 3 :(得分:1)

这里的问题是您修改传递给reverse_const的参数,但C中的参数按值传递意味着它们被复制。您在函数中修改的变量是原始指针的副本,更改副本当然不会更改原始。

C没有通过引用传递,但是它可以通过使用指针进行模拟,对于你的函数,你需要传递一个指向指针的指针,然后使用解除引用运算符*来修改指针指向的指针,并在调用函数时使用地址运算符&