K & R Упражнение 1.21 - PullRequest
       41

K & R Упражнение 1.21

0 голосов
/ 11 января 2020

В настоящее время пытаются решить экс 1.21. Задача: Написать программу entab, которая заменяет строки пробелов минимальным количеством вкладок и пробелов для достижения одинакового расстояния. Используйте те же табуляции, что и для detab. Когда для достижения позиции табуляции будет достаточно либо табуляции, либо одного пробела, которому следует отдать предпочтение?

Ниже приведен мой код, который я сделал до сих пор. У меня нет проблем с вводом количества пробелов меньше размера табуляции, но когда оно больше, я получаю ошибку сегментации. Кто-нибудь может мне помочь, пожалуйста?

#include <stdio.h>
#include <ctype.h>
#define TAB 8
#define MAXLINE 1000

int getmine(char s[], int lim);
int entab(char output[], int pos, int space);

int main()
{
    char line[MAXLINE], output[MAXLINE];
    int i;
    while ((i = getmine(line, MAXLINE)) > 0)
    {
        int space = 0;
        int pos = 0;
        int count = 0;
        while (line[count] != '\n')
        {
            if (line[count] != ' ')
            {
                space = 0;
                output[count] = line[count];
            }
            else if (line[count] == ' ')
            {
                pos = count - space;
                space++;
                if (line[count + 1] != ' ')
                {
                    if (space > TAB)
                    {
                        int z = entab(output, pos, space);
                        count = z;
                    }
                    else
                    {
                        for (int a = 0; a < space; a++)
                            output[pos + a] = ' ';
                    }
                }
            }
            count++;
        }
        if (line[count] == '\n')
        {
            output[count] = line[count];
            count++;
        }
        output[count] = '\0';
        printf("%s", output);
    }
}

int getmine(char s[],int lim)
{
    int c, i;
    for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
        s[i] = c;
    if (c == '\n') 
    {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}

int entab(char output[], int pos, int space)
{
    int nTabs = 0;
    int nSpaces = 0;
    int x = TAB - (pos % TAB);
    if (x > 0)
    {
        output[pos] = '\t';
        space = space - x;
        nTabs = space / TAB;
        nSpaces = space % TAB;
        for (int a = 0; a < nTabs; a++)
            output[pos + 1 + a] = '\t';
        for (int b = 0; b < nSpaces; b++)
            output[pos + 1 + nTabs + b] = ' ';
        return pos + nTabs + nSpaces + 1;
    }
    else if (x == 0)
    {
        nTabs = space / TAB;
        nSpaces = space % TAB;
        for (int a = 0; a < nTabs; a++)
            output[pos + a] = '\t';
        for (int b = 0; b < nSpaces; b++)
            output[pos + nTabs + b] = ' ';
        return pos + nTabs + nSpaces;
    }
}

1 Ответ

0 голосов
/ 11 января 2020

Поскольку последовательности пробелов из 8 символов заменяются одним символом (вкладка), количество прочитанных байтов из входных данных не совпадает с записанными байтами в выходных данных. Простое решение для этого состоит в том, чтобы просто отслеживать две переменные, одну для считанных байтов из ввода и одну для записанных байтов в выходной. Вы можете сделать это несколько точнее с помощью указателей, хотя, если вы следуете книге линейно, указатели IIR C будут представлены позже.

Непроверенный (а именно для демонстрационных целей) код, приведенный ниже. ПРИМЕЧАНИЕ: я взял на себя смелость переформатировать ваш код для краткости.

#include <stdio.h>
#include <ctype.h>
#define TAB 8
#define MAXLINE 1000

int getmine(char s[], int lim);
int entab(char output[], int pos, int space);

int main()
{
    char line[MAXLINE], output[MAXLINE];
    int i;
    while ((i = getmine(line, MAXLINE)) > 0) {
        int space = 0;
        int pos = 0;

        int read_bytes = 0;
        int write_bytes = 0;

        while(read_bytes < i) {
            if (line[read_bytes] != ' ') {
                space = 0;
                output[write_bytes++] = line[read_bytes];
            }
            else if (line[read_bytes] == ' ') {
                space++;
                if (line[read_bytes + 1] != ' ') {
                    if (space > TAB) {
                        write_bytes += entab(output, write_bytes, space);
                    } else {
                        for (int i = 0; i < space; i++)
                            output[write_bytes++] = ' ';
                    }
                }
            }
            read_bytes++;
        }
        if (line[read_bytes] == '\n') {
            output[write_bytes++] = line[read_bytes];
        }
        output[write_bytes] = '\0';
        printf("%s", output);
    }
}

int getmine(char s[],int lim)
{
    int c, i;
    for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
        s[i] = c;
    if (c == '\n')  {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}

int entab(char output[], int pos, int space)
{
    int nTabs = 0;
    int nSpaces = 0;
    int x = TAB - (pos % TAB);
    if (x > 0) {
        output[pos] = '\t';
        space = space - x;
        nTabs = space / TAB;
        nSpaces = space % TAB;
        for (int i = 0; i < nTabs; i++)
            output[pos + 1 + i] = '\t';
        for (int i = 0; i < nSpaces; i++)
            output[pos + 1 + nTabs + i] = ' ';
        return nTabs + nSpaces + 1;
    } else if (x == 0) {
        nTabs = space / TAB;
        nSpaces = space % TAB;
        for (int i = 0; i < nTabs; i++)
            output[pos + i] = '\t';
        for (int i = 0; i < nSpaces; i++)
            output[pos + nTabs + i] = ' ';
    }
    return nTabs + nSpaces;
}
...