鱼C论坛

 找回密码
 立即注册
查看: 1335|回复: 11

[已解决]练习 1-21 编写程序entab,将空格串替换为最少数量的制表

[复制链接]
发表于 2020-5-3 11:55:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
练习 1-21 编写程序entab,将空格串替换为最少数量的制表符和空格,但要保持单词之间的间隔不变
下面的代码是不是不对,应该不能直接把8个空格替换为制表符啊

  1. #include<stdio.h>
  2. #define MAX_ARRAY 1024
  3. #define TAB 8
  4. int getlines(char array[] , int maxlen);

  5. int main()
  6. {
  7.     char array[MAX_ARRAY];
  8.     int c,k,i;
  9.     int len;
  10.     int spacenum=0;

  11.     while ((len = getlines(array,MAX_ARRAY)) > 0)
  12.     {
  13.         for ( i = 0; i < len; i++)
  14.         {
  15.             if (c==' ')
  16.             {
  17.                 spacenum++;
  18.             }
  19.             if (c!=' ')
  20.             {
  21.                 spacenum=0;
  22.             }
  23.             if (spacenum==TAB)
  24.             {
  25.                 i-=7;
  26.                 len-=7;
  27.                 array[i] = '\t';
  28.                 for ( k = i+1;  k< len; k++)
  29.                 {
  30.                     array[k] = array[k+3];
  31.                 }
  32.                 spacenum = 0;
  33.                 array[len]='\0';
  34.             }
  35.         }
  36.        printf("%s",array);
  37.     }
  38.     return 0;
  39. }
  40. int getlines(char array[] , int maxlen)
  41. {
  42.     int i,c;
  43.     for ( i = 0; i < maxlen-1 && (c=getchar())!=EOF && c!='\n'; i++)
  44.     {
  45.         array[i] = c;
  46.     }
  47.     if (c=='\n')
  48.     {
  49.         array[i] = c;
  50.         i++;
  51.     }
  52.    
  53.     array[i] = '\0';
  54.     return i;
  55.    
  56. }
复制代码
最佳答案
2020-5-3 12:37:29
从上到下看代码,这次我只关心main函数中的变量 c
第8行没有出现c
第9行声明了 c,但是没有初值
第10行没有
第11行没有
第12行没有
第13行没有
第14行没有
第15行没有
第16行没有
第17行有一个 c==' '

那么问题来了,这个if条件成立吗?
答案是不知道,因为真的是不知道,不知道变量 c 的位置之前是什么
因为没有初始化,所以可以看成是 还是之前的值,但是我们不知道之前的值是什么

