😀

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