Align columns/C: Difference between revisions
Content added Content deleted
m (moved Column Aligner/C to Align columns/C) |
m (Fixed syntax highlighting.) |
||
(2 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{collection|Column Aligner}} |
{{collection|Column Aligner}} |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <stdlib.h> |
|||
#include <string.h> |
|||
const char *str = |
|||
struct linelement { |
|||
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$\n" |
|||
char **wordlist; |
|||
"are$delineated$by$a$single$'dollar'$character,$write$a$program\n" |
|||
int longest; |
|||
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$\n" |
|||
struct linelement *next; |
|||
"column$are$separated$by$at$least$one$space.\n" |
|||
}; |
|||
"Further,$allow$for$each$word$in$a$column$to$be$either$left$\n" |
|||
"justified,$right$justified,$or$center$justified$within$its$column."; |
|||
void align(const char *in, char alignment) |
|||
typedef struct linelement line_t; |
|||
char *trim(char *s, int *len) |
|||
{ |
{ |
||
int col, i, l, r; |
|||
char *b; |
|||
int w[1024] = {0}; |
|||
int l; |
|||
const char *s; |
|||
for (s = in, i = col = 0; s[i]; s += i + 1) { |
|||
for (i = 0; s[i] && s[i] != '$' && s[i] != '\n'; i++); |
|||
b = s; |
|||
l = strlen(b); |
|||
s += l; s--; |
|||
while( (*s == ' ') || (*s == '\t') ) s--; |
|||
s++; *s = 0; |
|||
if ( l > *len ) *len = l; |
|||
return b; |
|||
} |
|||
if (i > w[col]) w[col] = i; |
|||
char **split(char *l, int c, int *longest) |
|||
{ |
|||
int howmany, i; |
|||
char **arr; |
|||
char *n; |
|||
if (col++ >= 1024) abort(); /* artificial limit */ |
|||
if ( (n = strchr(l, 13)) != NULL ) *n = 0; |
|||
if (s[i] == '\n') col = 0; |
|||
if (!s[i]) break; |
|||
if ( (l[i]==c) && ((i+1) < strlen(l))) howmany++; |
|||
} |
|||
arr = malloc(sizeof(char *) * (howmany+1)); |
|||
arr[0] = NULL; |
|||
if ( arr != NULL ) { |
|||
n = l; |
|||
for(i=0; i < howmany; i++) { |
|||
arr[i] = n; |
|||
n = strchr(n, c); |
|||
if ( n == NULL ) { break; } |
|||
*n = 0; n++; |
|||
arr[i] = trim(arr[i], longest); |
|||
} |
|||
} |
|||
arr[howmany] = NULL; |
|||
return arr; |
|||
} |
|||
for (s = in, i = col = 0; s[i]; s += i + 1) { |
|||
for (i = 0; s[i] && s[i] != '$' && s[i] != '\n'; i++); |
|||
switch(alignment) { |
|||
#define MAXLINELEN 1024 |
|||
case 'l': r = w[col] - i; break; |
|||
#define FILLCHAR ' ' |
|||
case 'c': r = (w[col] - i)/2; break; |
|||
case 'r': r = 0; break; |
|||
} |
|||
l = w[col++] - i - r + 1; |
|||
while (l--) putchar(' '); |
|||
/* decide the alignment */ |
|||
printf("%.*s", i, s); |
|||
enum textalign { |
|||
while (r--) putchar(' '); |
|||
LEFT_ALIGNED, RIGHT_ALIGNED, CENTER_ALIGNED |
|||
}; |
|||
const int alignment = CENTER_ALIGNED; |
|||
if (s[i] != '$') { |
|||
putchar('\n'); |
|||
col = 0; |
|||
} |
|||
if (!s[i]) break; |
|||
} |
|||
} |
|||
int main() |
int main(void) |
||
{ |
{ |
||
puts("\n---- right ----"); align(str, 'r'); |
|||
char buf[MAXLINELEN]; |
|||
puts("\n---- left ----"); align(str, 'l'); |
|||
line_t *head, *cur; |
|||
puts("\n---- center ----"); align(str, 'c'); |
|||
char *lb; |
|||
return 0; |
|||
int reallongest, i, len, ipos; |
|||
}</syntaxhighlight> |
|||
head = malloc(sizeof(line_t)); |
|||
memset(head, 0, sizeof(line_t)); |
|||
/* for each line, split it ($-separated words) */ |
|||
cur = head; |
|||
while ( fgets(buf, MAXLINELEN, stdin) != NULL ) { |
|||
lb = malloc(strlen(buf)); |
|||
strncpy(lb, buf, strlen(buf)); |
|||
cur->wordlist = split(lb, '$', &(cur->longest)); |
|||
cur->next = malloc(sizeof(line_t)); |
|||
memset(cur->next, 0, sizeof(line_t)); |
|||
cur = cur->next; |
|||
} |
|||
cur->next = NULL; /* last node is a end-marker */ |
|||
/* each line holds the longest word length; find the |
|||
longest among all lines; this determines the width |
|||
of all columns */ |
|||
reallongest = head->longest; |
|||
cur = head; |
|||
while( cur->next != NULL ) { |
|||
if ( cur->longest > reallongest ) |
|||
reallongest = cur->longest; |
|||
cur = cur->next; |
|||
} |
|||
reallongest++; |
|||
buf[reallongest] = 0; /* no bounds check... */ |
|||
/* print the columns */ |
|||
cur = head; |
|||
while( cur->next != NULL ) { |
|||
for(i=0; cur->wordlist[i] != NULL; i++) { |
|||
len = strlen(cur->wordlist[i]); |
|||
switch(alignment) { |
|||
case LEFT_ALIGNED: |
|||
ipos = 0; |
|||
break; |
|||
case RIGHT_ALIGNED: |
|||
ipos = reallongest - len; |
|||
break; |
|||
case CENTER_ALIGNED: |
|||
ipos = (reallongest - len)/2; |
|||
break; |
|||
} |
|||
memset(buf, FILLCHAR, reallongest); |
|||
memcpy(buf+ipos, cur->wordlist[i], len); |
|||
printf("%s ", buf); |
|||
} |
|||
printf("\n"); |
|||
cur = cur->next; |
|||
} |
|||
}</lang> |
Latest revision as of 16:23, 1 September 2022
Align columns/C is part of Column Aligner. You may find other members of Column Aligner at Category:Column Aligner.
#include <stdio.h>
const char *str =
"Given$a$text$file$of$many$lines,$where$fields$within$a$line$\n"
"are$delineated$by$a$single$'dollar'$character,$write$a$program\n"
"that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$\n"
"column$are$separated$by$at$least$one$space.\n"
"Further,$allow$for$each$word$in$a$column$to$be$either$left$\n"
"justified,$right$justified,$or$center$justified$within$its$column.";
void align(const char *in, char alignment)
{
int col, i, l, r;
int w[1024] = {0};
const char *s;
for (s = in, i = col = 0; s[i]; s += i + 1) {
for (i = 0; s[i] && s[i] != '$' && s[i] != '\n'; i++);
if (i > w[col]) w[col] = i;
if (col++ >= 1024) abort(); /* artificial limit */
if (s[i] == '\n') col = 0;
if (!s[i]) break;
}
for (s = in, i = col = 0; s[i]; s += i + 1) {
for (i = 0; s[i] && s[i] != '$' && s[i] != '\n'; i++);
switch(alignment) {
case 'l': r = w[col] - i; break;
case 'c': r = (w[col] - i)/2; break;
case 'r': r = 0; break;
}
l = w[col++] - i - r + 1;
while (l--) putchar(' ');
printf("%.*s", i, s);
while (r--) putchar(' ');
if (s[i] != '$') {
putchar('\n');
col = 0;
}
if (!s[i]) break;
}
}
int main(void)
{
puts("\n---- right ----"); align(str, 'r');
puts("\n---- left ----"); align(str, 'l');
puts("\n---- center ----"); align(str, 'c');
return 0;
}