另外,给你个代码参考

  1. #include <stdio.h>

  2. #define TAB 8

  3. int main(void) {
  4.     char buf[4096];
  5.     while(fgets(buf, 4096, stdin)) {
  6.         int cols = 0;
  7.         for(int i = 0; buf[i]; ++i) {
  8.             if(buf[i] == '\t') {
  9.                 int count = TAB - (cols % TAB);
  10.                 if(count == 0) count = TAB;
  11.                 cols += count;
  12.                 while(count--)
  13.                     putchar(' ');
  14.             } else {
  15.                 putchar(buf[i]);
  16.                 ++cols;
  17.             }
  18.         }
  19.     }
  20.     return 0;
  21. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-5-3 12:37:29 | 显示全部楼层    本楼为最佳答案   
从上到下看代码,这次我只关心main函数中的变量 c
第8行没有出现c
第9行声明了 c,但是没有初值
第10行没有
第11行没有
第12行没有
第13行没有
第14行没有
第15行没有
第16行没有
第17行有一个 c==' '

那么问题来了,这个if条件成立吗?
答案是不知道,因为真的是不知道,不知道变量 c 的位置之前是什么
因为没有初始化,所以可以看成是 还是之前的值,但是我们不知道之前的值是什么

另外,给你个代码参考

  1. #include <stdio.h>

  2. #define TAB 8

  3. int main(void) {
  4.     char buf[4096];
  5.     while(fgets(buf, 4096, stdin)) {
  6.         int cols = 0;
  7.         for(int i = 0; buf[i]; ++i) {
  8.             if(buf[i] == '\t') {
  9.                 int count = TAB - (cols % TAB);
  10.                 if(count == 0) count = TAB;
  11.                 cols += count;
  12.                 while(count--)
  13.                     putchar(' ');
  14.             } else {
  15.                 putchar(buf[i]);
  16.                 ++cols;
  17.             }
  18.         }
  19.     }
  20.     return 0;
  21. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-3 12:57:28 | 显示全部楼层
人造人 发表于 2020-5-3 12:37
从上到下看代码,这次我只关心main函数中的变量 c
第8行没有出现c
第9行声明了 c,但是没有初值

这是题目的英文版的标准答案,我就是不理解作者的代码为什么会用一个制表符代替4个空格(在win里是8个),比如我前面有7个字符,输出制表符后不是应该占据1个空格吗,而不是固定的8个。
  1. /******************************************************
  2.    KnR 1-21
  3.    --------
  4.    Write a program "entab" which replaces strings of
  5.    blanks with the minimum number of tabs and blanks
  6.    to achieve the same spacing.

  7.    Author: Rick Dearman
  8.    email: rick@ricken.demon.co.uk

  9. ******************************************************/
  10. #include <stdio.h>

  11. #define MAXLINE 1000 /* max input line size */
  12. #define TAB2SPACE 4 /* 4 spaces to a tab */

  13. char line[MAXLINE]; /*current input line*/

  14. int getline(void);  /* taken from the KnR book. */


  15. int
  16. main()
  17. {
  18.   int i,t;
  19.   int spacecount,len;

  20.   while (( len = getline()) > 0 )
  21.     {
  22.       spacecount = 0;
  23.       for( i=0; i < len; i++)
  24.         {
  25.           if(line[i] == ' ')
  26.             spacecount++; /* increment counter for each space */
  27.           if(line[i] != ' ')
  28.             spacecount = 0; /* reset counter */
  29.           if(spacecount == TAB2SPACE) /* Now we have enough spaces
  30.                                       ** to replace them with a tab
  31.                                       */
  32.             {
  33.               /* Because we are removing 4 spaces and
  34.               ** replacing them with 1 tab we move back
  35.               ** three chars and replace the ' ' with a \t
  36.               */
  37.               i -= 3; /* same as "i = i - 3" */
  38.               len -= 3;
  39.               line[i] = '\t';
  40.               /* Now move all the char's to the right into the
  41.               ** places we have removed.
  42.               */
  43.               for(t=i+1;t<len;t++)
  44.                 line[t]=line[t+3];
  45.               /* Now set the counter back to zero and move the
  46.               ** end of line back 3 spaces
  47.               */
  48.               spacecount = 0;
  49.               line[len] = '\0';
  50.             }
  51.         }
  52.       printf("%s", line);
  53.     }
  54.   return 0;
  55. }


  56. /* getline: specialized version */
  57. int getline(void)
  58. {
  59.   int c, i;
  60.   extern char line[];
  61.   
  62.   for ( i=0;i<MAXLINE-1 && ( c=getchar()) != EOF && c != '\n'; ++i)
  63.     line[i] = c;
  64.   if(c == '\n')
  65.     {
  66.       line[i] = c;
  67.       ++i;
  68.     }
  69.   line[i] = '\0';
  70.   return i;

  71. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 13:16:49 | 显示全部楼层
JerryLeeSir 发表于 2020-5-3 12:57
这是题目的英文版的标准答案,我就是不理解作者的代码为什么会用一个制表符代替4个空格(在win里是8个) ...

制表符的宽度是可以设置的,这个作者选择的制表符宽度是 4
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 13:17:23 | 显示全部楼层
我感觉你还是没有把问题说清楚
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-3 13:24:25 | 显示全部楼层
人造人 发表于 2020-5-3 13:17
我感觉你还是没有把问题说清楚

制表符的宽度确实可以设置,比如设置宽度为4
当我前面有三个字符“123”时,此时再输出制表符,此时制表符应该占据一个空格
而作者的代码思路是 制表符永远占据4个空格
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 13:33:47 | 显示全部楼层
JerryLeeSir 发表于 2020-5-3 13:24
制表符的宽度确实可以设置,比如设置宽度为4
当我前面有三个字符“123”时,此时再输出制表符,此时制表 ...

将空格串替换为最少数量的制表符和空格

是把一堆的空格替换成制表符
题目有点模糊

如果一个tab是4个空格
那么13个空格应该替换成几个制表符和几个空格?
最少数量?
那就是一个tab和9个空格?(最少数量是什么意思?)
我怎么感觉是3个tab和1个空格

总和最少?
3 + 1 的确小于 1 + 9
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 13:49:55 | 显示全部楼层
还是不对,还是有问题
这种情况怎么办?把字符 b 后面的6个空格替换为1个tab,把字符 4 后面的4个空格替换为1个tab  ?

GIF.gif
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 13:58:49 | 显示全部楼层
我输入的是
12<空格>34<空格>5<tab>
也就是说要自己写的这个程序只把5后面的空格替换成制表符?

GIF.gif
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 14:13:24 | 显示全部楼层
作者提供的这个程序就仅仅只是扫描空格,发现4个空格就替换成1个tab,不考虑我上面提到的那2种情况
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-3 14:31:34 | 显示全部楼层
GIF.gif

  1. #include <stdio.h>

  2. #define TAB 8

  3. int main(void) {
  4.     char buf[4096];
  5.     while(fgets(buf, 4096, stdin)) {
  6.         int space = 0;
  7.         for(int i = 0; buf[i]; ++i) {
  8.             if(buf[i] == ' ') {
  9.                 ++space; continue;
  10.             }
  11.             if(space) {
  12.                 if(i % TAB == 0) putchar('\t');
  13.                 else {
  14.                     while(space--) putchar(' ');
  15.                 }
  16.                 space = 0;
  17.             }
  18.             putchar(buf[i]);
  19.         }
  20.     }
  21.     return 0;
  22. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-3 15:14:21 | 显示全部楼层

嗯嗯,了解了,比心谢谢啦
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-7-3 17:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表