Reputation: 41
I have worked on Python and I know that to concatenate a string to be --- you can simply "multiply" an integer by the char "-", so in this case we can simply do it like result=3*"-". I am stuck on trying to do this in C language.
How can I do this in C, for example:
#include <stdio.h>
int main (void)
{
int height=0;
int n=0;
char symbol='#';
printf("Height: ");
scanf("%d",&height);
n=height+1;
while (n>=2)
{
printf("symbol*n");
n=n-1;
}
return 0;
}
So it prints an inverted pyramid for height=5:
#####
####
###
##
#
Thank you in advance!!
Upvotes: 2
Views: 456
Reputation: 57388
In C, you also need to handle the memory you use. So if you wanted a "---" string, you would also need to allocate space for that string. Once allocated the space, you would fill it with the given character.
And afterwards, you'd have to free the area.
So:
char *charmul(char c, int n)
{
int i;
char *buffer; // Buffer to allocate
buffer = malloc(n+1); // To store N characters we need N bytes plus a zero
for (i = 0; i < n; i++)
buffer[i] = c;
buffer[n] = 0;
return buffer;
}
Then we'd need to add error checking:
char *charmul(char c, int n)
{
int i;
char *buffer; // Buffer to allocate
buffer = malloc(n+1); // To store N characters we need N bytes plus a zero
if (NULL == buffer)
return NULL;
for (i = 0; i < n; i++)
buffer[i] = c;
buffer[n] = 0;
return buffer;
}
Your source would become:
#include <stdio.h>
// charmul here
int main (void)
{
int height=0;
int n=0;
char symbol='#';
printf("Height: ");
scanf("%d",&height);
n=height+1;
while (n>=2)
{
char *s;
s = charmul(symbol, n);
printf("%s\n", s);
free(s); s = NULL;
n=n-1;
}
return 0;
}
An alternative implementation would seek to reduce the number of malloc
's, to enhance performance. To do so you'd need to also pass to the function a pointer to the previous buffer, which, if shorter, could be recycled with no need for a further malloc
, and if longer, would be free
'd and reallocated (or one could use realloc
). You would then do a free()
only of the last nonrecycled value:
char *charmul_recycle(char c, int n, char *prevbuf)
{
int i;
if (prevbuf && (n > strlen(*prevbuf)))
{
free(prevbuf); prevbuf = NULL;
}
if ((NULL == prevbuf)
{
prevbuf = malloc(n+1); // To store N characters we need N bytes plus a zero
if (NULL == prevbuf)
return NULL;
}
for (i = 0; i < n; i++)
prevbuf[i] = c;
prevbuf[n] = 0;
return prevbuf;
}
char *buffer = NULL;
while(n > 2)
{
buffer = charmul_recycle(symbol, n, buffer);
if (NULL == buffer)
{
fprintf(stderr, "out of memory\n");
abort();
}
printf("%s\n", buffer);
n--;
}
Of course the whole thing can be done with a single straight allocation and a progressive shortening of the string (by placing s[n]
to be zero), but then we wouldn't be using the "generating multiple character" features:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void)
{
char *string;
int height=0;
int n=0;
char symbol='#';
printf("Height: ");
scanf("%d",&height);
n=height+1;
string = malloc(n); // allocate just enough memory (n is height+1)
memset(string, symbol, n); // fill string with symbols
while (--n) // with n ever decreasing...
{
string[n] = 0; // Truncate string after n characters
printf("%s\n", string); // output string
}
free(string); // string = NULL; // finally free the string
return 0;
}
Update (thanks to Jonathan Leffler): above, there's a potentially dangerous "overoptimization". Immediately before each use of string
, string
is correctly zero-terminated ("string[n] = 0;
"). But it remains true that I have allocated a string variable and filled it with stuff, and did not immediately zero-terminate it. In the above code, it all works out perfectly. It's still bad coding practice, because if the code was reused and the cycle removed, and the string used for some other purpose (which in this case is unlikely, but still...), the nonterminated string
might become a subtle bug.
The quickest fix is to slap a termination after the allocation:
string = malloc(n); // allocate just enough memory (n is height+1)
memset(string, symbol, n-1); // fill string with symbols
string[n-1] = 0; // zero-terminate string
I've now wandered far from the original topic, but this would mean that in this instance the string is correctly zero-terminated twice. To avoid this, the code can be rewritten into a "cut and paste safe" version, also more clearly showing the extra zero as addition to n:
n=height; // Number of characters
string = malloc(n+1); // Allocate memory for characters plus zero
memset(string, symbol, n); // Store the characters
string[n] = 0; // Store the zero
while (n) // While there are characters
{
printf("%s\n", string); // Print the string
string[--n] = 0; // Reduce it to one character less than before
}
The cycle now accepts any valid string with meaningful n
, and if it is removed, the string is left in a useable state.
Upvotes: 0
Reputation: 753575
There isn't a built-in way to repeat the output like that. You have to code it yourself.
void multiputchar(char c, size_t count)
{
for (int i = 0; i < count; i++)
putchar(c);
}
For a library function, you might care about whether putchar()
fails, so you might be better to write:
int multiputchar(char c, size_t count)
{
for (int i = 0; i < count; i++)
{
if (putchar(c) == EOF)
return(EOF);
}
return (unsigned char)c;
}
But if the return value will always be ignored, the first is simpler. The cast is necessary to ensure that if your char
type is signed, you can tell the difference between a failure and successful output of ÿ (y-umlaut, U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS, 0xFF in 8859-1 and related code sets).
Upvotes: 2