C не корректно форматируется (используя\t)

Я просто удивляюсь и смущен, потому что мой вывод запутан. Код ниже. Я новичок, поэтому, пожалуйста, извините за недостаток мастерства. Любая помощь будет очень высоко ценится.

#include <stdio.h>

int main(int argc, char *argv[]) 
{

    for (int i = 1; i <= 10; i++)
    {

        for (int j = 1; j <= i; j++)
        {
            printf("*");
        }
        printf("\t");
        for (int k = 1; k <= 11-i; k++)     
        {
            printf("*");
        }
        printf("\n");
    }
    return 0;
}

Дает этот результат:

enter image description here

Мой желаемый результат:
enter image description here

Ответы

Ответ 1

\t останавливается в позиции следующей доступной вкладки, которая по умолчанию кратна 8.

Поэтому, если вы напечатаете ***, он перейдет к столбцу 8, но если вы напечатаете *********, вы уже прошли 8, поэтому он переходит к столбцу 16.

Ответ 2

Поля точности и ширины могут использоваться для форматирования. Precision будет печатать до указанного количества символов, а ширина будет печатать как минимум указанное количество символов. Использование звездочки в любом поле допускает аргумент для переменного количества символов.

#include <stdio.h>

int main( void) {
    char asterisk[] = "***********";

    for (int i = 1; i <= 10; i++)
    {
        printf ( "%.*s", i, asterisk);//print up to i characters
        printf ( "%*s", 15 - i, " ");//print at least 15 - i characters
        printf ( "%.*s", 11 - i, asterisk);
        printf("\n");
    }
    return 0;
}

Ответ 3

... почему мой вывод испорчен (?)

Код использует вкладку '\t' которая только выравнивается со следующей вкладкой-стопом - обычно каждые 8 столбцов и звезды должны превышать 8.


При разумном использовании флага '-', ширины поля и точности, код может быть упрощен для печати массива символов.

#include <stdio.h>
#include <string.h>

int main(void) {
  int n = 10;
  char stars[n];
  memset(stars, '*', n);

  for (int i = 0; i < n; i++) {
    //       +------------- - flag: pad on right     
    //       |+------------ field width: min characters to print, pad with spaces
    //       || +--------+- precision: max numbers of characters of the array to print
    printf("%-*.*s     %.*s\n", n, i + 1, stars, n - i, stars);
    //                          |  ^^^^^         ^^^^^ precision
    //                          +--------------------- field width
  }
}

Выход

*              **********
**             *********
***            ********
****           *******
*****          ******
******         *****
*******        ****
********       ***
*********      **
**********     *

Примечание: stars не являются строкой, так как в ней отсутствует нулевой символ. Использование точности с "%s" позволяет printf() использовать простой массив символов. Символы из массива записываются в (но не включая) завершающий нулевой символ.

Ответ 4

Закладка-стоп не является пространством фиксированной ширины (например, так же, как 4 пробела или 8 пробелов), это означает, что устройство вывода должно перемещать каретку (или печатающую головку) в следующую позицию столбца для табличных данных. Эти позиции столбцов имеют фиксированные регулярные интервалы, поэтому \t** и **\t имеют разную ширину печати:

String        Output:
"\t**a"       "    **a" (7 wide)
"**\ta"       "**  a"   (5 wide)

Ответ 5

Как отмечали другие, печать символа табуляции перемещает курсор на следующую вкладку, а не определенное количество пробелов.

После печати первого набора звездочек отпечатайте пробелы, пока вы не напечатаете достаточно символов, чтобы освободить пространство, насколько вам нужно.

    for (int j = 1; j <= 10; j++)
    {
        if (j<i) {
            printf("*");
        } else {
            printf(" ");
        }
    }

Ответ 6

Я бы сделал так:

const int rows = 10;
for (int i = 0; i < rows; i++) {
    const int width = 10;
    const int space = 5;
    const int totalw = 2*width + space;
    for (int j = 0; j < totalw; j++) {
        char ch = j<=i || (j>=width+space && j<(totalw-i)) ? '*' : ' ';
        printf("%c", ch);
    }
    printf("\n");
}

И только для полноты, хотя и упоминается в других ответах. Символ '\t' не имеет фиксированной ширины.

Ответ 7

Вот код, который должен сработать для вас:

#include <stdio.h>

int main(int argc, char *argv[])                                                                                          
{
    int i = 1;
    for (; i <= 10; i++)
    {
        int j = 1;
        for (; j <= i; j++)
        {
            printf("*");
        }
        for (; j <= 16; j += 8)
            printf("\t");

        int k = 1;
        for (; k <= 11-i; k++)  
        {
            printf("*");
        }
        printf("\n");
    }
    return 0;
}

Это основано на вашем коде, но есть много более эффективных способов сделать это.

В таких случаях, когда вы печатаете один символ в то время, я предпочитаю использовать putchar() вместо printf()

Примечание я должен объявить переменную вне for цикла, так как мой компилятор еще использует C89 стиль.