I stumbled into this while solving an exercise:
void ft_striteri(char *s, void (*f)(unsigned int, char*))
{
unsigned int i;
if (!s || !f)
return ;
i = 0;
while (s[i ])
f(i, s i);
}
Why doesn't the post increment in the while work while if i do this:
void ft_striteri(char *s, void (*f)(unsigned int, char*))
{
unsigned int i;
if (!s || !f)
return ;
i = -1;
while (s[ i])
f(i, s i);
}
It works?
I'm new and still very confused to the whole pointer concept is there any nuance here that I don't know about?
CodePudding user response:
The problem is the match between the comparison and the function call.
Consider the first iteration. In the first snippet it would be:
if(!s[0]) break;
f(1, s 1);
In the second snippet it would be:
if(!s[0]) break;
f(0, s 0);
CodePudding user response:
If you do simple debugging you will see what the problem is.
void ft_striteri(char *s, void (*f)(unsigned int, char*))
{
unsigned int i;
i = 0;
while (s[i ])
{
printf("i = %d\n", i);
if(f) f(i, s i);
}
}
void ft_striteri1(char *s, void (*f)(unsigned int, char*))
{
unsigned int i;
i = -1;
while (s[ i])
{
printf("i = %d\n", i);
if(f) f(i, s i);
}
}
int main()
{
ft_striteri("Hello", NULL);
printf("\n");
ft_striteri1("Hello", NULL);
}
https://godbolt.org/z/cqb1aMGje Result:
i = 1
i = 2
i = 3
i = 4
i = 5
i = 0
i = 1
i = 2
i = 3
i = 4
Function with postincrement iterates from index 1 to 5 instead of 0 to 4.
But your both functions do not use the correct type for the indexes. It should be size_t
instead of int
.
I would personally write another way, having "positive" test checking if parameters are OK and have only one return point:
void ft_striteri(char *s, void (*f)(unsigned int, char*))
{
size_t i = 0;
if(s && f)
{
while (s[i])
{
f(i, s i);
i ; // or i; - it makes no difference
}
}
}
CodePudding user response:
I don't know about nuance, but here is an equivalent to your first:
void first(char *s, void (*f)(unsigned int, char*))
{
unsigned int i;
if (!s || !f)
return ;
i = 0;
while (s[i]) {
f(i, s i 1);
s = s 1;
}
}
and second:
void second(char *s, void (*f)(unsigned int, char*))
{
unsigned int i;
if (!s || !f)
return ;
i = -1;
while (s[i 1]) {
f(i, s i 1);
i = i 1;
}
}
Really, neither look right to me; I would think you would want:
void ft_striteri(char *s, void (*f)(unsigned int, char*))
{
unsigned int i;
if (!s || !f)
return ;
i = 0
while (s[i]) {
f(i, s i);
i
}
}
which, in idiomatic style might be:
void ft_striteri(char *s, void (*f)(unsigned int, char*))
{
int c;
if (!s || !f)
return ;
for (; *s; s )
f(i, s);
}