C 中的切片与 Python 相比
Slicing in C compared with Python
我一直在想像Python的拼接那样的子串方法,例如'hello'[2:4].
OLD:指针new
和toret
(指向return)是相同的,但是当存储在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] != '[=11=]') {
buffer[length] = '[=11=]';
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 新手!
未测试,但类似如下的内容应该有效:
char name[] = "Clayton";
int slice_begin = 0, slice_end = 3;
printf("%.*s", slice_end - slice_begin, name + slice_begin);
Update 基于这个技巧,你可以使用两个变量来表示一个子字符串:一个指向切片开始的指针,和一个表示长度的整数。
您不能 return 指向在函数内局部声明的缓冲区的指针。该内存驻留在堆栈中,下一个函数调用可能会覆盖该内存。如果要将 return 分配给调用函数,则需要使用 malloc
创建所需的内存,完成后需要使用 free
进行清理有了它。
也就是说,在被调用函数中分配内存并 return 它通常是不明智的。为了防止调用者忘记清理内存,我建议请求一个缓冲区,子字符串将被复制到其中。
我会将函数签名更改为 return 空值,并占用一个额外的缓冲区,子字符串将被复制到其中:
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;
}
或者,由于这是一个子字符串函数,并且您知道该字符串完全包含在原始字符串中,您可以 return 字符串长度的大小和指向字符串开头的指针(在原始字符串内)。
您的签名可能如下所示:
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;
}
既然你想模仿 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] = '[=10=]';
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
我一直在想像Python的拼接那样的子串方法,例如'hello'[2:4].
OLD:指针new
和toret
(指向return)是相同的,但是当存储在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] != '[=11=]') {
buffer[length] = '[=11=]';
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 新手!
未测试,但类似如下的内容应该有效:
char name[] = "Clayton";
int slice_begin = 0, slice_end = 3;
printf("%.*s", slice_end - slice_begin, name + slice_begin);
Update 基于这个技巧,你可以使用两个变量来表示一个子字符串:一个指向切片开始的指针,和一个表示长度的整数。
您不能 return 指向在函数内局部声明的缓冲区的指针。该内存驻留在堆栈中,下一个函数调用可能会覆盖该内存。如果要将 return 分配给调用函数,则需要使用 malloc
创建所需的内存,完成后需要使用 free
进行清理有了它。
也就是说,在被调用函数中分配内存并 return 它通常是不明智的。为了防止调用者忘记清理内存,我建议请求一个缓冲区,子字符串将被复制到其中。
我会将函数签名更改为 return 空值,并占用一个额外的缓冲区,子字符串将被复制到其中:
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;
}
或者,由于这是一个子字符串函数,并且您知道该字符串完全包含在原始字符串中,您可以 return 字符串长度的大小和指向字符串开头的指针(在原始字符串内)。
您的签名可能如下所示:
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;
}
既然你想模仿 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] = '[=10=]';
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