-3

I am writing a program that will print the "*" based on the users input, the user will need to enter a number between 1 and 30 an the program will print the * n time. where n is between 1 and 30.

ex: user enters 7 output is "*******" for any n value between 1 and 30.

this is what i got so far:

int x;
char c = "*";

printf("%s","Please Enter a number between 1 and 30\n");
scanf("%d", &x);

if (x>=1)
{
    printf("%d",x,c);;
}

looking for some guidance on the printf part, how do i get it to print the * by what x is, this is the lower limit as 1 is the lowest the user can enter 30 is the upper limit but usually i like to make sure the lower limit works first before the upper then its a simple copy paste and change the numbers. A separate if will be for any number out of bounds i.e anything less then 1 and greater then 30 will require the user to reenter, so far it just prints the number that was entering not the * that many times. Also if i have any other mistakes in my code feel free to correct me still learning.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
JKS
  • 5
  • 1
  • 4
    You want to learn about loops. – user253751 Jul 21 '20 at 15:31
  • Already answered here https://stackoverflow.com/questions/14678948/how-to-repeat-a-char-using-printf – Shadi Naif Jul 21 '20 at 15:33
  • I initially was using a while loop, but i got stuck on the printf part, i still couldnt get it to print it n time, thats why i move to an if statement. – JKS Jul 21 '20 at 15:41
  • 1
    An how is the `if` supposed to repeat anything? Maybe you could post your approach using `while` and we figure out together what you got wrong there. Because an `if` is not going to repeat anything. – Lukas-T Jul 21 '20 at 15:43
  • What do you expect `printf("%d",x,c);;` should do? I would like to see your view on that. – RobertS supports Monica Cellio Jul 21 '20 at 15:48
  • the user needs to enter one input and the program to produce one output, a while loop would be good, if i needed the program to repeat the process multiple times, but i dont need it to repeat multiple times, i need to produce one output per input, if the user enters a single number i dont need it to run through the loop again. user enters 7 it print ******* and waits for the users next input. – JKS Jul 21 '20 at 15:55
  • @VladfromMoscow Are you sure the `printf` tag is appropriate here? Neither the `printf` function is necessary to solve the problem, nor the problem is `printf`–related. – CiaPan Jul 21 '20 at 17:39
  • @CiaPan One of main problems is incorrect using of printf. – Vlad from Moscow Jul 21 '20 at 17:54
  • @VladfromMoscow I see. I didn't think about it this way. – CiaPan Jul 21 '20 at 18:02
  • You need a beginner book and learn the basics – klutt Nov 02 '22 at 09:24

5 Answers5

1

You just need to replace your idea 'print once a group of N characters'
with 'print N times one character'.

Then the solution is straight-forward:

if (x >= 1 && x <= 30)    // test number of chars to print
{
    while (--x >= 0)      // decrement it and see if anything remains
        printf("*");      // print a character and reiterate

    printf("\n");         // terminate the output line
}
else
    printf("The value entered is not between 1 and 30.\n");   // error message

EDIT

Based on the answer by @RobertS supports Monica Cellio, you can make special use of the requirement that the output shall be a simple string of repeated single character, and that the size of the output is strictly limited to quite small length.

So you can define an explicit array of characters, containing the longest possible output string required:

const char outString[31] = "******************************";

The length of 31 suffices for 30 asterisks '*' and a zero character (ASCII NUL code), terminating the string.

When you want to output a string containing x asterisks, you can print a tail part of the string, starting at appropriate position:

if (x >= 1 && x <= 30)         // test number of chars to print
    puts( outString + 30 - x); // print appropriate part of the string
else
    puts("The value entered is not between 1 and 30.");

This way you avoid both the printf formatting and a loop overhead – at the cost of declaring a constant array.

