fork download
  1. /*
  2. プログラミングのお題スレ Part13
  3. https://m...content-available-to-author-only...h.net/test/read.cgi/tech/1549160513/
  4.  
  5. 831デフォルトの名無しさん2019/04/24(水) 20:52:14.50ID:NALZs80Z
  6. お題: 簡易なテーブルを綺麗に整形する
  7. 余力があればカラムの左揃え、右揃えをオプションで選択できるようにする(出力は中央揃え)
  8.  
  9. 入力:
  10. a|aaaaa|bb
  11. ccc|ddd|ee
  12.  
  13. 出力:
  14.  
  15. **a***|*aaaaa*|***bb*
  16. ------+-------+------
  17. *ccc**|**ddd**|***ee*
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22.  
  23. /* セル内の壁と文字列の間のスペース文字数 */
  24. #define RDD_CHAR (' ')
  25. #define RDD_CHAR_NUM 1
  26. /* セル内の文字列が終わったときに使う、空の文字列 */
  27. #define SPACE_CHAR ('*')
  28.  
  29. /* 配列で取得する最大サイズ */
  30. typedef enum{
  31. in_max_row = 16,
  32. in_max_col = 1024,
  33. table_max_row = 16,
  34. table_max_col = 16,
  35. out_max_row = in_max_row * 2 + 1, //input_max_row に依存
  36. out_max_col = 2048
  37. }max_size;
  38.  
  39. typedef struct{
  40. char *ptr;
  41. int size;
  42. }tablestr_t;
  43.  
  44.  
  45. /* 動作モード */
  46.  
  47. enum str_pos_id{
  48. /* セル中の文字列の位置 */
  49. LEFT, //左寄せ
  50. MEDIUM, //中間
  51. RIGHT //右寄せ
  52. };
  53.  
  54. enum cell_width_id{
  55. /* セルの幅 */
  56. MAX_IN_TABLE, //すべてのセルを表の最大幅のセルに合わせる
  57. MAX_IN_EACH_COL //各列のセルをその列の最大幅に合わせる
  58. };
  59.  
  60. int tbl(char output[out_max_row][out_max_col],
  61. char input[in_max_row][in_max_col],
  62. enum str_pos_id mode_str_pos,
  63. enum cell_width_id mode_cell_width){
  64.  
  65. /* セル内の壁と文字列の間のスペース文字数 */
  66. int rdd_char_num = RDD_CHAR_NUM; //redundant space , 0以上の整数
  67. char rdd_char = RDD_CHAR;
  68.  
  69. /* セル内の文字列が終わったときに使う、空の文字列 */
  70. char space_char = SPACE_CHAR;
  71.  
  72. /* カウンタ */
  73. int i, j;
  74.  
  75. /* セルの内容を記録する配列 */
  76. tablestr_t table[table_max_row][table_max_col];
  77.  
  78. /* 表の区切りの水平線の文字列配列 */
  79. char table_hori_line[out_max_col];
  80.  
  81. /* 各列のセルの幅を記録する配列 */
  82. int col_cell_width[table_max_col];
  83.  
  84. /* 表の最も大きいセルの幅 */
  85. int cell_max_width;
  86.  
  87. /* 各配列の行と列のサイズ */
  88. int in_row, in_col;
  89. int table_row, table_col;
  90. int out_row, out_col;
  91.  
  92.  
  93. /* 配列初期化 */
  94. //table
  95. for(i = 0; i < table_max_row; i++){
  96. for(j = 0; j < table_max_col; j++){
  97. table[i][j].ptr = NULL;
  98. table[i][j].size = 0;
  99. }
  100. }
  101. //col_cell_width
  102. for(i = 0; i < table_max_col; i++){
  103. col_cell_width[i] = 0;
  104. }
  105. //output
  106. for(i = 0; i < out_max_row; i++){
  107. for(j = 0; j < out_max_col; j++){
  108. output[i][j] = '\0';
  109. }
  110. }
  111. //table_hori_line
  112. for(i = 0; i < in_max_col; i++){
  113. table_hori_line[i] = '\0';
  114. }
  115.  
  116.  
  117. /* in_row, in_colを計算 */
  118. for(i = 0; i < in_max_row; i++){
  119. /* その行の最初の文字がnull文字なら、そこでデータの終点とする */
  120. if(input[i][0] == '\0'){
  121. in_row = i;
  122. break;
  123. }
  124. }
  125. /* in_col はin_max_colに設定 */
  126. in_col = in_max_col;
  127.  
  128.  
  129. /* table_row, table_colを計算 */
  130. /* table_row がtable_max_rowに収まるサイズか確認 */
  131. table_row = in_row;
  132. if(table_row > table_max_row){
  133. puts("ERROR: table_row > table_max_row");
  134. return(1);
  135. }
  136.  
  137.  
  138. /* 各行のセルの数をカウントする */
  139. //最終的に最大のセル数に合わせる
  140. { //一時変数隠蔽用ブロック
  141. int temp;
  142. char crr_char;
  143. char prev_char;
  144.  
  145. table_col = 0;
  146. for(i = 0; i < in_row; i++){
  147. temp = 0;
  148. prev_char = '\0';
  149. for(j = 0; (j < in_col) && ( (crr_char = input[i][j]) != '\0'); j++){
  150. if(crr_char == '|'){
  151. temp++;
  152. }
  153. prev_char = crr_char;
  154. }
  155. if(prev_char != '|'){
  156. temp++;
  157. }
  158.  
  159. if(table_col < temp){
  160. table_col = temp;
  161. }
  162. }
  163. }
  164. if(table_col > table_max_col){
  165. puts("ERROR: table_col > table_max_col");
  166. return(1);
  167. }
  168.  
  169.  
  170. /* tablelist の各セルに inputのポインタを登録 */
  171. { //一時変数隠蔽用ブロック
  172. char *ptr; //inputの文字列開始位置
  173. int size; //文字列数
  174. int in_crr_col; //inputの文字列の解析位置
  175. char crr_char;
  176.  
  177. for(i = 0; i < table_row; i++){
  178. in_crr_col = 0;
  179. for(j = 0; j < table_col; j++){
  180. ptr = &input[i][in_crr_col];
  181. size = 0;
  182. while( ( (crr_char = input[i][in_crr_col]) != '|' ) && (crr_char != '\0') ){
  183. in_crr_col++;
  184. size++;
  185. }
  186.  
  187. table[i][j].ptr = ptr;
  188. table[i][j].size = size;
  189.  
  190. if(crr_char == '|'){
  191. in_crr_col++;
  192. }
  193. else if(crr_char == '\0'){
  194. break;
  195. }
  196. }
  197. }
  198. }
  199.  
  200.  
  201. /* col_cell_width を計算 */
  202. {
  203. int temp = 0;
  204. int cell_crr_col;
  205.  
  206. for(i = 0; i < in_row; i++){
  207. cell_crr_col = 0;
  208. temp = 0;
  209. for(j = 0; j < in_col; j++){
  210. /* '|'かnull文字を検索し、セルの最大幅を求める */
  211. /* '|'だったら、tempを比較しリセット */
  212. if(input[i][j] == '|'){
  213. if(col_cell_width[cell_crr_col] < temp){
  214. col_cell_width[cell_crr_col] = temp;
  215. }
  216. temp = 0;
  217. cell_crr_col++;
  218. }
  219. /* null文字だったら、tempを比較しリセット、 ループ終了。次の行へ */
  220. else if(input[i][j] == '\0'){
  221. if(col_cell_width[cell_crr_col] < temp){
  222. col_cell_width[cell_crr_col] = temp;
  223. }
  224. break;
  225. }
  226. /* どちらでもないなら +1 */
  227. else{
  228. temp++;
  229. }
  230. }
  231. }
  232.  
  233. /* cell_max_widthを計算 */
  234. cell_max_width = col_cell_width[0];
  235. for(i = 1; i < table_col; i++){
  236. if(cell_max_width < col_cell_width[i]){
  237. cell_max_width = col_cell_width[i];
  238. }
  239. }
  240.  
  241. switch(mode_cell_width){
  242. case MAX_IN_TABLE:
  243. for(i = 0; i < table_col; i++){
  244. col_cell_width[i] = cell_max_width;
  245. }
  246. break;
  247.  
  248. case MAX_IN_EACH_COL:
  249. //特に何もしない
  250. break;
  251.  
  252. default:
  253. puts("'mode_cell_width' has invalid value");
  254. return(1);
  255. break;
  256. }
  257. }
  258.  
  259.  
  260. /* out_row, out_col を計算 */
  261. out_row = table_row * 2 + 1;
  262. if(out_row > out_max_row){
  263. puts("ERROR: out_row > out_max_row");
  264. return(1);
  265. }
  266. out_col = (cell_max_width + rdd_char_num * 2 + 1) * table_col + 1;
  267. if(out_col > out_max_col){
  268. puts("ERROR: out_col > out_max_col");
  269. return(1);
  270. }
  271.  
  272.  
  273. /* table_hori_line を作成 */
  274. { //一時変数隠蔽用ブロック
  275. int hori_line_crr;
  276. int temp;
  277. int cell_width;
  278.  
  279. table_hori_line[0] = '+';
  280. hori_line_crr = 1;
  281. for(i = 0; i < table_col; i++){
  282. temp = 0;
  283. cell_width = col_cell_width[i] + rdd_char_num * 2;
  284. while(temp < cell_width){
  285. table_hori_line[hori_line_crr] = '-';
  286. hori_line_crr++;
  287. temp++;
  288. }
  289. table_hori_line[hori_line_crr] = '+';
  290. hori_line_crr++;
  291. }
  292. }
  293.  
  294.  
  295. /* output にtableを書き出し */
  296. { //一時変数隠蔽用ブロック
  297. int out_crr_col;
  298. int out_crr_row;
  299. char *crr_cell_str_ptr;
  300. int crr_cell_str_size;
  301. int first_space_size;
  302. int last_space_size;
  303. int temp;
  304.  
  305. out_crr_col = 0;
  306. out_crr_row = 0;
  307. for(i = 0; i < table_row; i++){
  308. if(i == 0){
  309. for(out_crr_col = 0; out_crr_col < out_col; out_crr_col++){
  310. output[out_crr_row][out_crr_col] = table_hori_line[out_crr_col];
  311. }
  312. out_crr_row++;
  313. }
  314.  
  315. out_crr_col = 0;
  316.  
  317. output[out_crr_row][out_crr_col] = '|';
  318. out_crr_col++;
  319.  
  320. for(j = 0; j < table_col; j++){
  321. crr_cell_str_ptr = table[i][j].ptr;
  322. crr_cell_str_size = table[i][j].size;
  323.  
  324. switch(mode_str_pos){
  325. case MEDIUM:
  326. //中央配置
  327. if( (col_cell_width[j] + crr_cell_str_size) % 2 == 0){
  328. first_space_size = (col_cell_width[j] - crr_cell_str_size) / 2;
  329. last_space_size = (col_cell_width[j] - crr_cell_str_size) / 2;
  330. }
  331. else{
  332. first_space_size = (col_cell_width[j] - crr_cell_str_size) / 2;
  333. last_space_size = (col_cell_width[j] - crr_cell_str_size) / 2 + 1;
  334. }
  335. break;
  336.  
  337. case LEFT:
  338. //左詰め
  339. first_space_size = 0;
  340. last_space_size = col_cell_width[j] - crr_cell_str_size;
  341. break;
  342.  
  343. case RIGHT:
  344. //右詰め
  345. first_space_size = col_cell_width[j] - crr_cell_str_size;
  346. last_space_size = 0;
  347. break;
  348.  
  349. default:
  350. puts("'mode_str_pos' has invalid value");
  351. return(1);
  352. break;
  353. }
  354.  
  355. //冗長文字の書き込み
  356. for(temp = 0; temp < rdd_char_num; temp++){
  357. output[out_crr_row][out_crr_col] = rdd_char;
  358. out_crr_col++;
  359. }
  360.  
  361. //文字列の前の空白文字を書き込む
  362. for(temp = 0; temp < first_space_size; temp++){
  363. output[out_crr_row][out_crr_col] = space_char;
  364. out_crr_col++;
  365. }
  366.  
  367. //セルの文字列の書き込み
  368. for(temp = 0; temp < crr_cell_str_size; temp++){
  369. output[out_crr_row][out_crr_col] = crr_cell_str_ptr[temp];
  370. out_crr_col++;
  371. }
  372.  
  373. //文字列の後の空白文字を書き込む
  374. for(temp = 0; temp < last_space_size; temp++){
  375. output[out_crr_row][out_crr_col] = space_char;
  376. out_crr_col++;
  377. }
  378.  
  379. //冗長文字の書き込み
  380. for(temp = 0; temp < rdd_char_num; temp++){
  381. output[out_crr_row][out_crr_col] = rdd_char;
  382. out_crr_col++;
  383. }
  384.  
  385. //壁 '|'を書き込む
  386. output[out_crr_row][out_crr_col] = '|';
  387. out_crr_col++;
  388. }
  389. out_crr_row++;
  390.  
  391. for(out_crr_col = 0; out_crr_col < out_col; out_crr_col++){
  392. output[out_crr_row][out_crr_col] = table_hori_line[out_crr_col];
  393. }
  394. out_crr_row++;
  395. }
  396. }
  397.  
  398. return(0);
  399. }
  400.  
  401. void show_input(char input[][in_max_col]){
  402. int i = 0;
  403. while(i < in_max_row && input[i][0] != '\0'){
  404. printf("%s\n", input[i]);
  405. i++;
  406. }
  407. puts("");
  408. }
  409.  
  410. void show_output(char output[][out_max_col]){
  411. int i = 0;
  412. while(i < out_max_row && output[i][0] != '\0'){
  413. printf("%s\n", output[i]);
  414. i++;
  415. }
  416. puts("");
  417. }
  418.  
  419. int main(void){
  420. char input[in_max_row][in_max_col] = { "a|eeeee||123456789|abcdefg|qwertyuiop|asdxfghjkl",
  421. "bb|ffffff",
  422. "ccc|ggggggg||0|1|2|3",
  423. "dddd|hhhhhhhh||4|5|6|7|" };
  424. char output[out_max_row][out_max_col];
  425.  
  426. puts("入力: ");
  427. show_input(input);
  428.  
  429. puts("各列ごとに幅変更、中間配置");
  430. if(tbl(output, input, MEDIUM, MAX_IN_EACH_COL) != 0){
  431. exit(1);
  432. }
  433. show_output(output);
  434.  
  435. puts("各列ごとに幅変更、左詰め");
  436. if(tbl(output, input, LEFT, MAX_IN_EACH_COL) != 0){
  437. exit(1);
  438. }
  439. show_output(output);
  440.  
  441. puts("各列ごとに幅変更、右詰め");
  442. if(tbl(output, input, RIGHT, MAX_IN_EACH_COL) != 0){
  443. exit(1);
  444. }
  445. show_output(output);
  446.  
  447. puts("全セル等幅、中間配置");
  448. if(tbl(output, input, MEDIUM, MAX_IN_TABLE) != 0){
  449. exit(1);
  450. }
  451. show_output(output);
  452.  
  453. puts("全セル等幅、左詰め");
  454. if(tbl(output, input, LEFT, MAX_IN_TABLE) != 0){
  455. exit(1);
  456. }
  457. show_output(output);
  458.  
  459. puts("全セル等幅、右詰め");
  460. if(tbl(output, input, RIGHT, MAX_IN_TABLE) != 0){
  461. exit(1);
  462. }
  463. show_output(output);
  464.  
  465. return 0;
  466. }
