2016-07-15 45 views
1

我一直在試圖找出像Python的拼接這樣的子字符串方法, '你好'[2:4]。在C中切片與Python比較

OLD:指針newtoret(返回)是相同的,而是存儲在hello的時候,它有一個新的地址。有沒有辦法保持地址並打印出來?

NEW:將字符放入緩衝區的最佳方法是什麼?

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

//char * substr(char *str, int start, int end); 
//void substr(char *str, int start, int end); 
void get_substr(char *str, int start, int end, char *buffer); 

int main() { 
    char word[] = "Clayton"; 
    char buffer[15]; 
    printf("buffer is now %s",get_substr(word,2,5,buffer); 
    return 0; 
} 


void get_substr(char *str, int start, int end, char *buffer) { 
    int length = end - start; 
    printf("length %d\n",length); 
    //char buffer[length]; //init normal array  
    //assign values from *str 
    int i; 
    for (i = 0; i < length; i++) { 
     buffer[i] = *(str+i+start); 
    } 
} 


//char * substr(char *str, int start, int end) { 
/* char * substr(char *str, int start, int end) { 
    int length = end - start; 
    printf("length %d\n",length); 
    char buffer[length]; //init normal array  
    //assign values from *str 
    int i; 
    for (i = 0; i < length; i++) { 
     buffer[i] = *(str+i+start); 
     printf("i=%d buffer[i]=%c ptr=%c\n",i,buffer[i],*(str+i+start)); 
    } 
    //add endline if not present 
    if (buffer[length] != '\0') { 
     buffer[length] = '\0'; 
     printf("buffer[%d] is %c\n",length,buffer[length]); 
     printf("0 added\n"); 
    } 
    printf("buffer %s %p\n",buffer,buffer); 
    printf("len(buffer) is %d\n",strlen(buffer)); 
    char *toret; 
    toret = (char*) &buffer; 
    printf("toret %s %p\n",toret,toret); 
    return toret; 
} */ 

對不起,這可能是重複的,但我無法找到這個域上的相同例子。 我是新來的C!

+0

不要錯過,但是你的代碼充斥着明顯的錯誤,回答你的問題是完全不可能的。使用'new'作爲變量名稱?返回一個堆棧分配變量的地址?訪問長度爲* n *的0索引數組的索引* n *混淆'sizeof'與字符串的長度? – spectras

+1

@spectras:在C中不鼓勵使用'new'作爲變量名(例如,我不鼓勵它,或者使用任何不是C關鍵字的其他C++關鍵字),但問題是標記爲C,而不是C++,並且C編譯器_must_接受'new'作爲有效的變量名稱。如果不是,它不是C編譯器,但可能是僞裝的C++編譯器。 (這不是聲明代碼是好的 - 它不是!這只是一個觀察結果,'new'是C代碼中通用的有效名稱。) –

+0

@spectras感謝您在查看了一些[strncpy]( http://stackoverflow.com/a/14042078/5645103)s我的代碼似乎現在工作 –

回答

4

您不能將指針返回到在函數中本地聲明的緩衝區。該內存駐留在堆棧上,下一個函數調用可能會覆蓋該內存。如果要將其返回給調用函數,則需要使用malloc來創建所需的內存,然後在完成之後需要使用free進行清理。

也就是說,在被調用的函數中分配內存並返回它通常是不明智的。爲了防止調用者忘記清理內存,我建議請求將子字符串複製到其中的緩衝區。

我會改變函數簽名返回一個空白,並採取額外的緩衝到其子將被複制:

void get_substr(char *str, int start, int end, char *buffer) 

然後,在您的通話功能,你可以這樣做:

int main() { 
    char name[] = "Clayton"; 
    char buffer[10]; 

    get_substr(name, 0, 3, buffer); 
    /* "Cla" now copied into buffer */ 

    printf("%s", buffer); 
    return 0; 
} 

或者,由於這是一個子字符串函數,並且您知道該字符串完全包含在原始字符串中,所以您可以返回字符串長度的大小和一個指向字符串開頭的指針(在原始字符串內)。

您的簽名看起來是這樣的:

int substr(char *str, int start, int end, char *substr) 

和使用情況看起來是這樣的:

int main() { 
    char name[] = "Clayton"; 
    char *substr; 
    int substr_len = substr(name, 0, 3, substr); 
    /* substr now points to name, substr_len = 3 */ 

    /* Copy substring to buffer to print */ 
    char buffer[10]; 
    strncpy(buffer, substr, substr_len); 

    printf("%s", buffer); 
    return 0; 
} 
+0

謝謝,我的代碼和前者差不多嗎? –

+0

@ClaytonWahlstrom我不知道你的代碼是否正確實現。我首先驗證'start> = 0'和'start <= end',並使用'strlen'來驗證'end'參數(以確保它不會超過字符串的末尾)。如果你採用第一種方法,你應該使用'strncpy'將字符複製到緩衝區。如果你使用第二種方法,你可以計算substr_len並將substr指針設置爲str + start。 – Darthfett

1

沒有測試,但類似的東西如下應該工作:

char name[] = "Clayton"; 
int slice_begin = 0, slice_end = 3; 
printf("%.*s", slice_end - slice_begin, name + slice_begin); 

更新基於這種技術,你可以用兩個變量來表示一個字符串:一個指向片的開始,和一個表示長度的整數。

+0

它在函數中如何工作? (或者它是否需要?) –

+0

@ClaytonWahlstrom這一切都取決於你的需要。我認爲這太簡單了,不是我自己的一個函數,但是如果你希望它更加面向對象,你可以將所有東西都包含在一個結構體(指針和長度)中,並創建一個函數來管理結構體。 – xuhdev

1

既然你想模仿Python的片,我會去的東西,如:

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

char *slice(char *string, int start, int stop, int step) { 
    size_t string_length = ceil(fabs((stop - start)/(float) step)); 

    char *new_string = malloc(string_length + 1); 

    for (int i = start, j = 0; j < string_length; i += step, j++) { 
     new_string[j] = string[i]; 
    } 

    new_string[string_length] = '\0'; 

    return new_string; 
} 

int main() { 
    char *name = "Clayton"; 

    char *hello = slice(name, 0, 3, 1); 

    printf("%s\n", hello); 

    free(hello); 

    char *letters = "abcdefghijklmnopqrstuvwxyz"; 

    char *goodbye = slice(letters, strlen(letters) - 1, -1, -1); 

    printf("%s\n", goodbye); 

    free(goodbye); 

    return 0; 
} 

帶輸出:

Cla 
zyxwvutsrqponmlkjihgfedcba