CiaPan
  • 9,381
  • 2
  • 21
  • 35
  • Yes, that it is sneaky, too. :-) - Although there is no real advantage yet if you use a `char` array with 31 elements instead of a string literal with 30 elements. Suggestion: A real advantage to my version would be if you allocate the memory for the `char` array dynamically and free it after its use. ;-) – RobertS supports Monica Cellio Jul 22 '20 at 09:33
  • @RobertSsupportsMonicaCellio But an allocated array needs to be filled. There are quite a few options: one can `strcpy` a static string into it (but then the original string must be statically allocated anyway); or one can fill it with a loop (which OP apparently strives to avoid); or one can pretend there is no loop by calling `calloc('*',31)` (which has a loop inside), and then the last char has to be overwritten with zero. – CiaPan Jul 22 '20 at 10:49
  • 1
    I don't think that is how calloc works – Tenobaal Nov 02 '22 at 08:43
  • @Tenobaal Of course, you're right! I have no idea what I was thinking about when writing that part. It should be 'by calling `char *ptr = malloc(31);` followed by `memset(ptr, '*', 30);` which has a loop inside, and then the last char has to be set to zero: `ptr[30] = 0;`'. Thank you for pointing this out. :) – CiaPan Nov 02 '22 at 10:54
1

One way is using a loop and print one * at each iteration:

unsigned int x;

printf("Please Enter a number between 1 and 30\n");
if (scanf("%u", &x) != 1)
{
    // error routine.
}

if (x >= 1 && x <= 30)
{
    while (x--)
    {
        printf("%c", '*');
    }

    puts("");
}
else
{
    printf("Wrong input value!\n");
}

If you want to print the sequence of *s by just one printf() call,

One way is using a string literal of 30 *s and only display the amount of *s the user entered. The printing is possible with the .* modifier which provides the length of the output string relative to the value of the given argument x.

unsigned int x;
const char* p = "******************************";

printf("Please Enter a number between 1 and 30\n");
if (scanf("%u", &x) != 1)
{
    // error routine.
}

if (x >= 1 && x <= 30)
{
    printf("%.*s\n", x, p);
}
else
{
    printf("Wrong input value!\n");
}

