ZOJ 3481. Expand Tab

  題目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4278數組

 

  題意:ide

  給出一些文本片斷,把文本中的 Tab 字符根據配置,替換成必定數量的空格。函數

  配置分爲兩種,一種是隻提供一個 ts 值,則須要縮進到的位置是一個等比數列。另外一種是提供一個 ts 的有限集合,指定一些給定 ts 值,在邏輯上這個集合是無限的,當列位置超出集合中的數字時,後續的 tabstop 位置爲連續的以 1 個空格進行遞增。編碼

  即:spa

  { T } 在邏輯上至關於 { T, T * 2, T * 3, T * 4, ...... };code

  { T1, T2, ..., Tk } 在邏輯上至關於 { T1, T2, ..., Tk, Tk + 1, Tk + 2, Tk + 3, ...... };blog

 

  分析:排序

  本題目自己是比較簡單的。可是值得注意的是:索引

  (1)當給定一個 ts 序列時,ts 序列的數字無序且可能重複(若是去重,可能會致使數組中只剩下一個數字,這時候不能當作等比數列來處理。若是不去重就沒必要在乎這個問題)。因此不能假設序列有序,能夠對這個序列進行一次排序。get

  (2)當只提供一個 ts 值,這時爲等比數列。最開始我使用了相似圖像的行對齊公式來計算 stop 位置,結果這在一些狀況下,結果會多考慮一個 ts 值。實際上的索引爲 iCol 的列的 tabstop 值,公式僅僅是 (iCol / ts + 1) * ts 便可。因爲我在這裏編碼心態過急,犯下這個低級失誤,致使我不斷的 PE N 次,差點崩潰。回到家裏我慢慢查看這些步驟才找到這個錯誤。

 

  代碼:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct _TabStop {
    int count;
    int ts[500];
    char delimit[1024];
} TABSTOP, *LPTABSTOP;

//解析配置信息
void ParseTabStop(char *line, LPTABSTOP pTS);

//獲取 tab stop 位置
int GetStopCol(int iCol, LPTABSTOP pTS);

//排序用的比較函數
int cmp(const void* p1, const void* p2);

TABSTOP g_TS;

int main() 
{
    int i, T, col, stopCol;
    char line[1024], *p;

    scanf("%ld\n", &T);
    for(i = 0; i < T; i++) {
        gets(line);
        memset(&g_TS, 0, sizeof(TABSTOP));
        ParseTabStop(line, &g_TS);

        while(true) {
            gets(line);

            if(strcmp(line, g_TS.delimit) == 0) {
                gets(line); /*case結尾的空行*/
                printf("\n");
                break;
            }

            col = 0;
            p = line;
            while(*p) {
                if(*p == '\t') {
                    stopCol = GetStopCol(col, &g_TS);
                    while(col < stopCol) {
                        printf(" ");
                        ++col;
                    }
                }
                else {
                    printf("%c", *p);
                    ++col;
                }

                ++p;
            }
            printf("\n");
        }
    }
    return 0;
}

//解析 tabstop 配置
void ParseTabStop(char *line, LPTABSTOP pTS)
{
    /*expand tab-stops-configuration <<delimiting-identifier*/

    char *p = line + 7;
    char ch;
    int index = 0;

    while(*p) {
        ch = *p; 

        if(ch >= '0' && ch <= '9')
            pTS->ts[index] = pTS->ts[index] * 10 + (*p - '0');
        else if(ch == ',')
            ++index;
        else if(ch == '<') {
            strcpy(pTS->delimit, p + 2);
            break;
        }
        ++p;
    }

    pTS->count = index + 1;
    qsort(pTS->ts, pTS->count, sizeof(int), cmp);
}

//獲取當前列的 tabstop 位置
int GetStopCol(int iCol, LPTABSTOP pTS)
{
    int i;
    if(pTS->count == 1) {
        return (iCol / pTS->ts[0] + 1) * pTS->ts[0];
    }
    else {
        if(pTS->ts[pTS->count-1] <= iCol)
            return iCol + 1;

        for(i = 0; i < pTS->count; i++) {
            if(iCol < pTS->ts[i])
                return pTS->ts[i];
        }
    }
    return iCol + 1;
}

int cmp(const void* p1, const void* p2)
{
    int *pX1 = (int*)p1;
    int *pX2 = (int*)p2;
    return *pX1 - *pX2;
}
ZOJ_3481_cpp

 

  補充:

  固然,若是不對序列進行排序,也是能夠的。區別只是在獲取 tabstop 位置時,每次都要完整的線性遍歷這個集合(在有序的狀況下能夠提早結束遍歷,或者進一步的用二分查找快速定位),嘗試找到知足條件 ts > iCol 的全部 ts 中的最小值便可。

相關文章
相關標籤/搜索