How make a bar chart in C? - c

I have written a program that prints out the integers in the same order as the input with 5 numbers per line. That is, the first 5 integers will be printed in the first line; the next 5 integers in the next line; and so on. I was also was trying to print out the numbers in a bar chart format, like,
81-105 ( 1) x
56-80 ( 5) xxxxx
6-11(5) xxxxx
-1-5 (3) xxx
My program:
cntr=0;
while (fscanf(in, "%d", &a[i]) != EOF)
{i++;
fprintf(out, "%d-%d (%d) %s\n", A, B, k, x, cntr);
fprintf(out, "%d\n", k, cntr);
fprintf(out, "x", a[i]);
i++;
}
fprintf(out, "1864-2336 (%d)%s\n", k, x);
fprintf(out, "1391-1863 (%d)%s\n", k, x);
fprintf(out, "918-1390 (%d)%s\n", k, x);
fprintf(out, "445-917 (%d)%s\n", k, x);
fprintf(out,"-28-444 (%d)%s\n", k, x);
fclose(in);
fclose(out);
return 0;
}

You don't have to use a loop to print out your x's. You can declare a single string of x's that's as long as the maximum you will need, and then use a size specification in the printf call to control how many are printed. Here's a simple example to illustrate what I mean:
#include <stdio.h>
#include <string.h>
int main(void)
{
char maxBar[] = "xxxxxxxxxx";
size_t i;
for (i = 0; i < strlen(maxBar); i++)
{
printf("%lu: %-*.*s\n", (unsigned long) i, strlen(maxBar), i, maxBar);
}
return 0;
}
The output should look as follows:
0: __________
1: x_________
2: xx________
3: xxx_______
4: xxxx______
5: xxxxx_____
etc., where _ represents a space character.
A * in a printf conversion specifier indicates that a field width or precision specification is being passed as an argument to printf. Writing
printf("%-*.*s\n", 10, 2, "test");
is the same as writing
printf("%-10.2s\n", "test");
which, reading left to right, means
-: Left-justify the output
10: Minimum field width is 10 characters
.2: Precision (max number of chars printed) is 2
So the output looks like
te________
where _ represents a space character.
So, assuming you know how big your bar needs to be in advance, you can write something like
for (i = 0; i < k; i++)
{
printf("%d-%d (%d) %*.*s\n", lo[k], hi[k], ct[k], strlen(maxBar), ct[k], maxBar);
}

just do a loop to print the amount of x's you need
   fprintf(out, "1864-2336 (%d)%s\n", k, x);
for(x=k;x>0;x--)
fprint(out,"%s","x");
fprintf(out,"\n");
Cheers!
/B2S

There are many ways to do this
It seems you already have somewhere declared an array of the values that user enters. a[]
In order to calculate the bar chart you could after user has entered all values, sort that array (e.g. using qsort()) then traverse the array checking the number of same values that occur in the array - this would be the number of '*' to print out
I think you should first let user enter the values, then do the output.
The code you show looks wrong, e.g. you increment 'i' twice in the while loop. You use the a[i] after the increment so it will not have the read value.
Also its good to use fgets/atoi instead when reading numbers that way invalid numbers will not cause your program to potentially crash.

Related

How to find the total number of a certain element in an array(C)

