nice way to make a pyramid with numbers >10 - c

I'm new to C and programming in general. I wanted to create a pyramid of numbers I have seen on a class test. I managed to do it, but the problem is that when the numbers get over 9, the pyramid gets terrific. this is what I wanted to achieve without writing a lot of IFs
my code:
#include <stdio.h>
int strlen(char *str);
int main(int argc, char **args){
char spaces[] = {"| "};
int i = 1, line = 1; //line number of numbers per line
while(spaces[strlen(spaces)-1] != '|'){
printf("%s", spaces);
for(int k = 0; k < line; k++){
printf("%d", i);
i++;
}
printf("\n");
spaces[strlen(spaces)-1] = '\0';
line += 2;
}
}
int strlen(char *str){
int i = 0;
while(*(str + i))
i++;
return i;
}

You showed what you wanted to achieve without writing a lot of IFs: print the pyramid of numbers with a field width of 6. Your principal approach was right: in each line, first print the leading spaces, then print the numbers. What is missing is to account for the field width of the leading spaces as well as the numbers themselves. This can be done e. g. by changing your while loop to
int lines = 16; // how many lines you want
while (lines--)
{
// in this line, we need leading spaces for `lines` numbers
printf("%*s", lines*6, ""); // you chose 6 spaces per number
// print each number with the chosen width
for (int k = 0; k < line; k++) printf("%-6d", i++);
puts("");
line += 2;
}

Related

Digit Frequency calculating code in C not working

So, I was writing this code for counting the digit frequency i.e. the number of times the digits from 0-9 has appeared in a user inputted string(alphanumeric). So, I took the string, converted into integer and tried to store the frequency in "count" and print it but when I run the code, count is never getting incremented and the output comes all 0s. Would be grateful if anyone points out in which part my logic went wrong.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
// takes string input
char *s;
s = malloc(1024 * sizeof(char));
scanf("%[^\n]", s);
s = realloc(s, strlen(s) + 1);
//turns the string to int
int x = atoi(s);
int temp = x, len = 0;
//calculates string length
while (x != 0) {
x = x / 10;
len++;
}
x = temp;
//parses through the string and matches digits with each number
for (int j = 0; j < 10; j++){
int count = 0;
for(int i = 0; i < len; i++){
if(x % 10 == j){
count++;
}
x = x / 10;
}
x = temp;
printf("%d ", count);
}
return 0;
}
To write a correct and reasonable digit-counting program:
Do not allocate any buffer for this.
Create an array to count the number of times each digit occurs. The array should have ten elements, one for each digit.
Initialize the array to zero in each element.
In a loop, read one character at a time.
Leave the loop when the read routine (such as getchar) indicates end-of-file or a problem, or, if desired, returns a new-line or other character you wish to use as an end-of-input indication.
Inside the loop, check whether the character read is a digit. If the character read is a digit, increment the corresponding element of the array.
After the loop, execute a new loop to iterate through the digits.
Inside that loop, for each digit, print the count from the array element for that digit.
Your approach is way to complicated for a very easy task. This will do:
void numberOfDigits(const char *s, int hist[10]) {
while(*s) {
if(isdigit(*s))
hist[*s - '0']++;
s++;
}
}
It can be used like this:
int main(void) {
char buf[1024];
int hist[10];
fgets(buf, sizeof buf, stdin);
numberOfDigits(s, hist);
for(int i=0; i<10; i++)
printf("Digit %d occurs %d times\n", i, hist[i]);
}
This can also be quite easily achieved without a buffer if desired:
int ch;
int hist[10];
while((ch = getchar()) != EOF) {
if(isdigit(ch))
hist[ch - '0']++;
}
#include <stdio.h>
int main(void) {
int input = 1223330;
int freq[10] = {0};
input = abs(input);
while(input)
{
freq[input%10]++;
input /= 10;
}
for(int i=0; i<10; ++i)
{
printf("%d: %.*s\n", i, freq[i], "*************************************************");
}
return 0;
}
Output:
Success #stdin #stdout 0s 5668KB
0: *
1: *
2: **
3: ***
4:
5:
6:
7:
8:
9:
This app is currently limited by the size of an int (approximately 9 or 10 digits).
You can update it to use a long long easily, which will get you to about 19 digits.

scanf makes first element null in C