Success #stdin #stdout 0s 9432KB
stdin
Standard input is empty
stdout
入力: 
a|eeeee||123456789|abcdefg|qwertyuiop|asdxfghjkl
bb|ffffff
ccc|ggggggg||0|1|2|3
dddd|hhhhhhhh||4|5|6|7|

各列ごとに幅変更、中間配置
+------+----------+--+-----------+---------+------------+------------+
| *a** | *eeeee** |  | 123456789 | abcdefg | qwertyuiop | asdxfghjkl |
+------+----------+--+-----------+---------+------------+------------+
| *bb* | *ffffff* |  | ********* | ******* | ********** | ********** |
+------+----------+--+-----------+---------+------------+------------+
| ccc* | ggggggg* |  | ****0**** | ***1*** | ****2***** | ****3***** |
+------+----------+--+-----------+---------+------------+------------+
| dddd | hhhhhhhh |  | ****4**** | ***5*** | ****6***** | ****7***** |
+------+----------+--+-----------+---------+------------+------------+

各列ごとに幅変更、左詰め
+------+----------+--+-----------+---------+------------+------------+
| a*** | eeeee*** |  | 123456789 | abcdefg | qwertyuiop | asdxfghjkl |
+------+----------+--+-----------+---------+------------+------------+
| bb** | ffffff** |  | ********* | ******* | ********** | ********** |
+------+----------+--+-----------+---------+------------+------------+
| ccc* | ggggggg* |  | 0******** | 1****** | 2********* | 3********* |
+------+----------+--+-----------+---------+------------+------------+
| dddd | hhhhhhhh |  | 4******** | 5****** | 6********* | 7********* |
+------+----------+--+-----------+---------+------------+------------+