I'm trying to create a complete C program to read ten alphabets and display them on the screen. I shall also have to find the number of a certain element and print it on the screen.
#include <stdio.h>
#include <conio.h>
void listAlpha( char ch)
{
printf(" %c", ch);
}
int readAlpha(){
char arr[10];
int count = 1, iterator = 0;
for(int iterator=0; iterator<10; iterator++){
printf("\nAlphabet %d:", count);
scanf(" %c", &arr[iterator]);
count++;
}
printf("-----------------------------------------");
printf("List of alphabets: ");
for (int x=0; x<10; x++)
{
/* I’m passing each element one by one using subscript*/
listAlpha(arr[x]);
}
printf("%c",arr);
return 0;
}
int findTotal(){
}
int main(){
readAlpha();
}
The code should be added in the findTotal() element. The output is expected as below.
Output:
List of alphabets : C C C A B C B A C C //I've worked out this part.
Total alphabet A: 2
Total alphabet B: 2
Total alphabet C: 6
Alphabet with highest hit is C
I use an array to count the number of the existence of each character,
I did this code but the display of number of each character is repeated in the loop
int main()
{
char arr[100];
printf("Give a text :");
gets(arr);
int k=strlen(arr);
for(int iterator=0; iterator<k; iterator++)
{
printf("[%c]",arr[iterator]);
}
int T[k];
for(int i=0;i<k;i++)
{
T[i]=arr[i];
}
int cpt1=0;
char d;
for(int i=0;i<k;i++)
{int cpt=0;
for(int j=0;j<k;j++)
{
if(T[i]==T[j])
{
cpt++;
}
}
if(cpt>cpt1)
{
cpt1=cpt;
d=T[i];
}
printf("\nTotal alphabet %c : %d \n",T[i],cpt);
}
printf("\nAlphabet with highest hit is : %c\n",d,cpt1);
}
There is no way to get the number of elements You write in an array.
Array in C is just a space in the memory.
C does not know what elements are actual data.
But there are common ways to solve this problem in C:
as mentioned above, create an array with one extra element and, fill the element after the last actual element with zero ('\0'). Zero means the end of the actual data. It is right if you do not wish to use '\0' among characters to be processed. It is similar to null-terminated strings in C.
add the variable to store the number of elements in an array. It is similar to Pascal-strings.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 10
char array[ARRAY_SIZE + 1];
int array_len(char * inp_arr) {
int ret_val = 0;
while (inp_arr[ret_val] != '\0')
++ret_val;
return ret_val;
}
float array_with_level[ARRAY_SIZE];
int array_with_level_level;
int main() {
array[0] = '\0';
memcpy(array, "hello!\0", 7); // 7'th element is 0
printf("array with 0 at the end\n");
printf("%s, length is %d\n", array, array_len(array));
array_with_level_level = 0;
const int fill_level = 5;
int iter;
for (iter = 0; iter < fill_level; ++iter) {
array_with_level[iter] = iter*iter/2.0;
}
array_with_level_level = iter;
printf("array with length in the dedicated variable\n");
for (int i1 = 0; i1 < array_with_level_level; ++i1)
printf("%02d:%02.2f ", i1, array_with_level[i1]);
printf(", length is %d", array_with_level_level);
return 0;
}
<conio.h> is a non-standard header. I assume you're using Turbo C/C++ because it's part of your course. Turbo C/C++ is a terrible implementation (in 2020) and the only known reason to use it is because your lecturer made you!
However everything you actually use here is standard. I believe you can remove it.
printf("%c",arr); doesn't make sense. arr will be passed as a pointer (to the first character in the array) but %c expects a character value. I'm not sure what you want that line to do but it doesn't look useful - you've listed the array in the for-loop.
I suggest you remove it. If you do don't worry about a \0. You only need that if you want to treat arr as a string but in the code you're handling it quite validly as an array of 10 characters without calling any functions that expect a string. That's when it needs to contain a 0 terminator.
Also add return 0; to the end of main(). It means 'execution successful' and is required to be conformant.
With those 3 changes an input of ABCDEFGHIJ produces:
Alphabet 1:
Alphabet 2:
Alphabet 3:
Alphabet 4:
Alphabet 5:
Alphabet 6:
Alphabet 7:
Alphabet 8:
Alphabet 9:
Alphabet 10:-----------------------------------------List of alphabets: A B C D E F G H I J
It's not pretty but that's what you asked for and it at least shows you've successfully read in the letters. You may want to tidy it up...
Remove printf("\nAlphabet %d:", count); and insert printf("\nAlphabet %d: %c", count,arr[iterator]); after scanf(" %c", &arr[iterator]);.
Put a newline before and after the line of minus signs (printf("\n-----------------------------------------\n"); and it looks better to me.
But that's just cosmetics. It's up to you.
There's a number of ways to find the most frequent character. But at this level I recommend a simple nested loop.
Here's a function that finds the most common character (rather than the count of the most common character) and if there's a tie (two characters with the same count) it returns the one that appears first.
char findCommonest(const char* arr){
char commonest='#'; //Arbitrary Bad value!
int high_count=0;
for(int ch=0;ch<10;++ch){
const char counting=arr[ch];
int count=0;
for(int c=0;c<10;++c){
if(arr[c]==counting){
++count;
}
}
if(count>high_count){
high_count=count;
commonest=counting;
}
}
return commonest;
}
It's not very efficient and you might like to put some printfs in to see why!
But I think it's at your level of expertise to understand. Eventually.
Here's a version that unit-tests that function. Never write code without a unit test battery of some kind. It might look like chore but it'll help debug your code.
https://ideone.com/DVy7Cn
Footnote: I've made minimal changes to your code. There's comments with some good advice that you shouldn't hardcode the array size as 10 and certainly not litter the code with that value (e.g. #define ALPHABET_LIST_SIZE (10) at the top).
I have used const but that may be something you haven't yet met. If you don't understand it and don't want to learn it, remove it.
The terms of your course will forbid plagiarism. You may not cut and paste my code into yours. You are obliged to understand the ideas and implement it yourself. My code is very inefficient. You might want to do something about that!
The only run-time problem I see in your code is this statement:
printf("%c",arr);
Is wrong. At this point in your program, arr is an array of char, not a single char as expected by the format specifier %c. For this to work, the printf() needs to be expanded to:
printf("%c%c%c%c%c%c%c%c%c%c\n",
arr[0],arr[1],arr[2],arr[3],arr[4],
arr[5],arr[6],arr[7],arr[8],arr[9]);
Or: treat arr as a string rather than just a char array. Declare arr as `char arr[11] = {0};//extra space for null termination
printf("%s\n", arr);//to print the string
Regarding this part of your stated objective:
"I shall also have to find the number of a certain element and print it on the screen. I'm new to this. Please help me out."
The steps below are offered to modify the following work
int findTotal(){
}
Change prototype to:
int FindTotal(char *arr);
count each occurrence of unique element in array (How to reference)
Adapt above reference to use printf and formatting to match your stated output. (How to reference)

Large numbers, sums, and data conversions

I've been pouring over my code (which does not work) now for quite some time. It is for a Project Euler problem in which one is given a very large sum to find, and then required to print the first ten digits of said sum. (The problem can be found here: https://projecteuler.net/problem=13)
I have run several 'tests' where I add print commands to see various values at various points in the code. When I run the code, I have gotten anything from symbols to ten digit numbers that should be single digits.
Anyways. My question is this: is this a type conversion issue or is there some other glaring issue with my method that I'm missing? I've been studying type conversions trying to find a fix, but to no avail.
Thank you for any help!
The code is as follows:
// this is a program to find a very large sum of many very large numbers
#include <stdio.h>
#include <math.h>
int main()
{
//declare all ints needed
int i;
int j;
int d; // digit, need to add 48
int placesum; // sum of addition in _'s place (1's, 10's, 10000's)
int place; // final place value
int c = 0, tens = 1, otherc; // counters for start finder
int a = 0; // another counter
//declare all arrays
char numarray[101][51]; //array of strings containing all 100 numbers
char sum[100];
printf("please save data to largesumdata.txt\n\n press enter when ready");
getchar();
// THE PROBLEM- I don't know how to get my data into my program // FIXED
// using fscanf()
FILE *pf; // declare a pointer to the file
pf = fopen("largesumdata.txt", "r"); // trys to open file // "r" means read only
if(pf == NULL)
printf("Unable to open file, sorry Jar\n");
else
{
for(j = 0; j < 100; j++)
fscanf(pf, "%s\n", &numarray[j]); // fscanf(pointer, data type, location)
}
//TESTING
//printf("You have reached point A\n");//POINT A WAS REACHED
//TESTING
//TESTING
//printf("Check1, %c\n", numarray[45][23]);
//TESTING
//TESTING
//printf("%c\n", numarray[90][22]);//Can successfully call characters from array
//TESTING
// (Brute force attempt) //I NEVER MESS WITH numarray WHY IS IT CHANGING
for(i = 49; i >= 0; i--)
{
//printf("%d\n", d);
for(j = 0; j < 100; j++)
{
d = (int)numarray[j][i] - 'o';
//printf("%d\n", d);
//holdup// d -= 48; // ASCII conversion // could also write "d = d-48"
//printf("%d\n", d);
placesum += d; // could also write "placesum = placesum + d"
//printf("%d\n", placesum);
}
place = placesum % 10;
placesum = placesum / 10; // takes "10's place" digit for next column
// now need to put 'int place' into 'char sum'
sum[i+5] = (char)place+'0'; // ASCII conversion // "+5" for extra space //HERE not properly stored in sum
}
//TESTING
//printf("Check2, %c\n", numarray[45][23]);
//TESTING
//TESTING
//printf("You have reached point B\n");//POINT B WAS REACHED
//TESTING
// find out where sum starts
for(c=0; c<10; c++)
if(sum[c] != '0')
break;
//TESTING
//printf("You have reached point C\n"); //POINT C WAS REACHED
//TESTING
otherc = 4-c;
printf("The first 10 digits of the sum of all those f***ing numbers is....\n");
printf("%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", sum[otherc, otherc+1, otherc+2, otherc+3, otherc+4, otherc+5, otherc+6, otherc+7, otherc+8, otherc+9]);
//%c-%c-%c-%c-%c-%c-%c-%c-%c-%c //copy and paste purposes
//%d-%d-%d-%d-%d-%d-%d-%d-%d-%d // ^^^^^
getchar();
return 0;
}
P.S. I apologize if my plethora of notes is confusing
You are using wrong form to print an array in C.
sum[otherc, otherc+1, otherc+2, otherc+3, otherc+4, otherc+5, otherc+6, otherc+7, otherc+8, otherc+9] -> This actually decays to sum[otherc+9] because C treats , as an operator.
To print value at each array index, you should use it like this: sum[otherc], sum[otherc+1], sum[otherc+2],..
To read more about C's , (comma) operator, you can begin here
In your printf as I explained above, the first format specifier %d gets sum[otherc + 9], since sum[otherc,...,otherc+9] is actually a single number and that is otherc + 9th index of array sum. You do not provide anything to print for other format specifiers, hence you get garbage.
After a while I revisited my code, and realized that I was working with numbers upwards of 10 million. I had a mix of int, long int, and long long int variables declared.
I re-analyzed which was which, and made sure that all variables could handle the data it needed to (after looking at this handy link, showing what max integer sizes are for different data types.
Before I had been using the wrong ones, and going over the max values returned incorrect values, causing my program to crash during run time.
Lesson here: Check your data types!

Abundant Numbers in C

I have a programming assignment that I'm really stumped on. The question is:
Write a program that reads in a list of numbers, and for each number, determines and prints out whether or not that number is abundant.
Input Specification
1. The first integer input will be a positive integer, n, indicating the number of test cases coming next.
2. The next n inputs are single positive integers each, and for each you are to determine whether the number is abundant or not.
Output Specification
Output a line with one of the two the following formats for each input number:
Test case #t: X is abundant.
Test case #t: X is NOT abundant.
Right now this is all I have written, I'm not sure how to figure out the abundant number part.
#include <stdio.h>
#include <stdlib.h>
int main(){
int n, i, array [] = {n};
printf("Please enter n followed by n numbers:");
scanf(" %d", &n);
for (i=0; i<n; i++){
scanf(" %d", &array[n]);
}
system ("pause");
return 0;
}
Abundant numbers is a very simple concept - you can find the information in Wikipedia: http://en.wikipedia.org/wiki/Abundant_number
I think if you want just any solution (not the fastest) you can just explicitly find all divisors and their sum for each number.
First of all...
int n, i, array [] = {n};
doesn't do what you think it does; it declares array to hold exactly 1 element, and that one element is initialized to the value of n (which hasn't been initialized itself, so the value will be indeterminate). It will not be able to hold n values.
Based on the specification you've given, you shouldn't actually need to store the entire list of input numbers; you should be able to read one, test for abundance, then read the next, test for abundance, etc. So the structure of your code will be something like:
int n = 0;
...
printf("Please enter n followed by n numbers:");
scanf(" %d", &n);
for (int i = 0; i < n; i++ )
{
int candidate;
scanf( "%d", &candidate ); // read the next input
printf( "%d is%s abundant\n",
candidate,
!test( candidate ) ? " NOT" : "" ); // test the next input and
// print NOT if the test fails
}
The printf statement is a compact way of writing
if ( test( candidate ) == 0 )
printf( "%d is NOT abundant\n", candidate );
else
printf( "%d is abundan\n", candidate );
The test function is something you're going to need to figure out for yourself, but the outline of it will be
Find the proper divisors of the input value
Sum them together
Compare that result to the input
Return 1 is the result is greater than the input, 0 otherwise.

keep getting ascii value where char is expected

When a coordinate is selected, it should be replaced with a "~". However, it's being replaced with the ascii value for the ~ instead (126). I tried a few different things, but I always get the 126 instead of the ~. Any ideas?
Thanks for the help!
int board_is_empty(int N, int board[ROWS][COLS])
{
int i = 0, j = 0;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
if (board[i][j] != '~')
{
return 0;
}
}
}
return 1;
}
//updates the board to replace each selected coordinate with a ~.
//returns nothing
void update_board (int board[ROWS][COLS], int row_target, int column_target)
{
board[row_target][column_target] = '~';
}
int main(void)
{
int game_board[ROWS][COLS] = {0};
int rows, columns = 0;
int players_turn = 1, target_column = -1, target_row = -1, value = 0;
int row_selection = 0, column_selection = 0;
int i = 0;
initialize_game_board(game_board);
display_board(game_board);
generate_starting_point(game_board, &rows, &columns);
printf ("\nPlease hit <Enter> to continue.\n");
getchar ();
while (board_is_empty(ROWS, game_board) != 1)
{
select_target (&target_row, &target_column, players_turn);
value += game_board[target_row][target_column];
update_board (game_board, target_row, target_column); //should cause the coordinates at target_row && target_column to be replaced with a ~
display_board(game_board);
}
printf("\n%d", value);
}
'~' is a character and you have declared board as a two dimensional integer array.
so when you write board[row_target][column_target] = '~';
it convert '~' it into integer i.e into its ascii value which is 126
and there for it becomes board[row_target][column_target] = 126
I will suggest make board as two dimensional character array. Hopefully it will solve your problem.
And in case if you want it as integer only then consider 126 as a special no which means '~' by declaring
For storing your coordinates, you are using an integer array. When you execute
board[row_target][column_target] = '~'; tilde's ascii value (126) is assigned to LHS. There is no way you can assign a character to an integer value. I think you should use some special number rather than tilde. If I were you, I would use INT_MIN or INT_MAX.
There isn't a difference between the character '~' and the number 126 as far as the C language is concerned, '~' == 126.
(You used "~" which i would normally use for a string, but i assume you don't actually mean that).
If you want to display a value, you have to use the correct format string. %d is for decimal integers, %c would be for characters (the variable holding the value should also be a char)
In C, chars are just integers. At output time they are represented as characters but internally they hold just the ASCII code of that character.
Since your board is a matrix of int's, when you assign '~' you are effectively assigning the number 126 to a position of the board. If you check that position, the expected result is to get an int equal to 126.
However, if you want to see that value as a character, you can do it by casting that number into a char:
printf("%c", value);
Take a look:
#include <stdio.h>
int main()
{
int i = '~';
char c = '~';
printf("Integer: %d\n", i); /* outputs: 126 */
printf("Char: %c\n", c); /* outputs: ~ */
printf("Integer casted to char: %c\n", i); /* outputs: ~ */
}
That is, your value is right. You just need to get the representation you want. (If you want to be able to store the value 126 in the board and the character ~ at the same time, then you're out of luck because for C they are the same thing -you can use some other value that you know that the board isn't going to hold, like -1 or something like that).
Update:
So, if I didn't get it wrong what you're trying to do is to read numbers from a bidimensional matrix of random integers and mark each one as you go reading them.
If that is what you're trying to achieve, then your idea of using '~' to mark the read positions isn't going to work. What I meant before is that, in C, 126 and the character '~' are the exact same thing. Thus, you won't be able to differentiate those positions in which you have written a '~' character and those ones in which a random 126 is stored by chance.
If you happen to be storing positive integers in your array, then use -1 instead of '~'. That will tell you if the position has been read or not.
If you are storing any possible random integer, then there is nothing you can store in that array that you can use to mark a position as read. In this case a possible solution is to define your array like this:
typedef struct {
int value;
char marked;
} Position;
Position board[ROWS][COLS];
Thus, for each position you can store a value like this:
board[row][col].value = 23123;
And you can mark it as read like this:
board[row][col].marked = 'y';
Just, don't forget to mark the positions as not read (board[row][col].marked = 'n';) while you fill the matrix with random integers.

Pascal's Triangle returning nonsense values

This is a homework project I was assigned some time ago... I've been successful in getting this far on my own, and the only hiccup I have left is (I believe) an issue with data types and overflow.
I've tried changing over to unsigned and double, and the code complies and still accepts input in the terminal, but it seems to hang up after that... nothing is printed and it looks like it's caught in a loop.
Here is the code...
/* pascaltri.c
* A program that takes a single integer as input and returns the nth line of
* Pascal's Triangle. Uses factorial() function to help find items of
* individual entries on a given row.
*/
#include <stdio.h>
#include <stdlib.h>
long factorial(long i)
{
long fact = 1;
while(i > 1)
{
fact = fact * i;
i = i - 1;
}
return fact;
}
main(void)
{
long n;
long *nPtr;
nPtr = &n;
scanf(" %i", nPtr);
if (n >= 0)
{
long k;
long *kPtr;
kPtr = &k;
for(k = 0; k <= n; k++)
{
long ans;
long *ansPtr;
ansPtr = &ans;
ans = factorial(n) / (factorial(k) * factorial(n - k));
printf("\n %i", ans);
}
return 0;
}
return 0;
}
It's not perfect or pretty, but it works up to an input of 13 (that is, row 14) of the triangle. Beyond that I start getting gibberish and even negative values sprinkled throughout the returns... much larger values break the code and return nothing but an exit error message.
Any ideas on how I can correct this problem? I've been staring at the screen for much to long to really see anything myself. Also, it's not essential, but I would like to print my return values on one line, rather than having them separated by a newline character.
1 5 10 10 5 1
Would the easiest way be to load the values into an array as they are computed, and then print the array? Or is there a built-in way I can tell the print statement to occur on only one line?
You are suffering from integer overflow. You may need to find a different approach to the algorithm to avoid having to calculate the large numbers.
In answer to your other point about the newline, you are explicitly printing the newline with the \n in your print statement. Remove it, and you will get answers printed on one line. You probably want to inlucde a final printf("\n"); at the end so the whole line is terminated in a newline.
Some other observations:
You don't need the first return 0; - the control will drop out of
the bottom of the if block and on to the second (should be only)
return 0; and not cause any problems.
You're declaring kPtr but not using it anywhere
You don't need to declare a separate variable nPtr to pass to scanf; you can pass &n directly.
For the garbage, you are most likely running into an integer overflow, that is, your calculated values become too large for the long data type. You should correct it by calculating your factorial function without explicitely calculating n!.
Change scanf(" %i", nPtr); to
scanf(" %ld", nPtr);
and printf("\n %i", ans); to
printf("\n %ld", ans);
to get printout on one line, use:
printf(" %ld", ans);
If you are using gcc, turn on warnings, i.e. use -Wall.

Resources