2016-07-15 48 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