各列ごとに幅変更、右詰め
+------+----------+--+-----------+---------+------------+------------+
| ***a | ***eeeee |  | 123456789 | abcdefg | qwertyuiop | asdxfghjkl |
+------+----------+--+-----------+---------+------------+------------+
| **bb | **ffffff |  | ********* | ******* | ********** | ********** |
+------+----------+--+-----------+---------+------------+------------+
| *ccc | *ggggggg |  | ********0 | ******1 | *********2 | *********3 |
+------+----------+--+-----------+---------+------------+------------+
| dddd | hhhhhhhh |  | ********4 | ******5 | *********6 | *********7 |
+------+----------+--+-----------+---------+------------+------------+

全セル等幅、中間配置
+------------+------------+------------+------------+------------+------------+------------+
| ****a***** | **eeeee*** | ********** | 123456789* | *abcdefg** | qwertyuiop | asdxfghjkl |
+------------+------------+------------+------------+------------+------------+------------+
| ****bb**** | **ffffff** | ********** | ********** | ********** | ********** | ********** |
+------------+------------+------------+------------+------------+------------+------------+
| ***ccc**** | *ggggggg** | ********** | ****0***** | ****1***** | ****2***** | ****3***** |
+------------+------------+------------+------------+------------+------------+------------+
| ***dddd*** | *hhhhhhhh* | ********** | ****4***** | ****5***** | ****6***** | ****7***** |
+------------+------------+------------+------------+------------+------------+------------+

