libft再実装 mistake集
ft_strlcpy
#include "libft.h"
size_t ft_strlcpy(char *dest, const char *src, size_t size)
{
size_t i;
size_t src_len;
src_len = ft_strlen(src);
i = 0;
if (size == 0)
return (src_len);
while (src[i] && i < size - 1)
{
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return (src_len);
}
どうせstr_len返すからーとおもって最後のヌル文字を忘れがち。
あくまでコピーされた文字列をつくるのが目的。
最後のヌル文字をつけたらsize == 0の処理がないと、一個もコピーしないはずなのに'\0'がはいってしまうから注意。
ft_strncmp
間違えたver
#include "libft.h"
int ft_strncmp(char *str1, char *str2, size_t size)
{
size_t i;
i = 0;
while ((str1[i] && str2[i]) && (i < size))
{
if (str1[i] != str2[i])
return ((unsigned int ) str1[i] - (unsigned int) str2[i]);
i++;
}
return ((unsigned int ) str1[i] - (unsigned int) str2[i]);
}
まず文字列比較なのでconstにしておくこと。if (str1[i] != str2[i])で比較しているけどふつうにこれchar型で負の数になったときにだめだからこれもキャストする必要があった。
今までunsigned int で比較していたけど厳密にはだめみたい。
unisned int だと、、
str1[i] = -1 → unsigned int にキャスト → 4294967295(大きすぎ!)
str2[i] = 1 → unsigned int にキャスト → 1
結果:(4294967294)になる。
このため(unsigned char)で比較する必要があった。
またi = sizeの場合は最後のreturnの処理にいれたらインデックスを超えてしまうから0を返すように分ける。
ft_memchr
バイト列の中に c(unsigned char として扱う)が最初に現れる位置を探し、見つかればその位置のアドレス(ポインタ)を返す。見つからなければ NULL を返す。
#include "libft.h"
const void *ft_memchr(const void *str, int c, size_t n)
{
size_t i;
unsigned char *cast_str;
i = 0;
cast_str = (unsigned char *)str;
while (i < n)
{
if (cast_str[i] == c)
return (&str[i]);
i++;
}
return (NULL);
}
まずvoid *strだから型がなにかわからない。型もバイト数もわからないのでstr[0]やstr + 1はそもそも不可能犯罪。だからchar の1バイトを利用して「unsigned char * にキャスト」する。
またさきほどのようにcast_str[i] == cのcにもキャストが必要であった。
そしてポインタを返すはずがなぜかアドレスを返している。
cast_str + i → iバイト進んだ位置のポインタ この表現の方法を覚えておく。
*cast_strはunsigned charなので返り値に合わせてconst void *にすることも忘れすに。
(i < n)のところstr[i}もいれなくていいのは文字列ではなくバイト列であるから。
文字比較でキャストするかどうかは差分を考えたいかどうかによる。
ft_strnstr
#include "libft.h"
const char *ft_strnstr(const char *haystack, const char *needle, size_t len)
{
size_t i;
int j;
const char *start;
if (needle[0] == '\0')
return (haystack);
i = 0;
while (haystack[i] && (i < len))
{
j = 0;
if (haystack[i] == needle[j])
{
start = haystack;
j = 1;
while (haystack[i + j] == needle[j] && haystack[i + j]
&& (i + j < len))
{
j++;
if (needle[j] == '\0')
return (start);
}
}
i++;
}
return (NULL);
}
start = haystack;だと先頭アドレス入れている。i地点でのアドレス入れてたいから&haystack[i}でよい。
ft_strjoin
char *ft_strjoin(char const *s1, char const *s2)
{
size_t s1_len;
size_t s2_len;
char *result;
s1_len = ft_strlen(s1);
s2_len = ft_strlen(s2);
result = (char *)malloc(s1_len + s2_len + 1);
if (!result)
return (NULL);
ft_memcpy(result, s1, s1_len);
ft_memcpy(result + s1_len, s2, s2_len);
result[s1_len + s2_len + 1] = '\0';
return (result);
}
mallocにつられてs1_len + s2_len + 1をインデックスにしがち。インデックスは0からなので1つすくなくなる。
ft_strtrim
include "libft.h"
int ft_start_position(char const *s1, char const *set);
int ft_end_position(char const *s1, char const *set);
char *ft_strtrim(char const *s1, char const *set)
{
int total_len;
int i;
char *result;
int start;
int end;
if (!set || !s1)
return (NULL);
start = ft_start_position(s1, set);
end = ft_end_position(s1, set);
total_len = end - start + 1;
result = (char *)malloc(total_len + 1);
if (!result)
return (NULL);
i = 0;
while (i < total_len)
{
result[i] = s1[start + i];
i++;
}
result [total_len + 1] = '\0';
return (result);
}
int ft_start_position(char const *s1, char const *set)
{
int i;
int j;
i = 0;
while (s1[i])
{
j = 0;
while (set[j] && (s1[i] != set[j]))
{
j++;
}
if (set[j] == '\0')
break ;
i++;
}
return (i);
}
int ft_end_position(char const *s1, char const *set)
{
int i;
int j;
int s1_len;
s1_len = ft_strlen(s1);
i = s1_len - 1;
while ((i >= 0) && s1[i])
{
j = 0;
while (set[j] && s1[i] != set[j])
j++;
if (set[j] == '\0')
break ;
i--;
}
return (i);
}
同様に終端文字のインデックスのミス。また、トリムされた結果空文字列になっても、malloc(1) して '\0' を入れた "空文字列"("")を返すべき。
ft_strchr
#include "libft.h"
const char *ft_strchr(const char *str, int c)
{
int i;
i = 0;
while (str[i])
{
if (str[i] == c)
return (&str[i]);
i++;
}
return (NULL);
}
c == '\0'の場合の処理がない。
Discussion