(免責宣告:這不是一個完整的練習,因為我必須完成它,但是這部分代碼發生了錯誤)
我做了這個練習來練習記憶體分配。
創建一個函式,它接受一個 url(一個 C 字串)并回傳網站的名稱(帶有“www.”和擴展名)。例如,給定 wikipedia 的鏈接“http://www.wikipedia.org/”,它必須僅回傳另一個字串中的“www.wikipedia.org”(在堆中動態分配)。
這就是我到目前為止所做的:做一個 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 回圈,程式就會結束。(已解決)我意識到最好洗掉 if (i <= 6) 并編輯 for 回圈起點。現在 for 回圈從 i = 7 開始。
(2) 另一件事:我選擇在使用時創建另一個指標realloc,因為我必須檢查是否存在記憶體泄漏。這是一個好習慣嗎?還是我應該做其他事情?
編輯:洗掉 if-check 后,我看到這個 realloc (在除錯程序中觸發了一個斷點)。
uj5u.com熱心網友回復:
您的代碼中有多個問題:
url[i] != "/"不正確,是型別不匹配。您應該將字符url[i]與字符常量'/'而不是字串文字進行比較"/"。char *s = realloc(str, sizeof(char) 1);僅重新分配到大小 2,而不是當前長度加 1。您不增加指標,也不使用索引變數。
而不是使用
mallocandrealloc,您應該首先計算服務器名稱的長度并直接分配具有正確大小的陣列。
這是一個修改后的版本:
#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] = '\0';
}
return p;
}
uj5u.com熱心網友回復:
分配沒有說回傳的字串必須是最小的,并且用于 URL 的記憶體量是最小的。
基于chqrlie的解決方案,我首先找到域名的開頭(跳過協議部分),復制字串的其余部分,然后截斷結果。大致:
char *prot[] = { "http://", "https://" };
for( int i=0; i < 2; i ) {
if( 0 == strncmp(url, http, strlen(prot)) )
s = strlen(http);
break;
}
}
char *output = strdup(s);
if( output ) {
size_t n = strcspn(output, "/:");
output[n] = '\0';
}
return output;
回傳的指標仍然可以被呼叫者釋放,所以總的“浪費”空間僅限于被截斷的 URL 的尾隨部分。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/386853.html