I am trying to get 2, length of 8, inputs. With the code I have, my problem is that bit1[0] is null. Where is my problem ?
This is kind of debug I have, to see it null-ifies the first element
PS: Dont mind about the calculations I have at the bottom of the code. I am trying to create a calculator that does binary summation. I still couldn't try my code, it can be meaningless to do it in the way I do. But its not the question I am asking so please avoid giving advice on that one. Thank you.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char bit1[8];
char bit2[8];
int result[8];
int sum;
int dig1;
int dig2;
printf("Enter first binary number without any whitespaces!\t");
scanf("%s", bit1);
printf("Enter second binary number without any whitespaces!\t");
scanf(" %s", bit2);
int handle = 0;
puts(bit1);
puts(bit2);
for(int i = 7; i >= 0; i--){
//printf("%d", bit1[i] - '0');
dig1 = bit1[i] - '0';
dig2 = bit2[i] - '0';
if(dig1 + dig2 + handle < 2){
result[i] = dig1 + dig2 + handle;
handle = 0;
} else {
result[i] = (dig1 + dig2 + handle)%2;
handle = 1;
}
printf("dig1: %d\tdig2: %d\thandle: %d\n", dig1, dig2, handle);
printf("%d is added!\n", result[i]);
}
for(int i = 0; i < 8; i++){
printf("%c", result[i]);
}
printf(" And carry is: %d", handle);
return 0;
}
UPDATED
Working code is:
char bit1[9];
char bit2[9];
int result[8];
int sum;
int dig1;
int dig2;
printf("Enter first binary number without any whitespaces!\t");
scanf("%8s", bit1);
printf("Enter second binary number without any whitespaces!\t");
scanf("%8s", bit2);
Rest are the same
When you want to get a string (that is exactly 8 characters) from user input you should write:
char string[9];
scanf("%8s", string);
The reason you need char string[9] and not char string[8] is because a C-string always ends in the null-character (0 or '\0'). Thus, you need one extra space to store that null-character.
Don't forget to always use %8s. If the user input then exceeds the 8 characters you want, C will automatically cut off the exceeding characters.

Why did I get Wrong Answer on this problem(Uva OJ 455)

I'm crazy about this problem (Uva 455):
A character string is said to have period k if it can be formed by
concatenating one or more repetitions of another string of length k.
For example, the string ”abcabcabcabc” has period 3, since it is
formed by 4 repetitions of the string ”abc”. It also has periods 6
(two repetitions of ”abcabc”) and 12 (one repetition of
”abcabcabcabc”).
Write a program to read a character string and
determine its smallest period.
Input
The first line oif the input file
will contain a single integer N indicating how many test case that
your program will test followed by a blank line. Each test case will
contain a single character string of up to 80 non-blank characters.
Two consecutive input will separated by a blank line.
Output
An
integer denoting the smallest period of the input string for each
input. Two consecutive output are separated by a blank line.
Sample Input
1
HoHoHo
Sample Output
2
I've checked all test cases I could imagine and all of them returned correct result, but I still get Wrong Answer on the online judge. Where did I go wrong?
(English is not my native language; please excuse typing or syntax errors.)
#include <stdio.h>
#include <string.h>
#define maxn 85
int check(char* s, int per){
for(int i = 0; i < strlen(s) - per; i++){
if(s[i + per] != s[i]) return 0;
}
return 1;
}
int main(){
int T;
scanf("%d", &T);
char s[maxn];
while(T--){
scanf("%s", s);
int len = strlen(s);
bool OK = false;
for(int i = 1; i <= len/2 && (len % i == 0); i++){//That's wrong.
if(check(s, i)){
printf("%d\n", i);
OK = true;
break;
}
}
if(!OK) printf("%d\n", len);
if(T) printf("\n");
}
return 0;
}
The problem is in for(int i = 1; i <= len/2 && (len % i == 0); i++). You are stopping as soon as you encounter an i that doesn't divide len, instead of skipping it.
Write the loop as:
for (int i = 1; i <= len/2; i++) {
if (len % i != 0) continue;
...
}

Unable to extract full number from string in C program

