2015-10-21 112 views
0

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

#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); 
} 
+0

'char str [c_size];'不足以保存长度为'c_size'的* nul-terminated *字符串。 – Kninnug

+0

_我在这里做错了什么?_你没有做任何改变'str2'指向的地方。你已经知道你需要改变它的位置来解决这个问题......但是环境也很重要! 'str_const = str;'对'main()'上下文中的'str2'没有影响。 – mah

+0

“我可以将位置str2点修改为”不是如果该位置是恒定的。指针不是数组或字符串(并且数组不是字符串)。请阅读一本好C书中的指针,数组和字符串文字。 – Olaf

回答

2

如果要反转str2main(),则要么需要一个足够大缓冲器传递给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 

Returnin克将指针

您有更多的选择,指针返回str分配给str2main()。这更多的是你通常期望看到的。如果您有任何问题,请告知我们:

char *reverse_const2 (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); 

    return str; 
} 

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); 

    str2 = reverse_const2 ((const char **)&str2); 

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

    free (str2); 

    return 0; 
} 
+0

如果你将指针返回到反向字符串,而不是覆盖'str2',我想'reverse_const'函数更多。 –

+0

同意,我只是在使用函数的形式,并不知道这是否会改变。 –

+0

@JohnBode - 添加返回作为第二个例子。 –

1

这里的问题是,你修改传递到reverse_const的说法,但在C参数通过值传递这意味着它们被复制。你在函数中修改的变量是拷贝的原始指针,改变拷贝当然不会改变原来的。

C没有通通过这里需要参考,但它可以通过使用指针,在函数的情况下,模拟你需要一个指针传递到指针,然后使用解引用运算符*修改指向指针的指针,并在调用函数时使用运算符&的地址。

2

当您通过参数传递时,函数会获得副本。 str_const = str;分配给该副本。你可以传递一个指向指针的指针,以便能够改变函数外部的指针值,但是你要在堆栈中分配字符串副本,因此一旦离开reverse_const的范围,字符串副本就会失效,这里没有意义。

如果你想有一个字符串拷贝生存的reverse_const结束,分配阵列malloc或两者都做了分配,并与strdup复制。您必须以某种方式返回malloc'ed指针(通过指向指针参数的指针的返回值),然后调用者将负责free,即malloc'一旦完成它就执行内存。

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程序员都必须掌握的东西。

+0

任何使用内存分配而不提供释放该分配的细节的建议对读者来说通常是危险的(他们可能不了解动态分配足以查看完整需求)。 – mah

+1

公平点,现在固定。 – ams