The reason the loop was unending was that in the last iteration of the loop, i.e. when i==strlen(c), c[i] is the terminating NULL, which due to using assign rather than compare you were overwriting with a tab character, then on the next iteration you would start to get undefined behaviour (which often leads to a segfault).

Remember in C counting starts from 0. So a less than or equal comparison in the loop will count one MORE than you might have intended. Try it: let's count i from 0 to 5 using <=. 0, 1, 2, 3, 4 are all obvious. What about 5? Is 5 less than or equal to 5? YES. So i<=5 will still evaluate TRUE. So i will loop through the values 0,1,2,3,4,5, which is SIX iterations.

So unless you actually meant for the count to include the terminating NULL, you should use
Code:
for (i=0; i<strlen(c); i++)
And ALWAYS be careful about = and ==. Some languages interpret = differently according to the context, for example in BASIC the clause "IF A=5" is taken to be a comparison, but "A=5" is an assignment. But in C = *ALWAYS ALWAYS ALWAYS* means "assign", so "if (a=5)" will assign 5 to a, then evaluate 5 as a logical value where 0 is FALSE and any other value is TRUE. Since 5 is non-zero, it is TRUE, so "if (a=5)" will assign 5 to x and what comes after the if will always be performed (and if there is an else, that will never be performed). Some compilers will throw a "condition is always true" warning if they spot this, but it will have to be assignment to a constant.

Sometimes an assignment in an if is what you really want. Take the following:
Code:
int i=0;
while (c=str[i++])
    ...;
This will also loop over a string. For all non-zero values str[i] will be copied to c and the expression will evaluate TRUE. When it gets to the terminating NULL, str[i] which is 0 will be copied to c, this will evaluate FALSE and the loop will terminate.