A few notes here:

  • You need to change if (x >= 1) to if (x >= 1 && x <= 30) because it only should print the value if the values between 1 and 30 not only if 1 or above.

  • Always check the return of input functions such as scanf() if an error occurred.

  • I changed the type of x to unsigned int because its clear that it shouldn't have a negative value. Take care of that you need to change the format specifier in scanf() from %d to %u.

  • Isn't `printf`-ing with `"%.*s"` an overkill in this case...? :) – CiaPan Jul 21 '20 at 17:07
  • @CiaPan It might look a little strange but it is high-probably the most efficient version to use a string literal and just print a certain amount of characters from it at one call to `printf()`. Or did I misunderstood your comment? :-) – RobertS supports Monica Cellio Jul 21 '20 at 17:10
  • Well, there is a simple trick you can do _outside_ the call to `printf`. I'm going to add it to my answer ;) in a few hours. Hint: 'this case' refers to the very same simplicity and uniformity of an expected output, which allowed you to utilize the long string literal. – CiaPan Jul 21 '20 at 17:19
  • [Added](https://stackoverflow.com/a/63018233/733637). How do you like it? – CiaPan Jul 21 '20 at 21:05
1

This initialization of an object of the type char

char c = "*";

is wrong. Instead of the string literal "*" you have to use the character literal '*' like

char c = '*';

This call of printf

printf("%s","Please Enter a number between 1 and 30\n");

is too complicated. You could just write

printf("Please Enter a number between 1 and 30\n");

And this call of printf with a redundant null-statement

printf("%d",x,c);;

has an unused argument and does not do what you think it should do.

Moreover this if statement

if (x>=1)

does not check whether x is less than or equal to 30.

Beside this the user can interrupt the input. In this case the variable x will have indeterminate value if it is declared with automatic storage duration that is within a block.

Try never to use magic numbers as 1 or 30. Instead use named constants.

As the number of the repeated output characters can not be negative declare the corresponding variable x as having an unsigned integer type.

Here is a demonstrative program that shows how the code can be written.

#include <stdio.h>

int main(void) 
{
    const unsigned int MIN_VALUE = 1;
    const unsigned int MAX_VALUE = 30;
    const char c = '*';
    
    printf( "Please Enter a number between %u and %u inclusive: ", 
            MIN_VALUE, MAX_VALUE );
            
    unsigned int n;
    
    if ( scanf( "%u", &n ) == 1 && MIN_VALUE <= n && n <= MAX_VALUE )
    {
        putchar( '\n' );
        
        do
        {
            putchar( c );
        } while ( n-- != MIN_VALUE );
        putchar( '\n' );
    }
    else
    {
        puts( "\nSorry. The input is not valid." );
    }
    
    return 0;
}

The program output might look like

Please Enter a number between 1 and 30 inclusive: 20

********************
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • First thank you for the char correction i was told it was "*" not '*'. Second if i know that x im my case is going to between 1 and 30 an all other values will essentially stop at the else part of the if else statement, what would be the reason that we assign a max and a min to the variable if anything under 1 and over 30 would result in the if statement skipping over the first condition and outputting the second condition results? – JKS Jul 21 '20 at 16:57
  • Third what is the difference between put and printf, seeing it for the first time in your comment, after messing with the put and printf to me so far they look like they do essentially the same thing, there has to be something going on that i cant see? – JKS Jul 21 '20 at 16:58
  • @JKS printf requires an argument of the type char * that represents a string. But you need to output just one character in a loop. So it is more efficient to use putchar instead of printf. – Vlad from Moscow Jul 21 '20 at 17:06
  • @JKS As you wrote yourself in your question a valid number shall be between 1 and 30. So you have to check whether the entered number belongs to the specified range. – Vlad from Moscow Jul 21 '20 at 17:07
  • so in essence the puts will only print out a string, where the printf can output a string an any variable declared in that string or in my case if I use the printf function I have to assign the char in the printf like you would do with a variable, where as for the puts I can just use the character * with out defining it in the puts function? Am I understanding that correctly. – JKS Jul 21 '20 at 17:32
  • @JKS prints is designed to output a string and the new line character '\n'. For example puts( :Hello" ); has the same effect as printf( "Hello\n" ); Pay attention to that in the previous comment a compared printf and putchar. – Vlad from Moscow Jul 21 '20 at 17:36
1
//enter a numbers between 1 and 30 and print the character as per the entered number 

#include<stdio.h>

void main()
{

    int n;
    printf("Enter a number between 1 and 30 only  :\n ");
    scanf("%d",&n);
    if(n>=1 && n<=30)
    {
        for(int i=1; i<=n; i++)
        {
            printf("*");
        }
    }
    else
    {
         printf("Please enter a number only between 1 and 30");
    }
}
Tenobaal
  • 637
  • 1
  • 16
mrlfrnnds
  • 11
  • 1
  • Please read [answer] and [edit] your answer to contain an explanation as to why this code would actually solve the problem at hand. Always remember that you're not only solving the problem, but are also educating the OP and any future readers of this post. Especially given the OP explicitly asks for "guidance" and mentions they're "still learning". – Adriaan Nov 02 '22 at 09:26
0

For this purpose the most effizient was is to use fwrite. Other than for example printf, you have to tell the function how many character to write.

printf("%s","Please Enter a number between 1 and 30\n");
scanf("%d", &x);

if (x >= 1 && x <= 30) {
    char outbuffer[30];
    memset(outbuffer, '*', 30); // fill outbuffer with '*'
    fwrite(outbuffer, 1, x, stdout);
}
else ...

The fwrite function takes 4 arguments. The first argument is a pointer to bytes you want to write. Ignore the second. The third argument is the amount of elements you want to write and finally the fourth is where you wamt to write it to. stdout is the standart output.

An other way to do it, that escentially does the same, is to use a loop and putchar.

printf("%s","Please Enter a number between 1 and 30\n");
scanf("%d", &x);

if (x >= 1 && x <= 30) {
    for (int i = 0; i < x; i++) {
        putchar('*');
    }
}
else ...

For loops are seperated by ; into 3 pieces. The first int i = 0 will be run at the start and creates an integer called i and sets it to 0. The second is the condition. The loop runs as long as the condition is true or not 0. The last part is executed at the end of every loop iteration.

for (foo(); bar(); buzz()) {/* */}

Is the same as

foo();
while (bar()) {
    /* */
    buzz();
}
Tenobaal
  • 637
  • 1
  • 16