15

I am just wondering and confused as too why my output is messed up. The code is below. I am a beginner so please excuse my lack of skill. Any help would be very much appreciated.

#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;
}

Gives this output:

enter image description here

My desired output is this:
enter image description here

Iman
  • 183
  • 1
  • 4
  • 4
    Please post code, errors, sample data or textual output here as plain-text, not as images that can be hard to read, can’t be copy-pasted to help test code or use in answers, and are hostile to those who use screen readers. You can edit your question to add the code in the body of your question. Use the `{}` button to format any blocks of code, or indent with four spaces for the same effect. **Unfortunately, we can’t run your screenshot as code.** – tadman Jun 29 '18 at 20:06
  • 1
    Also, please add what the desired output should be. – 001 Jun 29 '18 at 20:08
  • Added the code. – Iman Jun 29 '18 at 20:16
  • Possible duplicate of [printf \t option](https://stackoverflow.com/questions/6646039/printf-t-option) – Bernhard Barker Jun 30 '18 at 09:15
  • I strongly suspect that the intent of this assignment is to print the two patterns *one after the other*, i.e., pattern A, and then pattern B *further below on the screen*. Specifically: It exactly matches Gaddis, *Starting Out with C++*, Programming Challenge Ch. 5, #23 (including the exact number of rows & columns, naming convention A/B, etc.), and I'm also looking at the book solution here which matches that expectation... – Daniel R. Collins Jul 01 '18 at 00:51
  • See if the exact phrasing of the assignment isn't, per Gaddis, "Write a program that uses a loop to display Pattern A below, followed by another loop that displays Pattern B". So: Two separate loops, and not nested. – Daniel R. Collins Jul 01 '18 at 00:53

6 Answers6

28

\t stops at the next reachable tab position, which by default are multiples of 8.

Therefore, if you print ***, it will skip to column 8, but if you print *********, you are already past 8, so it skips to column 16.

Aganju
  • 6,295
  • 1
  • 12
  • 23
  • That makes sense. So what would I add as a replacement for the spacing? I tried just using printf(" "), and that made the spacing correct but it did not out put my desired result. – Iman Jun 29 '18 at 20:23
  • Just to point out, by default it's indeed 8 character widths for a tab, but it can be changed if you're using a *nix terminal. If it's an IDE - that may or may not be available as option – Sergiy Kolodyazhnyy Jun 30 '18 at 08:22
12

The precision and width fields can be use for formatting. Precision will print up to the specified number of characters and width will print at least the specified number of characters. Using an asterisk in either field allows an argument for a variable number of characters.

#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;
}
user3121023
  • 8,181
  • 5
  • 18
  • 16
11

... why my output is messed up (?)

Code uses a tab '\t' which only aligns to the next tab-stop - usual every 8 columns and the stars needed exceed 8.


With judicious use of the '-' flag, field width and precision, code can be simplified to print an array of characters.

#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
  }
}

Output

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

Note: stars is not a string as it lacks a null character. Use of a precision with "%s" allows printf() to use a simple character array. Characters from the array are written up to (but not including) a terminating null character.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
7

A tab-stop is not a fixed-width space (e.g. the same as 4 spaces or 8 spaces), it means that the output device should move the caret (or print-head) to the next column position for tabular data. These column positions are at fixed regular intervals, that's why \t** and **\t have different printed widths:

String        Output:
"\t**a"       "    **a" (7 wide)
"**\ta"       "**  a"   (5 wide)
Dai
  • 141,631
  • 28
  • 261
  • 374
  • That makes sense. So what would I add as a replacement for the spacing? I tried just using printf(" "), and that made the spacing correct but it did not out put my desired result. – Iman Jun 29 '18 at 20:22
3

As others have mentioned, printing a tab character move the cursor to the next tab stop, not a certain number of spaces.

After printing the first set of asterisks, print spaces until you've printed enough characters to space out as far as you need.

    for (int j = 1; j <= 10; j++)
    {
        if (j<i) {
            printf("*");
        } else {
            printf(" ");
        }
    }
dbush
  • 205,898
  • 23
  • 218
  • 273
1

I would do like this:

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");
}

And just for completeness, even though mentioned in other answers. The '\t' character does not have a fixed width.

klutt
  • 30,332
  • 17
  • 55
  • 95