全セル等幅、左詰め
+------------+------------+------------+------------+------------+------------+------------+
| a********* | eeeee***** | ********** | 123456789* | abcdefg*** | qwertyuiop | asdxfghjkl |
+------------+------------+------------+------------+------------+------------+------------+
| bb******** | ffffff**** | ********** | ********** | ********** | ********** | ********** |
+------------+------------+------------+------------+------------+------------+------------+
| ccc******* | ggggggg*** | ********** | 0********* | 1********* | 2********* | 3********* |
+------------+------------+------------+------------+------------+------------+------------+
| dddd****** | hhhhhhhh** | ********** | 4********* | 5********* | 6********* | 7********* |
+------------+------------+------------+------------+------------+------------+------------+

全セル等幅、右詰め
+------------+------------+------------+------------+------------+------------+------------+
| *********a | *****eeeee | ********** | *123456789 | ***abcdefg | qwertyuiop | asdxfghjkl |
+------------+------------+------------+------------+------------+------------+------------+
| ********bb | ****ffffff | ********** | ********** | ********** | ********** | ********** |
+------------+------------+------------+------------+------------+------------+------------+
| *******ccc | ***ggggggg | ********** | *********0 | *********1 | *********2 | *********3 |
+------------+------------+------------+------------+------------+------------+------------+
| ******dddd | **hhhhhhhh | ********** | *********4 | *********5 | *********6 | *********7 |
+------------+------------+------------+------------+------------+------------+------------+