簡體   English   中英

在C中修改const char *

[英]Modify const char * in C

我正在練習面試。 Im當前遇到的問題是反轉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);
}

當您傳遞參數時,該函數將獲得一個副本。 str_const = str; 分配給該副本。 您可以將指針傳遞給指針,以能夠在函數之外更改指針的值,但是您正在將字符串副本分配在堆棧上,因此一旦離開了reverse_const的范圍,字符串副本將變為無效,因此這里沒有道理。

如果您想讓字符串副本在reverse_const的末尾reverse_const下來,請使用malloc分配數組,或者使用strdup進行分配和復制。 您必須以某種方式返回通過malloc malloc'ed指針(通過指向指針參數的指針的返回值),然后調用者將有責任在完成malloc分配的內存后free它。

您需要編寫函數,以便有某種方式返回修改后的參數。

一種這樣的解決方案是通過引用傳遞

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 數組無法以這種方式在C語言中傳回,因為它們存在於堆棧中,並在函數退出時銷毀。

每當長時間運行的程序使用malloc ,在代碼中的某處確實應該有一個匹配的free ,否則您將發生內存泄漏。 這很痛苦,但是所有C程序員都必須掌握一些東西。

如果要在main()返回反轉的str2 ,則需要將足夠大小的緩沖區傳遞給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的指針返回給main() str2 這通常是您期望看到的。 如果您有任何疑問,請告訴我:

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

這里的問題是您修改了傳遞給reverse_const的參數,但是C中的參數是按值傳遞的這意味着它們已被復制。 你在功能修改該變量是原始指針的副本 ,改變副本當然不會改變原來的。

C沒有此處需要的按引用傳遞 ,但是可以通過使用指針進行模擬 ,對於函數,您需要將指針傳遞給指針,然后使用解引用運算符*修改指向的指針指針指向該函數,並在調用該函數時使用地址運算符&

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM