I am trying to create a function that scans the user input and shows the counted integer numbers and add them. For example the user input would be 'room 2301 next to 12 street' the function would count the number 2301 as one, and 12 as two and add them, 2313 which is the sum and returns it. so the return would be count=2, sum= 2313. However, I am having an issue with the logic behind the function. Currently my function takes the numbers separately, eg. 2302 = 2,3,0,2.
Here is my code:
void num_count(char array[]) {
int i = 0;
int count = 0;
int sum = 0;
int tmp[20];
tmp_size = 20;
while (array[i] != '\0') {
if (array[i] >= '0' && array[i] <= '9') {
tmp[i] = (array[i] - '0');
//not sure what to do here
count++;
sum += (array[i] - '0');
}
i++;
}
}
currently I try to put it into a temp array but not really sure what to do next. Any help would be appreciated .
I think you should begin from the end of the array to the beginning.
When you encounter a digit you have to sum this first digit, then iterate the next character and if it is a digit you have to sum digit x10, the next one: digit x100...
When the next character is not a digit, reset the multiplier and count++.
if(isDigit){
sum+= digit*multiplier;
multiplier*=10;
}
else {
multiplier=1;
}
I don't inlcude the count part.
Use the following code snippet to extract the individual words of the string, check if the extracted word is a number, and, if a number, calculate the sum and increase the count.
int i;
int j;
int count;
int sum;
char *chars;
char *pChar;
int len;
int isNum;
for (i=0, count=0, sum=0; i<strlen(array);) {
pChar = strchr(array[i], ' ');
len = pChar - array[i];
chars = malloc(sizeof(char) * (len + 1));
strncpy(chars, array[i], len);
chars[len] = '\0';
for (j =0, isNum = 1; j<len; j++) {
if (!isdigit(chars[j])) {
isNum=0;
break;
}
}
if (isNum) {
count++;
sum += atoi(chars);
}
free(chars);
if (strchr(array[pChar - array + 1] != NULL)
i = (pChar - array) + 1;
else
break;
}
If you only need the sum, you do not have to save it as char in a char array (in your code it is named tmp[]), but you can directly convert it to integer (assuming no overflow will occur).
Every time you detect the first numeric character, you should reset the tmp to zero and continue multiplying by 10 before adding the next numeric value, until you detect a non-numeric character.
edit: I think the function should return the sum. So, you'd better change the function decoration as well (and add a return sum line).
int num_count(char array[]) {
int i = 0;
int sum = 0;
int tmp;
while (array[i] != '\0') {
if (array[i] >= '0' && array[i] <= '9') {
tmp = 0;
while (array[i] >= '0' && array[i] <= '9') {
tmp = tmp * 10 + array[i] - '0';
i++;
}
sum += tmp;
}
else {
i++;
}
}
return sum;
}
I am self teaching C programming.
I am trying to count number of int present in given string which are separated by space.
exp:
input str = "1 2 11 84384 0 212"
output should be: 1, 2, 11, 84384, 0, 212
total int = 6
When I try. It gives me all the digits as output which make sense since I am not using a right approach here.
I know in python I can use str.split (" ") function which can do my job very quickly.
But I want to try something similar in C. Trying to create my own split method.
#include <stdio.h>
#include <string.h>
void count_get_ints(const char *data) {
int buf[10000];
int cnt = 0, j=0;
for (int i=0; i<strlen(data); i++) {
if (isspace(data[i] == false)
buf[j] = data[i]-'0';
j++;
}
printf("%d", j);
}
// when I check the buffer it includes all the digits of the numbers.
// i.e for my example.
// buf = {1,2,1,1,8,4,3,8,4,0,2,1,2}
// I want buf to be following
// buf = {1,2,11,84384,0,212}
I know this is not a right approach to solve this problem. One way to keep track of prev and dynamically create a memory using number of non space digits encountered.
But I am not sure if that approach helps.
You want to build your number incrementally until you hit a space, then put that into the array. You can do this by multiplying by 10 then adding the next digit each time.
void count_get_ints(const char *data) {
int buf[10000];
int j = 0;
int current_number = 0;
// Move this outside the loop to eliminate recalculating the length each time
int total_length = strlen(data);
for (int i=0; i <= total_length; i++) {
// Go up to 1 character past the length so you
// capture the last number as well
if (i == total_length || isspace(data[i])) {
// Save the number, and reset it
buf[j++] = current_number;
current_number = 0;
}
else {
current_number *= 10;
current_number += data[i] - '0';
}
}
}
I think strtok will provide a cleaner solution, unless you really want to iterate over every char in the string. It has been a while since I did C, so please excuse any errors in the code below, hopefully it will give you the right idea.
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[19] = "1 2 11 84384 0 212";
const char s[2] = " ";
char *token;
int total;
total = 0;
token = strtok(str, s);
while (token != NULL) {
printf("%s\n", token);
total += atoi(token);
token = strtok(NULL, s);
}
printf("%d\n", total);
return 0;
}
You can check the ascii value of each character by doing c-'0'. If it's between [0,9], then it's an integer. By having a state variable, when you're inside an integer by checking if a given character is a number of space, you can keep track of the count by ignoring white space. Plus you don't need a buffer, what happens if data is larger than 10,000, and you write pass the end of the buffer?, undefined behavior will happen. This solution doesn't require a buffer.
Edit, the solution now prints the integers that are in the string
void count_get_ints(const char *data) {
int count = 0;
int state = 0;
int start = 0;
int end = 0;
for(int i = 0; i<strlen(data); i++){
int ascii = data[i]-'0';
if(ascii >= 0 && ascii <= 9){
if(state == 0){
start = i;
}
state = 1;
}else{
//Detected a whitespace
if(state == 1){
count++;
state = 0;
end = i;
//Print the integer from the start to end spot in data
for(int j = start; j<end; j++){
printf("%c",data[j]);
}
printf(" ");
}
}
}
//Check end
if(state == 1){
count++;
for(int j = start; j<strlen(data); j++){
printf("%c",data[j]);
}
printf(" ");
}
printf("Number of integers %d\n",count);
}
I believe the standard way of doing this would be using sscanf using the %n format specifier to keep track of how much of the string is read.
You can start with a large array to read into -
int array[100];
Then you can keep reading integers from the string till you can't read anymore or you are done reading 100.
int total = 0;
int cont = 0;
int ret = 1;
while(ret == 1 && total < 100) {
ret = sscanf(input, "%d%n", &array[total++], &cont);
input += cont;
}
total--;
printf("Total read = %d\n", total);
and array contains all the numbers read.
Here is the DEMO
Example using strtol
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
int count_get_ints(int output[], int output_size, const char *input) {
const char *p = input;
int cnt;
for(cnt = 0; cnt < output_size && *p; ++cnt){
char *endp;
long n;
errno = 0;
n = strtol(p, &endp, 10);
if(errno == 0 && (isspace((unsigned char)*endp) || !*endp) && INT_MIN <= n && n <= INT_MAX){
output[cnt] = n;
while(isspace((unsigned char)*endp))
++endp;//skip spaces
p = endp;//next parse point
} else {
fprintf(stderr, "invalid input '%s' in %s\n", p, __func__);
break;
}
}
return cnt;
}
int main(void) {
const char *input = "1 2 11 84384 0 212";
int data[10000];
int n = sizeof(data)/sizeof(*data);//number of elements of data
n = count_get_ints(data, n, input);
for(int i = 0; i < n; ++i){
if(i)
printf(", ");
printf("%d", data[i]);
}
puts("");
}
Assuming you don't have any non-numbers in your string, you can just count the number of spaces + 1 to find the number of integers in the string like so in this pseudo code:
for(i = 0; i < length of string; i++) {
if (string x[i] == " ") {
Add y to the list of strings
string y = "";
counter++;
}
string y += string x[i]
}
numberOfIntegers = counter + 1;
Also, this reads the data between the white spaces. Keep in mind this is pseudo code, so the syntax is different.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I want to take a string consisting only of numbers and arithmetic operators. Then solve them algebraically. e.g. User input as string = "45 - 98 + 656" and get the output as "603" an integer.
Here's my code
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <ctype.h>
int main(void){
scanf(%s, &S);
int sum = 0;
int a;
for (int i = 0; i < strlen(S); i++) {
if (S[i] == ' ') {
continue;
} else
if (S[i] != ' ') {
if (isdigit(S[i])) {
a = atoi(&S[i]);
} else
if (!isdigit(S[i])) {
if (S[i] == '+') {
S[i] = S[i + 1];
sum = (sum + a);
} else
if (S[i] == '-') {
S[i] = S[i + 1];
sum = (sum - a);
} else {
sum = a;
}
}
}
}
printf("%d", sum);
}
Your code has syntax errors.
You forgot the " around %s
you did not declare S
Here is a simpler solution:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char buf[200];
if (fgets(buf, sizeof buf, stdin)) {
long sum = 0;
/* remove all white space */
for (int i = j = 0, len = strlen(buf); i <= len; i++) {
if (!isspace((unsigned char)buf[i]))
buf[j++] = buf[i];
}
/* parse the expression */
for (char *p = buf, *q;;) {
long a = strtol(p, &q, 10);
if (p == q) {
break;
} else {
sum += a;
p = q;
}
}
printf("sum = %ld\n", sum);
}
return 0;
}
This (unusual) solution should do the trick. It works strictly left-to-right:
sum= 0
number= 0
op= '+'
while get(character)
case character of
digit: case op of
'+': sum-= number; number= 10 * number + character; sum+= number
'-': sum+= number; number= 10 * number + character; sum-= number
'+', '-': number= 0; op= character
And now a slightly obfuscated, but very efficient C translation:
char* c= "45 - 98 + 656";
int s= 0, n= 0, d, p= 1;
for ( ; d= *c - '0', *c; c++)
if ((unsigned)d <= 9) { s-= n; n= 10 * n + p * d; s+= n; }
else if (*c != ' ') { n= 0; p= *c == '+' ? 1 : -1; }
printf("s = %d\n", s);
Prints out 603, as should.
Looking this code I see some error, after atoi() you have to increment the index according to number size (Eg "656" is 3 chars long).
Even after this fix this algorithm is wrong because you are executing the operation too early.
I mean, in your example, this algorithm compute -45+98 and do not compute 656.
Moreover S[i]=S[i+1]; is useless an so .. Wrong
I keep trying to test this code but I keep getting a segmentation fault in my power() function. The code is supposed to take a word made up of lowercase letters and change the word to a number of base 10. The word is supposed to take on the form of a number of base 20, where 'a' = 0, 'b' = 1,...., 't' = 19;
int power(int i){
if(i==1){
return 20;
}else{
return 20*power(i--);
}
}
int main(){
int len;
char mayan[6];
int n;
int val;
while(scanf("%s", mayan)){
val = 0;
n = 0;
for(len = 0; mayan[len] != '\0'; len++){
mayan[len] = tolower(mayan[len]);
mayan[len] = mayan[len] - 'a';
}
for(i = 0; len >= 0; len--, i++){
if(mayan[len] <= 19){
n = n + mayan[len] * power(i);
}else{
fprintf(stderr, "Error, not a base 20 input \n");
val = 1;
break;
}
}
if(val==0){
printf("%d \n", n);
}
}
return val;
}
There were three mistakes in your code.
Case for i==0 not added in the power function, which basically translates to any number to the power of zero is one i.e. x^0 = 1;.
Instead of using return 20*power(i--); for your recursive call, use return 20*power(i-1);. i-- is post decrement operator, which means that, it will return the value of i as it is and will the decrement it for further use, which is not what you want. Also, you altogether don't even want to change the value of i for this iteration too; what you want to do is use a value one less than i for the next iteration, which is what, passing i-1, will do.
Add a len-- in the initialization of the for(i = 0; len >= 0; len--, i++) loop, because len is now over the last index of the input because of the previous loop.
Correcting these mistakes the final code is:
#include<stdio.h>
int power(int i)
{
if(i==0)
{
return 1;
}
if(i==1)
{
return 20;
}
else
{
return 20*power(i-1);
}
}
int main()
{
int len,i;
char mayan[6];
int n;
int val;
while(scanf("%s", mayan))
{
val = 0;
n = 0;
for(len = 0; mayan[len] != '\0'; len++)
{
mayan[len] = tolower(mayan[len]);
mayan[len] = mayan[len] - 'a';
}
for(i = 0, len--; len >= 0; len--, i++)
{
if(mayan[len] <= 19)
{
n = n + mayan[len] * power(i);
}
else
{
fprintf(stderr, "Error, not a base 20 input \n");
val = 1;
break;
}
}
if(val==0)
{
printf("%d \n", n);
}
}
return val;
}
Note that, your code would essentially only work for at most a five digit base 20 number, because, the array mayan that you are using to store it has size 6, of which, one character will be spent for storing the terminating character \0. I recommend that you increase the size of the array mayan unless you want to support only five digit base 20 numbers.
This is a K&R exercise (1-13)...
"Write a program to print a histogram
of the length of words in its input.
It is easy to draw the histogram with
bars horizontal; a vertical
orientation is more challenging."
The section was about arrays, and to be honest, I'm not sure I fully understood it. Everything up to this point was fairly easy to grasp, this was not.
Anyway I'm trying to do a histogram with horizontal bars first. Once I got that down I'll try vertical, but right now I'm not even sure where to begin with the easy version. (I slept on it, woke up, and still couldn't get it.)
I drew an example of what the program would output:
----------------------------------------------------------------
001|XX
002|XXXX
003|X
004|XXXXXXXXXX
005|XXXXXXXXXXXXXXXXXXXXXXXXX
006|XXXX
007|X
008|
009|XXXXXXXXX
010|XXX
>10|XXXX
----------------------------------------------------------------
And tried to break it (the program) down in sections. This is what I came up with:
PRINT TOP BORDER
PRINT CATEGORY, PRINT X EACH TIME CONDITION IS TRUE, PRINT NEWLINE,
REPEAT.
PRINT BOTTOM BORDER
But the more I think about it the less I think that's how it would work (because getchar() goes through one character at a time, and it wouldn't be able to go back up to put a X in the right category.) Or...
... I'm just really confused as to how I would solve this problem. Here's as far as I've been able to get code wise:
#include <stdio.h>
#define MAXWORDLENGTH 10
// print a histogram of the length of words in input. horizontal bar version
int main(void)
{
int c;
while ((c = getchar()) != EOF) {
}
return 0;
}
Could someone help enlighten me? Not necessarily with the code, maybe just pseudo code, or with some "words from the wise" as to what I need to do, or think, or something. This has just been a really big stone in the road and I'd like to get past it :/.
(I'll check back in 30 minutes)
I loved the pseudo-code! Some good thinking there, but you're still not ordering your program right.
As you said yourself, you can't read the text, go back and print an X in a particular row. If we establish that it can't be done, then there's no choice but to know all the values of the histogram beforehand.
So you should think your program as having two parts (and you'll make this kind of division in practically every program you write): first, a part that will make calculations; and then a part that will output them in a certain format (the histogram).
This tip should get you started! If you need further help, comment below.
I suggest you simplify the problem by solving it for the case of one word per line, so you can use fgets. Here's how to "eat up" lines that are too long.
Then, as often, the central data structure is the key to solving the problem. The data structure you need is an array used as frequency table:
int freq[11];
In freq[1], store the number of words/lines of length 1, in freq[2] those of length 2, etc., and in freq[0] those of length >10. You don't need to store the words since the rest of the program only needs their length. Writing out the histogram should be easy now.
I hope this isn't too much of a spoiler.
The code below prints a horizontal histogram using only the basic toolkit provided by the book so far:
#include<stdio.h>
/* Prints a horizontal histogram of the lengths of words */
#define MAX_WORDS 100
#define IN 1
#define OUT 0
main()
{
int c, length, wordn, i, j, state, lengths[MAX_WORDS];
wordn = length = 0;
state = OUT;
for (i = 0; i < MAX_WORDS; ++i) lengths[i] = 0;
while ((c = getchar()) != EOF && wordn < MAX_WORDS)
{
if (c == ' ' || c == '\t' || c == '\n')
state = OUT;
else if (wordn == 0)
{
state = IN;
++wordn;
++length;
}
else if (state == IN)
++length;
else if (state == OUT)
{
lengths[wordn] = length;
++wordn;
length = 1;
state = IN;
}
}
lengths[wordn] = length;
for (i = 1; i <= wordn; ++i)
{
printf("%3d: ",i);
for (j = 0; j < lengths[i]; j++)
putchar('-');
putchar('\n');
}
}
#include<stdio.h>
#define RESET 0
#define ON 1
main()
{
int i,wnum=0,c,wc[50];
int count=0,state;
state=RESET;
for(i=0;i<50;++i)
wc[i]=0;
/*Populating the array with character counts of the typed words*/
while((c=getchar())!=EOF)
{
if(c=='\n'||c=='\t'||c==' '||c=='"')
{
if(state!=RESET)
state=RESET;
}
else if((c>=65&&c<=90)||(c>=97&&c<=122))
{
if(state==RESET)
{
count=RESET;
++wnum;
state=ON;
}
++count;
wc[wnum-1]=count;
}
}
c=RESET;
/*Finding the character count of the longest word*/
for(i=0;i<wnum;++i)
{
if(c<wc[i])
c=wc[i];
}
/*Printing the Histogram Finally*/
for(i=c;i>0;--i)
{
for(count=0;count<wnum;++count)
{
if(wc[count]-i<0)
printf(" ");
else printf("x ");
}
printf("\n");
}
}
VERTICAL ORIENTATION: Using only the tools we learned so far in the book. And you can change the array size, wc[50]. I kept the code valid for 50 words.
Horizontal orientation should be quite simpler. I didn't try it though.
To histogram the word lengths, you are going to need to know the word lengths.
How do you define a word?
How can you measure the length of a word? Can you do it one character at a time as you read the stream, or should you buffer the input an use strtok or something similar?
You will need to accumulate data on how many occurrences of each length occur.
How will you store this data?
You will need to output the results in a pleasing form. This is fiddly but not hard.
I will link the answer below but since you asked for details the key seems to be this
Use an ARRAY of lengths i.e have an array with each element initialised to zero assume MAX wordlength to be about 30...
*have a flag while in the word and increment a counter every time a whitespace is NOT encountered
*once out of the word flag is set to "out" and the corresponding word length index item in the array is incremented i.e if word length counter is w_ctr use
array[w_ctr]++
*use the array as a table of reference for each line in a loop to print each line in the histogram so you can use the array and will now be able to determine weather the 'X' in the histogram is to be inserted or not
EDIT: sorry i didn't read the question right but the idea is simpler for Vertical histograms and the same thing can be used.
after the last step just print the horizontal histogram until counter exceeds current wordlength being printed
for(ctr=0;ctr<array[current_wordlength];ctr++)
printf('X');
End
the original is here http://users.powernet.co.uk/eton/kandr2/krx113.html
CLC-wiki is also a place see the comments for details.
//This is for horizontal histogram.
//It works for any number of lines of words where total words <= MAX
#include <stdio.h>
#define MAX 100 //Change MAX to any value.But dont give words more than MAX.
void main()
{
int w, nwords[MAX] = {0}, i = 0; //nwords is an array for storing length of each word.Length of all words initialized to 0.
while ((w = getchar()) != EOF)
{
if (w == ' ' || w == '\t' || w == '\n')
++i; //if space or tab or newline is encountered, then index of array is advanced indicating new word
else
++nwords[i]; //increment the count of number of characters in each word
} //After this step,we will have array with each word length.
for (i = 0; i < MAX; i++) //iterating through array
{
printf("\n");
for (; nwords[i] > 0; nwords[i]--)
printf("$"); //if length of word > 0 , print $ and decrement the length.This is in loop.
if (nwords[i+1] == 0) //as MAX is 100, to avoid printing blank new lines in histogram,we check the length of next word.
break; //If it is 0, then break the loop
printf("\n"); //After each word bar in histogram, new line.
}
printf("\n");
} //main
I've been also studying K&R book. An good approach is to use a int array for storing word frequencies. The array index is the word length, and the array values are the frequencies.
For example:
int histogram[15]; // declares an int array of size 15
// it is very important to initialize the array
for (int i = 0; i <= 15; ++i) {
histogram[i] = 0;
}
histogram[4] = 7; // this means that you found 7 words of length 4
Given that now you have a data structure for storing your word length frequencies, you can use the same reasoning of Word Counting example found in the book to populate the histogram array. It is very important that you manage to find the right spot for word length tracking (and resetting it) and histogram update.
You can create a function display_histogram for displaying the histogram afterwards.
Here's a code example:
#include<stdio.h>
#define MAX_WORD_LENGTH 15
#define IS_WORD_SEPARATOR_CHAR(c) (c == '\n' || c == ' ' || c == '\t')
#define IN 1
#define OUT 0
/* WARNING: There is no check for MAX_WORD_LENGTH */
void display_horizontal_histogram(int[]);
void display_vertical_histogram(int[]);
void display_histogram(int[], char);
void display_histogram(int histogram[], char type) {
if (type == 'h') {
display_horizontal_histogram(histogram);
} else if (type = 'v') {
display_vertical_histogram(histogram);
}
}
void display_horizontal_histogram(int histogram[]) {
printf("\n");
//ignoring 0 length words (i = 1)
for (int i = 1; i <= MAX_WORD_LENGTH; ++i) {
printf("%2d: ", i);
for (int j = 0; j < histogram[i]; ++j) {
printf("*");
}
printf("\n");
}
printf("\n\n");
}
void display_vertical_histogram(int histogram[]) {
int i, j, max = 0;
// ignoring 0 length words (i = 1)
for (i = 1; i <= MAX_WORD_LENGTH; ++i) {
if (histogram[i] > max) {
max = histogram[i];
}
}
for (i = 1; i <= max; ++i) {
for (j = 1; j <= MAX_WORD_LENGTH; ++j) {
if (histogram[j] >= max - i + 1) {
printf(" * ");
} else {
printf(" ");
}
}
printf("\n");
}
for (i = 1; i <= MAX_WORD_LENGTH; ++i) {
printf(" %2d ", i);
}
printf("\n\n");
}
int main()
{
int c, state, word_length;
int histogram[MAX_WORD_LENGTH + 1];
for (int i = 0; i <= MAX_WORD_LENGTH; ++i) {
histogram[i] = 0;
}
word_length = 0;
state = OUT;
while ((c = getchar()) != EOF) {
if (IS_WORD_SEPARATOR_CHAR(c)) {
state = OUT;
if (word_length != 0) {
histogram[0]++;
}
histogram[word_length]++;
word_length = 0;
} else {
++word_length;
if (state == OUT) {
state = IN;
}
}
}
if (word_length > 0) {
histogram[word_length]++;
}
display_histogram(histogram, 'h');
display_histogram(histogram, 'v');
}
Here's an input/output sample:
kaldklasjdksla klsad lask dlsk aklsa lkas adç kdlaç kd dklask las kçlasd kas kla sd saçd sak dasças sad sajçldlsak dklaa slkdals kkçl askd lsak lçsakç lsak lsak laskjl sa jkskjd aslld jslkjsak dalk sdlk jsalk askl jdsj dslk salkoihdioa slk sahoi hdaklshd alsh lcklakldjsalkd salk j sdklald jskal dsakldaksl daslk
1: *
2: ***
3: ******
4: ***************
5: **********
6: ****
7: ****
8: ***
9:
10: *
11: **
12:
13:
14: **
15:
*
*
*
*
*
* *
* *
* *
* *
* * *
* * *
* * * * *
* * * * * * *
* * * * * * * * *
* * * * * * * * * * *
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
You should separate your 2 problems in functions, like:
void gethist(char *s, int *hist, int len)
{ /* words here breaks on spaces (' ') */
char *t;
for( t=strtok(s," ");t;t=strtok(0," ") )
if(*t)
hist[ strlen(t)>len-1?len-1:strlen(t)-1 ]++;
}
void outhist(int *hist, int len)
{
int i;
for( i=1; i<=len; ++i )
{
char *s = calloc(1,5+hist[i-1]);
sprintf(s,"%03d|", i);
memset( s+4, 'X', hist[i-1]);
puts(s);
free(s);
}
}
then its easy in your main:
int main(void)
{
int c, hist[11] = {};
char *s = calloc(1,1);
while ((c = getchar()) != EOF) {
s = realloc( s, 2+strlen(s) );
s[ strlen(s)+1 ] = 0;
s[ strlen(s) ] = c;
}
gethist(s,hist,11); free(s);
outhist(hist,11);
return 0;
}
The vertical histogram can be printed one line at a time, by going through the array of word lengths and decreasing the word length at each iteration. A # is printed if the word length is still above zero, and a space is printed when it reaches 0. The newline is printed after each iteration.
If lengths[i] holds the number of characters for word i, and wordn is the total number of words, then the following will print the vertical histogram:
#define YES 1
#define NO 0
more_lines = YES;
while (more_lines)
{
more_lines = NO;
for (i = 1; i <= wordn; ++i)
{
if (lengths[i] > 0 )
{
more_lines = YES;
printf("#\t");
--lengths[i];
}
else
printf(" \t");
}
putchar('\n');
}
The complete code is below:
#include<stdio.h>
/* Prints a histogram of the lenghts of words */
#define MAX_WORDS 100
#define IN 1
#define OUT 0
#define YES 1
#define NO 0
main()
{
int c, length, wordn, i, j, state, more_lines, lengths[MAX_WORDS];
wordn = length = 0;
state = OUT;
for (i = 0; i < MAX_WORDS; ++i) lengths[i] = 0;
while ((c = getchar()) != EOF && wordn < MAX_WORDS)
{
if (c == ' ' || c == '\t' || c == '\n')
state = OUT;
else if (wordn == 0)
{
state = IN;
++wordn;
++length;
}
else if (state == IN)
++length;
else if (state == OUT)
{
lengths[wordn] = length;
++wordn;
length = 1;
state = IN;
}
}
lengths[wordn] = length;
/* Print histogram header */
for (i = 1; i <= wordn; ++i)
printf ("%d\t", i);
putchar('\n');
more_lines = YES;
while (more_lines)
{
more_lines = NO;
for (i = 1; i <= wordn; ++i)
{
if (lengths[i] > 0 )
{
more_lines = YES;
printf("#\t");
--lengths[i];
}
else
printf(" \t");
}
putchar('\n');
}
}
Although the exercise is based on Arrays, I tried to write it using the basic while loop and an if statement. I am not really good with Arrays as of now, so thought of trying this out. I have not tested it for bugs though, but it seems to be working fine for most inputs.
#include<stdio.h>
main() {
long int c;
while((c=getchar())!=EOF) {
if(c!=' '&&c!='\n'&&c!='\t') {
putchar("*");
}
if(c==' '||c=='\n'||c=='\t') {
putchar('\n');
}
}
return 0;
}
Please note that this is a very basic piece of code to print it horizontally, just for the basic understanding of the structure.
// Histogram to print the length of words in its input
#include <stdio.h>
main()
{
int wordcount[10],c,token=0;
int word=0, count =0;
for (int i=0; i<10; i++)
{
wordcount[i]=0;
}
while((c=getchar())!=EOF)
{
if(c== ' ' || c == '\n' || c== '\t')
{
// add the length of word in the appropriate array number
switch(word)
{
case 1:
++wordcount[0];break;
case 2:
++wordcount[1];break;
case 3:
++wordcount[2];break;
case 4:
++wordcount[3];break;
case 5:
++wordcount[4];break;
case 6:
++wordcount[5];break;
case 7:
++wordcount[6];break;
case 8:
++wordcount[7];break;
case 9:
++wordcount[8];break;
case 10:
++wordcount[9];break;
}
word =0;
}
else if (c != ' ' || c != '\n' || c!= '\t')
{
word++;
}
}
for (int j=0; j<10; j++)
{
if(wordcount[j]==0)
{
printf("- ");
}
for (int k=0;k<wordcount[j];k++)
printf("X", wordcount[j]);
printf("\n");
}
}
Here is the example of simple vertical Histogram
#include <stdio.h>
int main()
{
int c, i, j, max;
int ndigit[10];
for (i = 0; i < 10; i++)
ndigit[i] = 0;
while ((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
max = ndigit[0];
for (i = 1; i < 10; ++i) /* for Y-axis */
if (max < ndigit[i])
max = ndigit[i];
printf("--------------------------------------------------\n");
for (i = max; i > 0; --i) {
printf("%.3d|", i);
for (j = 0; j < 10; ++j)
(ndigit[j] >= i) ? printf(" X ") : printf(" ");
printf("\n");
}
printf(" ");
for (i = 0; i < 10; ++i) /* for X-axis */
printf("%3d", i);
printf("\n--------------------------------------------------\n");
return 0;
}
#include <stdio.h>
#include <string.h>
int main()
{
//hold length of string
unsigned long length;
// Holds the name input by user upto 50 characters
char name[50];
//iterator for generating dash for bar chart
int i = 0;
//iterator for generating dash for bar chart
int j = 0;
//take user name input
printf("input your name [without spaces and < 50 characters] : ");
scanf("%s", &name[0]);
//find the length of string
length = strlen(name);
printf("length of your name is %lu \n", length);
//generate dashes for bar chart
while (i < length)
{
printf("--");
++i;
}
printf("| \n");
// fill the bar chart with []
while (j < length)
{
printf("[]");
++j;
}
printf("| \n");
//generate dashes for bar chart
while (length > 0)
{
printf("--");
--length;
}
printf("| \n");
}
input your name [without spaces and < 50 characters] : ThisIsAtestRun
length of your name is 14
----------------------------|
[][][][][][][][][][][][][][]|
----------------------------|
I've tried to implement the latter part of the question (i.e. Displaying the histogram in a vertical manner) and have managed to get most of it done. In the code below, The maximum number of words accepted are 20 and the maximum word length is 10. Also, apologies for not getting the best graphical representation of a typical histogram but the logic to display vertical bars is completely accurate!
Here's my code,
#define MAXWORDS 20
#define MAXLENGTH 10
int c, nlength = 0, i, nword = 0, j;
int length_words[20]= {0};
while((c = getchar()) != EOF && nword <= MAXWORDS)
{
if(c != ' ' && c != '\t' && c != '\n')
++nlength;
else
{
if(nlength != 0){
length_words[nword] = nlength;
++nword;
/* for(i = 0; i < nlength; i++)
printf("O");
printf("\n");*/
printf("Word number: %d has length: %d\n", nword - 1, nlength);
}
nlength = 0;
}
}
// Displaying the Histogram
for(i = MAXLENGTH; i > 0; i--)
{
for(j = 0; j < nword; j++)
{
if(i > length_words[j])
printf(" ");
else
printf(" O ");
}
printf("\n");
}
Feel free to run this and let me know in case of any discrepancy or loopholes!
#include <stdio.h>
int main(void)
{
int i, ii, state, c, largest, highest;
int A[100];
for(i = 0; i < 100; ++i)
A[i] = 0;
i = ii = state = c = largest = 0;
while((c = getchar()) != EOF)
{
if(c == ' ' || c == '\b' || c == '\n')
{
if(state)
{
++A[i];
if(largest <= i)
largest = i;
i = state = 0;
}
}
else
{
if(state)
++i;
else
state = 1;
}
}
for(i = 0; i < 100; ++i)
if(highest <= A[i])
highest = A[i];
for(i = 0; i <= highest; ++i)
{
for(ii = 0; ii < 100; ++ii)
if(A[ii])
{
if(A[ii] > (highest - i))
printf("*\t");
else
printf(" \t");
}
putchar('\n');
}
for(ii = 0; ii < 100; ++ii)
if(A[ii])
printf("-\t");
putchar('\n');
for(ii = 0; ii < 100; ++ii)
if(A[ii])
printf("%d\t", ii + 1);
putchar('\n');
return 0;
}
Print Histogram based on word Length. (C Program).
HORIZONTAL VERSION :
#include<stdio.h>
#define MAX 15
int main()
{
int c, wordLength, count;
int arr[MAX] = { 0 };
wordLength = count = 0;
while((c = getchar()) != EOF)
{
if(c != ' ' && c != '\t' && c != '\n')
++arr[count];
else
++count;
}
for(int i = 0; i <= count; i++)
{
printf("\n%2d |", i+1);
for(int k = arr[i]; k > 0; k--)
printf("— ");
}
return 0;
}
Input/Output :
man in black thor jsjsk ksskka
1 |— — —
2 |— —
3 |— — — — —
4 |— — — —
5 |— — — — —
VERTICAL VERSION :
#include<stdio.h>
#define MAX 15
int main()
{
int c, count, maxLength;
int arr[MAX] = { 0 };
maxLength = count = 0;
while((c = getchar()) != EOF)
{
if(c != ' ' && c != '\t' && c != '\n')
++arr[count];
else
++count;
if(arr[count] > maxLength)
maxLength = arr[count];
}
for(int i = 1; i <= maxLength + 2; i++)
{
printf("\n");
for(int k = 0; k <= count; k++)
{
if(i <= maxLength)
{
if(maxLength - i < arr[k])
printf("|");
else
printf(" ");
}
else
{
if(maxLength - i == -1)
printf("—");
else
printf("%d", k+1);
}
printf(" ");
}
}
return 0;
}
Input/Output :
jsjs sjsj sjsj sjskks sjs sjs
|
|
| | | |
| | | | | |
| | | | | |
| | | | | |
— — — — — —
1 2 3 4 5 6
here is the method that I used :
#include <stdio.h>
#define MAXWD 25 // maximum words
#define MAXLW 20 // maximum lenght of word or characters
int main(void) {
int word[MAXWD]; // an array consists of 25 words
int c, i, j, nc, nw; // declaring c for the input, i for the loop 'for', j is for printing left to right, nc and nw stands for new character and new word
for (i = 0; i < 25; ++i)
word[i] = 0;
nc = nw = 0; // set to count from 0
while ((c = getchar()) != EOF) {
++nc;
if ( c == ' ' || c == '\t' || c == '\n') {
word[nw] = nc -1; // for deleting the space to go for the new word
++nw;
nc = 0; // start counting from zero
}
}
for (i = MAXLW; i >= 1; --i) {
for(j = 0; j <= nw; ++j) { // to start from left to wright
if (i <= word[j]) // MAXLW is less or equal to the number of words
putchar('|');
else
putchar(' ');
}
putchar ('\n');
}
return 0;
}