Align columns/C: Difference between revisions

From Rosetta Code
Content added Content deleted
m (Fixed syntax highlighting.)
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{collection|Column Aligner}}
{{collection|Column Aligner}}


<lang c>#include <stdio.h>
<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;


while( (*s == ' ') || (*s == '\t') ) 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 ( (n = strchr(l, 10)) != NULL ) *n = 0;
if (col++ >= 1024) abort(); /* artificial limit */
if ( (n = strchr(l, 13)) != NULL ) *n = 0;


for(howmany=1, i=0; l[i] != 0 ; i++)
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;
}