【问题标题】:How do you centre align N lines of textN行文本如何居中对齐
【发布时间】:2016-02-11 12:32:48
【问题描述】:

显然在 C 语言中没有标准化的居中对齐方式,所以我

想知道我如何编写一个 if 语句来居中对齐接下来的 N 行

文本。例如,如果程序在文本文件中找到.ce2,它应该

在页面中心打印接下来的两行,然后照常进行。

.ce2 This is my heading
Lesson 1
Task 2

输出:

                       This is my heading

                           Lesson 1

Task 2

下面是我写的代码,我实现了.br功能来破解

句子和.sp 功能可在文本中添加空行。

int main(void) {
FILE *fp = NULL;
char file_name[257] = {'\0'};
char line[61] = {'\0'};
char word[61] = {'\0'};
int out = 0;
int blanks;
int space;

printf ( "Enter file name:\n");
scanf ( " %256[^\n]", file_name);

if ( ( fp = fopen ( file_name, "r")) == NULL) {
    printf ( "could not open file\n");
    return 1;
}

while ( ( fscanf ( fp, "%60s", word)) == 1) { //breaks the sentence after .br
    if ( strcmp ( word, ".br") == 0) {
        printf ( "%s\n", line);
        line[0] = '\0';
        out = 1;
    }

    if ( strncmp ( word, ".sp", 3) == 0) { // creates n amount of spaces after .sp
        if ( ( sscanf ( &word[3], "%d", &blanks)) == 1) {
        printf ( "%s\n", line);
            while ( blanks) {
                blanks--;
                printf ( "\n");
                                }
            line[0] = '\0';
            out = 1;
                        }

    if ( strncmp ( word, ".ce", 3) == 0) { // centre the next n lines
        if ( ( sscanf ( &word[3], "%d", &space)) == 1) {
   //this is the if statement I am stuck at on what to include                
}
            line[0] = '\0';
            out = 1;
                        }

【问题讨论】:

  • 如果文本不能完全居中会发生什么?另外,请格式化您的代码。到处都是大括号,有点难以阅读。
  • 什么是line?它在哪里填充?请以标准方式格式化您的代码,以便我们阅读它..
  • @PaulOgilvie 我已经添加了代码的开头以使其更易于理解

标签: c formatting user-input


【解决方案1】:

printf 不提供使文本居中的机制,但它提供了一种使文本右对齐(字段宽度)的机制和一种将字段宽度指定为参数的机制。将这两者放在一起,很容易使文本居中:

int print_centered(FILE* f, const char* str, int width) {
  int len = strlen(str);
  if (len < width) 
    return fprintf(f, "%*s\n", (width + len) / 2, str);
  else /* Line is too long to fit */
    return fprintf(f, "%s\n", str);
}

如果您想截断太长而无法容纳的行,您可以使用“精度”,在 %s 格式的情况下,它会限制要打印的字符串的长度:

int print_centered_or_truncated(FILE* f, const char* str, int width) {
  int len = strlen(str);
  if (len < width) 
    return fprintf(f, "%*s\n", (width + len) / 2, str);
  else /* Line is too long to fit */
    return fprintf(f, "%.*s\n", width, str);
}

更多详情请见man fprintf

【讨论】:

  • 您的代码可以工作,但我认为这与我的问题无关,因为我有一个包含.ce2 的给定文件,这意味着接下来的两行应该居中,但您的代码没有将任何内容更改为我现有的代码
  • @jayjay:取决于您如何看待它,它为您提供了一个可以调用以使行居中的函数,该函数仅使用代码来读取要居中的行,或者它提供您是代码的基础模型。它不提供“请为我编写代码”,这不是 SO 的意义所在。
【解决方案2】:

此函数将获取您希望文本居中的缓冲区的宽度、格式和 printf 接受的任何其他参数,如果宽度小于输出缓冲区,它将截断。

#include <stdarg.h>

/***********************************
 * This function will center a     *
 * buffer of size 'width', and     *
 * it will truncate larger strings *
 **********************************/
int center_printf(int width, const char* format, ...)
{
   char *tmp = NULL, *output = NULL;
   int length, leading_spaces, ret;
   va_list args;

   if ( width <= 0 )                // Abort on incorrect width.
   {
      ret = -1;
      goto cleanup;
   }

   tmp = (char *)malloc ( width );
   if (tmp == NULL)
   {
      ret = -1;
      goto cleanup;
   }

   output = (char *)malloc ( width );
   if ( output == NULL )
   {
      ret = -1;
      goto cleanup;
   }

   va_start ( args, format );
   memset ( output, 0x20, width );    // Fill the output buffer with spaces.

   length = vsnprintf ( tmp, width, format, args );
   leading_spaces = ( length >= width ) ? 0 : (width - length)/ 2;
   memcpy ( output + leading_spaces, tmp, length );

   ret = printf ( output );
   va_end( args );

cleanup:
   if ( tmp != NULL )
      free ( tmp );
   if ( output != NULL )
        free ( output );

   return ret;
}

编辑: 根据 chux 和 rici 的 cmets 修复了我的函数。

int center_printf(int width, const char* format, ...)
{
   char *output = NULL;
   int length, ret;
   va_list args;

   if ( width <= 0 )                // Abort on incorrect width.
   {
      ret = -1;
      goto cleanup;
   }

   output = (char *)malloc ( width + 1 );
   if (output == NULL)
   {
      ret = -1;
      goto cleanup;
   }

   va_start ( args, format );
   length = vsnprintf ( output, width + 1, format, args );
   ret = printf ( "%*s", ( length >= width ) ? 0 : (width + length)/2 , output );
   va_end( args );

cleanup:
   if ( output != NULL )
      free ( output );

   return ret;
}

用法:

center_printf (50, "%s: testing 123", __FUNCTION__);

【讨论】:

  • if ( width &lt;= 0 ) { ... goto cleanup; 在未初始化的tmp 上执行if ( tmp != NULL ) free ( tmp );
  • 我觉得这种方式对我来说太复杂了,我正在寻找一种更简单的方式,类似于我实现.sp.br的方式
  • 这个解决方案是不必要的复杂,是的。它还有两个明显的错误:(1)可以包含width 字符的字符串需要malloc(width+1)(两个地方,虽然不需要第二个副本,因为您可以使用 printf 输出必要的空格); (2) 使用任意字符串作为printf 的格式是不安全的。请改用fputs(str, stdout)printf("%s", str)。 (如果要打印的字符串中有百分比会怎样?)
  • 我使用您的 cmets 和答案修复了我的功能。感谢您的输入,我实际使用它,我的要求之一是获取格式参数以及发送的任何其他变量,就好像它是一个普通的 printf 函数一样。啊。我明白你的意思是通过一个百分号这样转义\%。以下 printf 会出现问题。谢谢。正在努力。如果我有观点,我会支持你的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
  • 1970-01-01
  • 2013-06-14
  • 1970-01-01
相关资源
最近更新 更多