【制表符和空格的转换】The C Programming Language 程序研究 第一部分第二章

第二章 字符和字符串的转换

一、文本中制表符和空格的相互转换

(一)制表符转换为空格

问题描述: 

 

 

 

 

 

 

 


要解决这个问题,首先要弄清楚文本中tab的性质,我们以vim编辑器为例进行探究。

说明:在每个tab后面都会紧跟一个2,以此来标记2前面是一个tab,另外为了发现tab的规律,特在文本中插入几行用来标记列号的数字

下面就是tab在vim文本编辑器中的效果:

 

每个数字2前面都有一个tab,很容易观察到,每个2都会出现在列号为1的位置,也就是说输入一个tab后,会让光标出现在某些固定的列,而且这些固定的列会是第9列、第17列、第25列……那么,如果在第8列后(此时光标位于第9列)再输入一个tab(输入后tab出现在第9列)会怎样呢?光标会停留在第9列,还是会跳转到第17列呢?我们观察这一情况:

 

答案是:光标跳转到第17列。也就是说,tab一定是占位符,在输入tab后不会出现光标位置不变的情况。

我们还可以观察到:

如果tab出现在第1~8列,光标会跳转到第9列

如果tab出现在第9~16列,光标会跳转到第17列

如果tab出现在第n列,光标会跳转到第((n-1)/8+1)*8+1列

……

 

因此,如果要用空格代替tab,并且不改变文本的布局,就要知道tab所处的列,然后将tab替换为相应数目的空格,使光标处于正确的位置即可。那么,如何得到tab所在列呢?当然,我们首先想到的应该是字符计数,但是,单纯的字符计数能够知道tab所处的列吗?我们假设输入的文本(tab用\t表示)是11\t21\t1,此时,如果使用单纯的字符计数,第一个tab位于第3列,第二个tab位于第6列,根据得到的规律,它们都将光标移至第9列,这显然是不正确的。正确计算列号的方式应该是:第一个tab位于第3列,为了将光标移至第9列,应该把这个tab换为6个空格,然后,将这些用于替换的空格也算入字符计数中,这时,第二个tab就会位于第11列,为了将光标移至第17列,应该把tab换为6个空格。

这样我们便得到了解决这个问题的方案:

逐个读取字符,如果读到tab,根据此时的字符数(列号)n,将这个tab替换为(n/8+1)*8-n个空格输出,并将此时的字符数记为:(n/8+1)*8;如果是非tab就直接输出字符,并计数。依此思路编写程序,便可以解决问题。 (另外,注意换行符对程序的影响:如果换行,则需要重新计算字符的列号)

下面是代码和测试结果:

 C++ Code By DuanXu-yzc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * 将文本中的tab转换为等效的空格,并且不改变文本原先的布局
 */

#include <stdio.h>
#define INTERVAL 8

int main ( void )
{
    int count;
    int ch;
    int i;
    int space_num;

    count = 0;
    while ( (ch=getchar()) != EOF )
    {
        if ( '\t' == ch )
        {
            space_num = (count/INTERVAL+1)*INTERVAL-count;
            for ( i=0; i<space_num; i++ )
                putchar ( ' ' );
            count = (count/INTERVAL+1)*INTERVAL;
        }
        else
        {
            count++;
            putchar ( ch );
        }

        if ( '\n' == ch )
            count = 0;
    }

    return 0;
}


 

在上面的方法中,

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值