减少字符串的大小
reduce the size of a string
(免责声明:这不是一个完整的练习,因为我必须完成它,但是这部分代码出现错误)
我做这个练习是为了练习内存分配。
create a function that takes an url (a C string) and returns the name of the website (with "www." and with the extension).
for example, given wikipedia's link, "http://www.wikipedia.org/", it has to return only "www.wikipedia.org" in another string (dynamically allocated in the heap).
这是我目前所做的:
做一个for循环,当“i”大于6时,开始复制另一个字符串中的每个字符,直到达到“/”。
我需要分配另一个字符串,然后重新分配它。
这是我目前的尝试:
char *read_website(const char *url) {
char *str = malloc(sizeof(char));
if (str == NULL) {
exit(1);
}
for (unsigned int i = 0; url[i] != "/" && i > 6; ++i) {
if (i <= 6) {
continue;
}
char* s = realloc(str, sizeof(char) + 1);
if (s == NULL) {
exit(1);
}
*str = *s;
}
return str;
}
int main(void) {
char s[] = "http://www.wikipedia.org/";
char *str = read_website(s);
return 0;
}
(1) 通过逐行调试,我注意到一旦达到 for-loop 程序就结束了。
(2) 另一件事:我选择在使用 realloc
时创建另一个指针,因为我必须检查是否存在内存泄漏。这是一个好习惯吗?或者我应该做点别的吗?
您的代码中存在多个问题:
url[i] != "/"
不正确,是类型不匹配。您应该将字符 url[i]
与字符常量 '/'
进行比较,而不是将字符串文字 "/"
.
char *s = realloc(str, sizeof(char) + 1);
仅重新分配给大小 2,而不是当前长度加 1。
你不增加指针,也不使用索引变量
而不是使用malloc
和realloc
,您应该首先计算服务器名称的长度并直接分配具有正确大小的数组。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *read_website(const char *url) {
// skip the protocol part
if (!strncmp(url, "http://", 7))
url += 7;
else if (!strncmp(url, "https://", 8))
url += 8;
// compute the length of the domain name, stop at ':' or '/'
size_t n = strcspn(url, "/:");
// return an allocated copy of the substring
return strndup(url, n);
}
int main(void) {
char s[] = "http://www.wikipedia.org/";
char *str = read_website(s);
printf("%s -> %s\n", s, str);
free(str);
return 0;
}
strndup()
是许多系统上可用的 POSIX 函数,它将成为下一版本 C 标准的一部分。如果它在您的目标上不可用,这里是一个简单的实现:
char *strndup(const char *s, size_t n) {
char *p;
size_t i;
for (i = 0; i < n && s[i]; i++)
continue;
p = malloc(i + 1);
if (p) {
memcpy(p, s, i);
p[i] = '[=11=]';
}
return p;
}
赋值并没有说返回的字符串必须是最小大小,并且用于 URLs 的内存量是最小的。
基于 的解决方案,我首先找到域名的开头(跳过协议部分),复制字符串的其余部分,然后截断结果。大致:
char *prot[] = { "http://", "https://" };
for( int i=0; i < 2; i++ ) {
if( 0 == strncmp(url, http, strlen(prot)) )
s += strlen(prot);
break;
}
}
char *output = strdup(s);
if( output ) {
size_t n = strcspn(output, "/:");
output[n] = '[=10=]';
}
return output;
返回的指针仍然可以被调用者释放,因此总的“浪费”space仅限于被截断的尾部URL。
(免责声明:这不是一个完整的练习,因为我必须完成它,但是这部分代码出现错误)
我做这个练习是为了练习内存分配。
create a function that takes an url (a C string) and returns the name of the website (with "www." and with the extension). for example, given wikipedia's link, "http://www.wikipedia.org/", it has to return only "www.wikipedia.org" in another string (dynamically allocated in the heap).
这是我目前所做的: 做一个for循环,当“i”大于6时,开始复制另一个字符串中的每个字符,直到达到“/”。 我需要分配另一个字符串,然后重新分配它。
这是我目前的尝试:
char *read_website(const char *url) {
char *str = malloc(sizeof(char));
if (str == NULL) {
exit(1);
}
for (unsigned int i = 0; url[i] != "/" && i > 6; ++i) {
if (i <= 6) {
continue;
}
char* s = realloc(str, sizeof(char) + 1);
if (s == NULL) {
exit(1);
}
*str = *s;
}
return str;
}
int main(void) {
char s[] = "http://www.wikipedia.org/";
char *str = read_website(s);
return 0;
}
(1) 通过逐行调试,我注意到一旦达到 for-loop 程序就结束了。
(2) 另一件事:我选择在使用 realloc
时创建另一个指针,因为我必须检查是否存在内存泄漏。这是一个好习惯吗?或者我应该做点别的吗?
您的代码中存在多个问题:
url[i] != "/"
不正确,是类型不匹配。您应该将字符url[i]
与字符常量'/'
进行比较,而不是将字符串文字"/"
.char *s = realloc(str, sizeof(char) + 1);
仅重新分配给大小 2,而不是当前长度加 1。你不增加指针,也不使用索引变量
而不是使用
malloc
和realloc
,您应该首先计算服务器名称的长度并直接分配具有正确大小的数组。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *read_website(const char *url) {
// skip the protocol part
if (!strncmp(url, "http://", 7))
url += 7;
else if (!strncmp(url, "https://", 8))
url += 8;
// compute the length of the domain name, stop at ':' or '/'
size_t n = strcspn(url, "/:");
// return an allocated copy of the substring
return strndup(url, n);
}
int main(void) {
char s[] = "http://www.wikipedia.org/";
char *str = read_website(s);
printf("%s -> %s\n", s, str);
free(str);
return 0;
}
strndup()
是许多系统上可用的 POSIX 函数,它将成为下一版本 C 标准的一部分。如果它在您的目标上不可用,这里是一个简单的实现:
char *strndup(const char *s, size_t n) {
char *p;
size_t i;
for (i = 0; i < n && s[i]; i++)
continue;
p = malloc(i + 1);
if (p) {
memcpy(p, s, i);
p[i] = '[=11=]';
}
return p;
}
赋值并没有说返回的字符串必须是最小大小,并且用于 URLs 的内存量是最小的。
基于
char *prot[] = { "http://", "https://" };
for( int i=0; i < 2; i++ ) {
if( 0 == strncmp(url, http, strlen(prot)) )
s += strlen(prot);
break;
}
}
char *output = strdup(s);
if( output ) {
size_t n = strcspn(output, "/:");
output[n] = '[=10=]';
}
return output;
返回的指针仍然可以被调用者释放,因此总的“浪费”space仅限于被截断的尾部URL。