2014-01-11 64 views
1

「寫入程序入口,用最少數量的製表符和空白代替空白符,以達到相同的間距,使用與製表符相同的製表符,當製表符或單個空白符足以達到製表位,應給予優先選擇?「K&R答案書練習1.21

我自己做了練習,本書的答案有不同的解決方案。我不理解從輸入流中讀取製表符時執行的數學公式。下面是代碼:

#include <stdio.h> 
#define TABINC 8 

main() 
{ 
int c, nb, nt, pos; 

nb = 0; 
nt = 0; 
for (pos = 1; (c =getchar()) != EOF; ++pos) 
    if (c == ' '){ 
     if (pos % TABINC != 0) 
      ++nb; 
     else { 
      nb = 0; 
      ++nt; 
     } 
    } 
    else { 
     for (; nt > 0; --nt) 
      putchar('\t'); 
     if (c == '\t') 
      nb = 0; 
     else 
      for (; nb > 0; --nb) 
       putchar(' '); 
     putchar(c); 
     if (c == '\n') 
      pos = 0; 
     else if (c == '\t') 
      pos = pos + (TABINC - (pos - 1) % TABINC) - 1; 
    } 
} 

我不理解的部分如下:

else if (c == '\t') 
    pos = pos + (TABINC - (pos - 1) % TABINC) - 1; 

我可以通過在Visual Studio調試看到,這個結構帶來的POS到下一個製表位時從輸入流中出現選項卡。它是否正確?

我真的不明白的是這個公式是如何工作的,或者他們是怎麼想出來的。這是編程中常見的公式嗎?它有用嗎?它有名字嗎?

編輯:我明白模數運算符的作用。對不起,我沒有具體說明。

我很欣賞任何輸入。

回答

0

它沒有名稱或類似的東西。
詳細:

首先,很多POS如何必須增加依賴於POS%TABINC,
即。 TABINC是8,所以如果pos是8的倍數,那麼如果pos%8是1(如9,17 ...),則添加8,
,然後如果pos%8是2(10,18),則添加7,
。 ..)加6等等。

全部列表:
POS%8 - >數增加
0 - > 8
1 - > 7
2 - > 6
3 - > 5
4 - > 4
5 - > 3
6 - > 2
7 - > 1

這將是8 - pos%8或,更一般TABINC - pos%TABINC

重要:負數模的東西在C是數學上不正確
在C語言中,爲a,b >= 0:什麼是在代碼中添加(-a)%b == -(a%b)

(TABINC - (pos - 1) % TABINC) - 1
一些基本的數學和上面的事實,這是
(TABINC - (pos - 1) % TABINC) - 1
= TABINC - ((pos - 1) % TABINC)) - 1
= TABINC - ((pos % TABINC) - 1) - 1
= TABINC + 1 - (pos % TABINC) - 1
= TABINC - (pos % TABINC)
這與我上面的短公式相同,只是因爲沒有理由而變得更復雜。

1

有沒有具體的名稱這一公式 - 它是從小學到日常問題應用數學的一個相對直接的方式。這是怎麼回事:'\t'字符由多個位置的一至TABINC,包括推進pos

  • posTABINC多,你跳完整TABINC
  • pos是一個TABINC的倍數之下,您可以通過一個跳,
  • pos是兩者的一個倍數低於TABINC,你跳過兩個,
  • 等 - 當posx,其中0 < x < TABINC,低於下一個倍數TABINC,你ju熔點x

現在計算跳躍的問題簡化爲計算posTABINC的下一個倍數之間的差。這可以通過計算posTABINC的餘數部分,並從TABINC中減去餘數。這是通過%運營商完成的。

由於pos是一個基於*,該公式的第一件事是爲了計算餘數而使其爲零。接下來,該公式計算餘數,這是一種數學方式,表示「上一次止損位置的數量」。現在您只需要從TABINC中減去剩餘部分即可獲得您的結果。

*上發現'\n'分配pos=0看似矛盾的是pos是基於一個斷言。但是,循環標題在每次迭代後執行pos++,因此下一次循環的下一次循環會看到pos=1