我正在尝试创建一个在16 * 8屏幕上居中文本的功能(一行8行和16个字母),长度<1的部分。 16工作正常,但当我有多行时,我找不到如何解决问题,这是我的代码:
char* align_text(char* text)
int i=0, j=0, k;
int modulo, diff;
int size = strlen(text);
char space[16];
char tmp[16];
char tmp2[16];
char* tmp3;
char median[150];
char* final;
if(size==16)
return text;
else if(size<16)
{
diff = 16 - size;
modulo = diff%2;
if(modulo==0)
{
for(j=0;j<diff/2;j++)
space[j] = ' ';
space[j] = '\0';
strcat(median, space);
strcat(median, text);
strcat(median, space);
}
else
{
for(j=0;j<(int)(diff/2);j++)
space[j] = ' ';
space[j] = '\0';
strcat(median, space);
strcat(median, text);
space[j] = ' ';
space[j+1] = '\0';
strcat(median, space);
}
final = (char*)malloc(strlen(median)*sizeof(char));
strcpy(final, median);
return final;
}
else
{
while(text[i] != '\0')
{
if(text[i] == ' ')
{
if(strlen(tmp2)>16 && strlen(tmp)<=16)
{
tmp3 = align_text(tmp);
if(strlen(median) == 0)
strcpy(median, tmp3);
else
strcat(median, tmp3);
free(tmp3);
j=0;
tmp2[0] = '\0';
i = k;
}
strcpy(tmp, tmp2);
tmp2[j++]=text[i++];
tmp2[j]='\0';
k = i;
}
else
{
tmp2[j++]=text[i++];
tmp2[j]='\0';
}
}
if(strlen(tmp2)>16 && strlen(tmp)<=16)
{
tmp3 = align_text(tmp);
if(strlen(median) == 0)
strcpy(median, tmp3);
else
strcat(median, tmp3);
free(tmp3);
}
j=0;
tmp2[0] = '\0';
i = k;
while(text[i] != '\0' )
{
tmp2[j] = text[i];
tmp3 = align_text(tmp2);
strcat(median, tmp3);
free(tmp3);
}
final = (char*)malloc(strlen(median)*sizeof(char));
strcpy(final, median);
return final;
}
}
答案 0 :(得分:0)
我相信经过一些测试后这会有效。我不会声称自己具有很高的优雅水平,但它干净而实用。
这里的方法是将输入作为一个以空字符结尾的文本字符串。输入字符串的副本是由于strtok
用于提取每个非空字符串,strtok
修改字符串。通过一次构建一行(在line
缓冲区中)来管理输出,然后在该行被复制到输出时被认为已满时对该行进行居中。函数format_line
将行的副本复制到必须居中的输出。如果您想要左对齐或右对齐,只需修改format_line
即可。因为strtok
用于拉动#34;令牌&#34;从带有空白分隔符的输入中,在输出的每个单词之间重新插入一个空格。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const int cols = 16;
static const int rows = 8;
void format_line(char *out_text, char line[], int col)
{
int nspaces;
// Back off the trailing space if there is one
//
if ( line[col-1] == ' ' )
col -= 1;
line[col] = '\0';
// Center the text to the output buffer
//
nspaces = cols - col;
memset(out_text, ' ', nspaces/2);
out_text += nspaces/2;
*out_text = '\0';
strcat(out_text, line);
out_text += strlen(line);
memset(out_text, ' ', nspaces - nspaces/2);
out_text += nspaces - nspaces/2;
*out_text = '\0';
}
char *align_text(char *text)
{
int col, row;
char *fit_text, *ret_text;
char *np;
char line[cols+1];
char *ptext;
// Copy the input text so we don't destroy the original w/strtok
ptext = malloc(strlen(text) + 1);
strcpy(ptext, text);
// Create the buffer for the output text
ret_text = fit_text = malloc(cols * rows + 1);
// Initialize the working line/row
line[col = 0] = '\0';
row = 0;
// Parse each string in the input text with space as delimeter
//
for (np = strtok(ptext, " "); (np != NULL) && (row < rows); np = strtok(NULL, " "))
{
// If the next string fits on the current line
// then we'll put it there
//
if ((col + strlen(np)) < cols)
{
col += strlen(np);
strcat(line, np);
// Append a space delimeter if there's room
//
if (col < cols)
line[col++] = ' ';
line[col] = '\0';
// If we hit the end of the line, copy it to the output text
// buffer and reset the to the beginning of the working line
//
if (col == cols)
{
memcpy(fit_text, line, col);
fit_text += cols;
line[col = 0] = '\0';
row += 1;
}
}
else // The next string doesn't fit on the current line
{
// If there is text on the current line, then
// space pad it, append it to the output (centered), and reset working line
//
if ( col > 0 )
{
format_line(fit_text, line, col);
fit_text += cols;
}
// If the current string is longer than a line, then
// copy over the long chunks
//
while ( strlen(np) >= cols )
{
memcpy(fit_text, np, cols);
fit_text += cols;
np += cols;
row += 1;
}
// Copy the rest of the current string to the fresh working line
//
strcpy(line, np);
col = strlen(np);
line[col++] = ' ';
line[col] = '\0';
row += 1;
}
}
// Copy over and center the last one
//
if ( (col > 0) && (row < rows) )
{
format_line(fit_text, line, col);
fit_text += cols;
}
*fit_text = '\0';
return ret_text;
}
int main(int argc, char *argv[])
{
if ( argc > 1 )
{
printf("%s\n", align_text(argv[1]));
printf("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF\n");
}
return 0;
}
答案 1 :(得分:-1)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum { left, center, right } position;
int pos_calc(int width, int max_width, position pos){
int d;
if((d=max_width - width)< 0)
return -1;
switch(pos){
case left: return 0;
case right: return d;
case center: return d/2;
}
}
char *puton(char *buff, int width, position pos, const char *data){
int len = strlen(data);
int offset = pos_calc(len, width, pos);
memset(buff, ' ', width);
buff[width]='\0';
memcpy(buff + offset, data, len);
return buff;
}
char* join(char c, size_t arrsize, const char *arr[]){
size_t i, total, len[arrsize];
char *buff, *ret;
for(total=i=0;i<arrsize;++i)
total+=(len[i]=strlen(arr[i]));
if(NULL==(ret=buff=malloc((total + arrsize)*sizeof(char))))
return NULL;
for(i=0;i<arrsize;++i){
memcpy(buff, arr[i], len[i]);
buff+=len[i];
*buff++=c;
}
*--buff='\0';
return ret;
}
char *align_text(const char *str){
static const int row = 8;
static const int col = 16;
static const char *delimiter = " \t\n";
char *text = strdup(str);
char *words[col], *p, *cat;
int wc, total_len, r;
char *buff = malloc(row * col * sizeof(char) + 1);
//memset(buff, ' ', row*col);
//buff[row*col] = '\0';
for(r=total_len=wc=0, p=strtok(text, delimiter); p ; p = strtok(NULL, delimiter)){
int len = strlen(p);
//if(len > col){...}
words[wc++] = p;
total_len += len;
if(total_len + wc - 1 > col){
cat = join(' ', wc - 1, words);
puton(buff + col * r++, col, center, cat);
//if(r >= row){...}
free(cat);
words[0] = words[wc-1];
wc = 1;
total_len = len;
}
}
cat = join(' ', wc, words);
puton(buff + col * r++, col, center, cat);
free(cat);
free(text);
return buff;
}
void print(const char *text, int width){
int i;
for(i=1;*text;++i){
putchar(*text++);
if(i % width == 0)
putchar('\n');
}
}
int main(){
char *text = align_text("Hello how are you");
//printf("%s", text);
print(text, 16);
free(text);
return 0;
}