Существует множество способов преобразования вкладок в строке в 1-8 пробелов. Существуют неэффективные способы сделать раскрытие на месте, но самый простой способ справиться с ним - это иметь функцию, которая принимает входную строку, и отдельный буфер вывода, который достаточно велик для расширенной строки. Если входные данные состоят из 6 вкладок, плюс X и новая строка (8 символов + завершающий ноль), выходные данные будут состоять из 48 пробелов, X и новой строки (50 символов + завершающий ноль) - поэтому вам может потребоваться гораздо больший выходной буфер, чем входной буфер.
#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 */
Самая большая проблема этого теста заключается в том, что трудно доказать, что он правильно обрабатывает переполнения в выходном буфере. Вот почему есть две последовательности «#define» для размеров буфера - с очень большими значениями по умолчанию для реальной работы и независимо настраиваемыми размерами буфера для стресс-тестирования. Если исходный файл dt.c
, используйте компиляцию, подобную этой:
make CFLAGS="-DTEST -DTEST_INPUT_BUFFERSIZE=32 -DTEST_OUTPUT_BUFFERSIZE=32" dt
Если функция detab () должна использоваться вне этого файла, вы должны создать заголовок, содержащий его объявление, и включить этот заголовок в этот код, и функция не будет статической Конечно.