减少字符串的大小

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。

  • 你不增加指针,也不使用索引变量

  • 而不是使用mallocrealloc,您应该首先计算服务器名称的长度并直接分配具有正确大小的数组。

这是修改后的版本:

#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。