Program to calculate the average of n numbers given by the user.
Okay so I have this program whose purpose is what you have read above. Its output is not quite right. I figured out what the problem is but couldn't find the solution as I am not a leet at programming (newbie actually). Here is the code:
#include <stdio.h>
int main(void) {
char user_data[100];
long int sum = 0;
double average;
unsigned int numbers_count = 0;
for (int i = 0; i <= 99; ++i)
user_data[i] = 0;
unsigned int numbers[100];
for (int i = 0; i <= 99; ++i)
numbers[i] = 0;
printf("Please enter the numbers:");
fgets(user_data, sizeof(user_data), stdin);
int i = 0;
while (user_data[i] != 0) {
sscanf(user_data, "%u", &numbers[i]);
++i;
}
i = 0;
while (numbers[i] != 0) {
sum += numbers[i];
++i;
}
i = 0;
while (numbers[i] != 0) {
++numbers_count;
++i;
}
average = (float)sum / (float)numbers_count;
printf("\n\nAverage of the entered numbers is: %f",average);
return 0;
}
Now here comes the problem.
When I enter an integer say 23, it gets stored into the user_data in two separate bytes. I added a loop to print the values of user_data[i] to figure out what was wrong.
i = 0;
while (i <= 99) {
printf("%c\n",user_data[i]);
++i;
}`
and the result was this
user_data insight
This was the first problem, here comes the second one.
I added another loop same like the above one to print the numbers stored in numbers[100] and figure out what was wrong and here is the output. Here's a sample
numbers stored in numbers[]
Now my main question is
How to extract the full number from user_data?
I believe it could be helpful to layout user_data after the fgets() of "23" (assuming Linux or Mac new line):
+-----+-----+----+----+
| '2' | '3' | \n | \0 | .....
+-----+-----+----+----+
0 1 2 3
Note that user_data[0] does not contain 2 (the number 2)! It contains '2' (the character '2') whose code is (again, assuming Linux) 0x32 (in hex or 50 in decimal).
This is why your attempt to print the values of user_data[] have not been fruitful: you were trying to print the representation of the number, not the number itself.
To convert that string to the integer it represents, you can do something like:
num = atoi(user_data)
The function atoi() does the work for you. A more flexible function is strtol() which does the same but for long int (and also can handle string that represents numbers in a base that is not 10).
I hope this answers to your question: How to extract the full number from user_data?
There are some other points where you should clean up and simplify your code, but you can open another question in case you need help.
Try this:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int i;
char user_data[100];
long int sum = 0;
double average;
unsigned int numbers_count = 0;
for( i=0; i<= 99; ++i)
user_data[i] = 0;
unsigned int numbers[100];
for( i=0; i<= 99; ++i)
numbers[i] = 0;
printf("Please enter the numbers:");
fgets(user_data,sizeof(user_data),stdin);
//int p=0;//use with strtol(see further code)
i = 0;
int j;//this will store each number in numbers array.. so this is also the count of numbers stored - 1
for(j=0;;){
for(i=0;i<strlen(user_data);i++)
{
if(user_data[i]=='\n'){
break;
}
if(user_data[i]==' '){
j++;
i++;
//p=i;//to be used with strtol
}
numbers[j]=(numbers[j]*10)+((user_data[i]-48));//alternatively use => numbers[j]=strtol(user_data+p,NULL,10);
}
break;
}
i = 0;
while( i<=j)
{
sum += numbers[i];
++i;
}
average = (float)sum/(j+1);
printf("\n\nAverage of the entered numbers is: %f",average);
return 0;
}
Sample input
10 11 12
Sample output
11.00000000
I have shown two approaches to solve this:
One is straight-forward, subtract 48 from each char and add it to numbers array(ASCII manipulation) .
Other is to use strtol. Now strtol converts the number pointed by the char pointer(char array in this case) until the next char is not a number. So use pointer arithmetic to point to further numbers(like here I have added p(yeah I know p is not a good variable name, so does i and j!)).
There are more ways to solve like using atoi library functions.
regarding the posted code:
what happens if one of the numbers is zero?
What happens if the sum of the numbers exceeds the capacity of 'sum'
#include <stdio.h> // sscanf(), fgets(), printf()
#include <stdlib.h> // strtol()
#include <string.h> // strtok()
// eliminate the 'magic' number by giving it a meaningful name
#define MAX_INPUTS 100
int main(void)
{
// the array can be initialized upon declaration
// which eliminates the 'for()' loop to initialize it
// char user_data[100];
// and
// initialization not actually needed as
// the call to 'fgets()' will overlay the array
// and 'fgets()' always appends a NUL byte '\0'
char user_data[ MAX_INPUTS ];
long int sum = 0;
double average;
// following variable not needed
// unsigned int numbers_count = 0;
// following code block not needed when
// 'user_data[]' initialized at declaration
// for (int i = 0; i <= 99; ++i)
// user_data[i] = 0;
// not needed, see other comments
//unsigned int numbers[100];
// not needed, as 'numbers' is eliminated
// for (int i = 0; i <= 99; ++i)
// numbers[i] = 0;
printf("Please enter the numbers:");
// should be checking the returned value
// to assure it is not NULL
// And
// this call to 'fgets()' is expecting
// all the numbers to be on a single input line
// so that could be a problem
fgets(user_data, sizeof(user_data), stdin);
// the following two code blocks will not extract the numbers
// for a number of reasons including that 'sscanf()'
// does not advance through the 'user_data[]' array
// int i = 0;
// while (user_data[i] != 0) {
// sscanf(user_data, "%u", &numbers[i]);
// ++i;
// }
// i = 0;
// while (numbers[i] != 0) {
// sum += numbers[i];
// ++i;
// }
// suggest the following,
// which also eliminates the need for 'numbers[]'
// note: the literal " \n" has both a space and a newline
// because the user is expected to enter numbers,
// separated by a space and
// 'fgets()' also inputs the newline
int i = 0;
char *token = strtok( user_data, " \n");
while( token )
{
// not everyone likes 'atoi()'
// mostly because there is no indication of any error event
// suggest using: 'strtol()'
//sum += atoi( token );
sum += strtol( token, NULL, 10 ) // could add error checking
i++;
token = strtok( NULL, " \n" );
}
// the value assigned to 'numbers_count'
// is already available in 'i'
// suggest eliminate the following code block
// and
// eliminate the 'numbers_count' variable
// i = 0;
// while (numbers[i] != 0) {
// ++numbers_count;
// ++i;
// }
// 'average' is declared as a 'double',
// so the casting should be to 'double'
// and
// if incorporating the prior comment about 'numbers_count'
// average = (float)sum / (float)numbers_count;
average = (double)sum / (double)i'
// to have the text immediately displayed on the terminal
// place a '\n' at the end of the format string.
// without adding the '\n' the text only displays
// as the program exits
// printf("\n\nAverage of the entered numbers is: %f",average);
printf("\n\nAverage of the entered numbers is: %f\n",average);
return 0;
} // end function: main

How can I print multiple character with one printf?

I want to print multiple character using printf. My approach up to now is this-
#include <stdio.h>
int main()
{
printf("%*c\n", 10, '#');
return 0;
}
But this only prints 9 spaces before the #.
I want to print it like this-
##########
I am unable to figure out how to do this. Please help me?
You can not use printf like that to print repetitive characters in Ansi C. I suggest you to use a loop like this -
#include <stdio.h>
int main()
{
int i;
for(i = 0; i < 10; i++) putchar('#');
return 0;
}
Or if you have absolutely no desire to use loops, you can do something like this-
#include <stdio.h>
int main()
{
char out[100];
memset(out, '#', 10);
out[10] = 0;
printf("%s", out);
return 0;
}
By the way, using printf like this also works-
#include <stdio.h>
int main()
{
printf("%.*s", 10, "############################################");
return 0;
}
I think the best approach, if you have an upper limit to the number of characters to be output is:
printf("%.*s", number_of_asterisks_to_be_printed,
"**********************************************************************");
I think this will also be the most efficient, portable way to do that.
this will print ten # characters, followed by a newline
char tenPounds[] = "##########";
printf( "%s\n", tenPounds);
I am working on a similar problem in "The C Programming Language" book (exercises 1-13 and 1-14). My own program, to start simply, is to count the occurrences of the digits 0 to 9 in a given input, and print a horizontal histogram made of '=' bars according to each count.
To do this, I created the following program;
main() {
int c, ix, k;
int nDigit[10];
//Instantiate zero values for nDigits array
for(ix = 0; ix < 10; ix++) {
nDigit[ix] = 0;
}
//Pull in input, counting digit occurrences and
//incrementing the corresponding value in the nDigit array
while ((c = getchar()) != EOF) {
if (c >= '0' && c <= '9') {
++nDigit[c-'0'];
}
}
//For each digit value in the array, print that many
//'=' symbols, then a new line when completed
for (ix = 0; ix < 10; ix++) {
k = 0;
while (k <= nDigit[ix]) {
putchar('=');
k++;
}
printf("\n");
}
}
Note that this is a work in progress. A proper histogram should include axes labels, and most importantly this program does not account for digits of zero count. If the input includes five 1's but no 0's, there is no visual way to show that we have no zeros. Still, the mechanism for printing multiple symbols works.

Resources