我正在为LeetCode的“保护IP地址”发布两种解决方案。如果你想复习,请看。谢谢!
给定有效(IPv4) IP地址,返回该IP地址的防御版本。
一个被破坏的IP地址取代了每一个句点。加上"..。“。
Input: address = "1.1.1.1"
Output: "1[.]1[.]1[.]1"Input: address = "255.100.50.0"
Output: "255[.]100[.]50[.]0"#include <stdio.h>
#include <stdlib.h>
static const char* defangIPaddr(
char* address
) {
char* ipv4_memory = calloc(1, sizeof("###[.]###[.]###[.]###"));
char* defanged = ipv4_memory;
for (char* character = address; *character; character++) {
if (*character == '.') {
*ipv4_memory++ = '[';
*ipv4_memory++ = '.';
*ipv4_memory++ = ']';
} else {
*ipv4_memory++ = *character;
}
}
return defanged;
}
int main() {
printf ("%s \n", defangIPaddr("1.1.1.1"));
printf ("%s \n", defangIPaddr("255.100.50.0"));
return 0;
}#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char* defangIPaddr(
const char* address
) {
char* cloned_address = NULL;
cloned_address = strdup(address);
char* ipv4_memory = calloc(1, sizeof("###[.]###[.]###[.]###"));
char* defanged = ipv4_memory;
for (char* character = cloned_address; *character; character++) {
if (*character == '.') {
*ipv4_memory++ = '[';
*ipv4_memory++ = '.';
*ipv4_memory++ = ']';
} else {
*ipv4_memory++ = *character;
}
}
return defanged;
}
int main() {
printf ("%s \n", defangIPaddr("1.1.1.1"));
printf ("%s \n", defangIPaddr("255.100.50.0"));
return 0;
}发布于 2020-10-24 03:34:56
注意内存分配和释放。在这两种情况下,defangIPaddr都会将一个const char *返回给堆分配的内存,调用者需要释放这个内存.但是它不能被释放,因为free期望一个非const void*作为它的参数。
将堆的所有权分配给调用方的函数应该(A)返回char*,而不是const char*,(B)应该有明确的文档记录。
在代码2中,不仅泄漏返回的指针,还泄漏strdup'ed原始指针,没有理由在这里调用strdup。
你想要的只是
char *defangIPaddr(const char *address) {
char *defanged = calloc(sizeof("###[.]###[.]###[.]###"), 1);
char *q = defanged;
for (const char *p = address; *p != '\0'; ++p) {
if (*p == '.') {
*q++ = '[';
*q++ = '.';
*q++ = ']';
} else {
*q++ = *p;
}
}
return defanged;
}我把你的名字character和ipv4_memory缩短为p和q。我的p是“指针”的意思;它根本不是一个字符,所以character是一个误导性的名字。q仅仅是继p之后出现的东西。
您将参数以错误的顺序传递给calloc。在实践中,这并不重要,但让它正确是容易的和免费的。如果你不确定一个接口,检查手册页。
在您的原始代码中,您执行了以下操作:
char* cloned_address = NULL;
cloned_address = strdup(address);这是一种冗长的写作方式
char* cloned_address = strdup(address);始终初始化您的变量--但是将它们初始化到正确的值!不要初始化一个无稽之谈或垃圾值,然后在其上分配正确的值;只要用正确的值开始初始化即可。
sizeof("###[.]###[.]###[.]###")是计算最大可能长度的一种稍微狡猾的方法。最好只分配3*strlen(address)+1字节,这样即使调用者传入".................."作为它们的输入,也不可能发生缓冲区溢出。
或者,您可以精确地计算正确的缓冲区长度和malloc。
int len = 0;
for (const char *p = address; *p != '\0'; ++p) {
len += (*p == '.') ? 3 : 1;
}
char *defanged = calloc(len+1, 1);
[...]考虑提交一个if (defanged == NULL) return NULL;,以防分配失败。
发布于 2020-10-24 17:03:10
下面是我对这个问题的看法,这个函数接受任何字符串长度,并且只分配足够的内存:
//#include <malloc/_malloc.h>
#include <stdlib.h> // malloc, free
#include <assert.h> // assert
#include <stdio.h> // printf, fprintf
/**
* "Defangs" a string by replacing all `.` with `[.]`.
*
* @param str The string to defang
* @return A pointer to a heap-allocated, defanged version of the string. The
* pointer may be `NULL` if the allocation failed. The caller is responsible for
* freeing the pointed-to memory (via `free()`) when they are done with it.
*/
char* defang(const char* str) {
size_t str_len = 0; // without null terminator
size_t new_len = 1; // with null terminator
for (const char* c = str; *c; c++) {
str_len++;
if (*c == '.') {
new_len += 3;
} else {
new_len++;
}
}
char* new = malloc(new_len);
if (new) {
char* ptr = new;
for (size_t i = 0; i < str_len; i++) {
const char* c = &str[i];
if (*c == '.') {
*ptr++ = '[';
*ptr++ = '.';
*ptr++ = ']';
} else {
*ptr++ = *c;
}
}
*ptr++ = 0;
assert(ptr - new == new_len);
}
return new;
}
int main() {
char* defanged1 = defang("1.1.1.1");
if (defanged1) {
printf("%s\n", defanged1);
free(defanged1);
} else {
fprintf(stderr, "Failed to allocate memory for defanged1\n");
return 1;
}
char* defanged2 = defang("255.100.50.0");
if (defanged2) {
printf("%s\n", defanged2);
free(defanged2);
} else {
fprintf(stderr, "Failed to allocate memory for defanged2\n");
return 1;
}
return 0;
}当内存无法分配时,它会向调用方返回一个空指针,以允许它们处理这种情况,而不是试图继续并立即导致分段错误。
此外,该函数有一个文档注释,它准确地解释了它所做的事情、需要做的事情、返回的内容以及对调用方的期望。我认为,这四个要素对任何文件都是必不可少的。
然后,包含的main函数是一个示例,说明如何使用defang函数,如果内存被分配,则释放内存,如果没有释放内存,则会出现错误消息。
可以随意查看这段代码,作为如何应用其他人给出的建议的示例。
https://codereview.stackexchange.com/questions/251077
复制相似问题