將一行文字中的單字間空白符平均重新分配,實現兩端對齊排版效果。規則:
base = spaces / (words - 1)extra = spaces % (words - 1)#include#include #define N 80 void edit(char *s) { int i, sp = 0, w = 0, inw = 0; // 階段 1:統計單字數與空白數 for (i = 0; s[i]; i++) { if (s[i] == ' ') { sp++; inw = 0; // 進入空白狀態 } else if (!inw) { w++; inw = 1; // 進入單字狀態 } } if (w <= 1) return; // 單字不超過 1,無需排版 int v = sp / (w - 1); // 每間隔基礎空白數 int r = sp % (w - 1); // 多餘空白數 // 階段 2:重新排版 char buf[N]; strcpy(buf, s); // 備份原字串 char *str = buf; // 讀取指標 char *dst = s; // 寫入指標 (原地修改) while (*str) { // 跳過原有空白 while (*str == ' ') str++; // 複製單字 while (*str && *str != ' ') { *dst++ = *str++; } if (--w == 0) break; // 最後一個單字不加空白 // 插入基礎空白 for (i = 0; i < v; i++) *dst++ = ' '; // 插入多餘空白 (優先前面間隔) if (r > 0) { *dst++ = ' '; r--; } } *dst = '\0'; // 結束符 } int main() { char buff[N]; puts("This is a typeset program!\nPlease input a character line:\n"); fgets(buff, N, stdin); buff[strcspn(buff, "\n")] = '\0'; // 移除換行 edit(buff); printf("\nThe character line after typeset is:\n\n%s\n", buff); return 0; }
輸入: "Hello world !" 統計: words=3, spaces=6 計算: base=6/(3-1)=3, extra=0 輸出: "Hello world !" 輸入: "A B C" 統計: words=3, spaces=3 計算: base=1, extra=1 輸出: "A B C" (第一間隔得 2 空白,第二間隔得 1 空白)
| 技巧 | 程式碼 | 作用 |
|---|---|---|
| 狀態機統計單字 | inw 旗標 | O(n) 單次掃描完成統計,避免重複掃描 |
| 雙緩衝區原地修改 | buf + str/dst | 讀取與寫入分離,避免覆蓋未處理資料 |
| 指標運算而非索引 | *dst++ = *str++ | 高效、簡潔,C 風格精髓 |
| 多餘空白優先前置 | if (r--) *dst++ = ' '; | 視覺上更自然 (左側鬆散、右側緊湊) |