There are a myriad ways to convert tabs in a string into 1-8 spaces. There are inefficient ways to do the expansion in-situ, but the easiest way to handle it is to have a function that takes the input string and a separate output buffer that is big enough for an expanded string. If the input is 6 tabs plus an X and a newline (8 characters + terminating null), the output would be 48 blanks, X, and a newline (50 characters + terminating null) - so you might need a much bigger output buffer than input buffer.
#include <stddef.h>
#include <assert.h>
static int detab(const char *str, char *buffer, size_t buflen)
{
char *end = buffer + buflen;
char *dst = buffer;
const char *src = str;
char c;
assert(buflen > 0);
while ((c = *src++) != '\0' && dst < end)
{
if (c != '\t')
*dst++ = c;
else
{
do
{
*dst++ = ' ';
} while (dst < end && (dst - buffer) % 8 != 0);
}
}
if (dst < end)
{
*dst = '\0';
return(dst - buffer);
}
else
return -1;
}
#ifdef TEST
#include <stdio.h>
#include <string.h>
#ifndef TEST_INPUT_BUFFERSIZE
#define TEST_INPUT_BUFFERSIZE 4096
#endif /* TEST_INPUT_BUFFERSIZE */
#ifndef TEST_OUTPUT_BUFFERSIZE
#define TEST_OUTPUT_BUFFERSIZE (8 * TEST_INPUT_BUFFERSIZE)
#endif /* TEST_OUTPUT_BUFFERSIZE */
int main(void)
{
char ibuff[TEST_INPUT_BUFFERSIZE];
char obuff[TEST_OUTPUT_BUFFERSIZE];
while (fgets(ibuff, sizeof(ibuff), stdin) != 0)
{
if (detab(ibuff, obuff, sizeof(obuff)) >= 0)
fputs(obuff, stdout);
else
fprintf(stderr, "Failed to detab input line: <<%.*s>>\n",
(int)(strlen(ibuff) - 1), ibuff);
}
return(0);
}
#endif /* TEST */
The biggest trouble with this test is that it is hard to demonstrate that it handles overflows in the output buffer properly. That's why there are the two '#define' sequences for the buffer sizes - with very large defaults for real work and independently configurable buffer sizes for stress testing. If the source file is dt.c
, use a compilation like this:
make CFLAGS="-DTEST -DTEST_INPUT_BUFFERSIZE=32 -DTEST_OUTPUT_BUFFERSIZE=32" dt
If the 'detab()' function is to be used outside this file, you'd create a header to contain its declaration, and you'd include that header in this code, and the function would not be static, of course.