Hello I would like to check for a float number in string
#include<stdio.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
int main(void)
{
char qihjuq[] = "a s d a s d g g 1 2 3 1 2 3 5 5.4 d 10.4";
int num[256];
float digit[256];
char let[256] = {"0"};
int lcounter =0;
int ncounter =0;
int dcounter =0;
for(int i =0; i< sizeof qihjuq; i++)
{
if(isalpha(*(qihjuq+i))) {
let[lcounter] = *(qihjuq + i);
lcounter++;
}
else if(isdigit(*(qihjuq+i)) && *(qihjuq+i+1) != '.') {
num[ncounter] = *(qihjuq + i);
ncounter++;
}
else if(roundf(*(qihjuq+i)) != *(qihjuq+i)) {
digit[dcounter] = *(qihjuq + i);
dcounter++;
}
}
printf("The letters are: \n");
for(int i =0; i< lcounter; i++)
printf("%c ",let[i]);
printf("The whole numbers are: \n");
for(int i =0; i< ncounter; i++)
printf("%c ",num[i]);
}
The problem lies in the second and third if
else if(isdigit(*(qihjuq+i)) && *(qihjuq+i+1) != '.') {
num[ncounter] = *(qihjuq + i);
ncounter++;
}
else if(roundf(*(qihjuq+i)) != *(qihjuq+i)) {
digit[dcounter] = *(qihjuq + i);
dcounter++;
}
where the program has to detect whether the is float or integer. The problem is that the program is detecting 10.4 as individual characters which in turn puts 1 0 4 in the whole number to try to negate this I added a detection for . but still has logical errors since the condition does not include the numbers behind the .
like this:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void){
char qihjuq[] = "a s d a s d g g 1 2 3 1 2 3 5 5.4 d 10.4";
int num[256];
float digit[256];
char let[256];
int lcounter =0;
int ncounter =0;
int dcounter =0;
for(int i = 0; i < sizeof(qihjuq) -1; i++){
if(isspace(qihjuq[i]))
continue;//skip spaces
char work[256] = {0};
for(int j = 0; qihjuq[i] && !isspace(qihjuq[i]); ++j, ++i)
work[j] = qihjuq[i];//Extraction
--i;//for next loop
if(isalpha(*work) && !work[1]) {//one letter
let[lcounter++] = *work;
} else {
char *p = work;
int n = strtol(p, &p, 10);
if(!*p)//convert to int succeeded (Not strict)
num[ncounter++] = n;
else {
p = work;
float f = strtod(p, &p);
if(!*p)//convert to float succeeded (Not strict)
digit[dcounter++] = f;
}
}
}
printf("The letters are: \n");
for(int i = 0; i < lcounter; i++)
printf("%c ", let[i]);
printf("\nThe whole numbers are: \n");
for(int i = 0; i < ncounter; i++)
printf("%d ", num[i]);
puts("");
}
I do not understand your approach.
You have – let's call it – tokens in a string separated by spaces. You can neither detect the kind of a token nor the value of that token by simply looking on one character.
You have two options: (Logically they are the same, but the implementation is different.)
You iterate over the string extracting the tokens and then iterate over each token to detect its kind.
You iterate over the string and recursively iterate over a token.
Like so (typped in browser)
char *char_ptr = qihjuq;
do
{
if( char_ptr == ' ')
{
continue
}
// iterate overe the next token
int char_set = 0x0;
char * start_ptr = char_ptr; // The start of an item
do
{
if( isdigit( *char_ptr) )
{
char_set |= 0x01; // contains digit
}
else if( *char_ptr == '.' )
{
char_set |= 0x02; // contains period
}
else if( isalpha( *char_ptr ))
{
char_set |= 0x04;
}
break; // any other character breaks item
} while( *char_ptr++ );
// integers have 0x01, floats have 0x3. Other values are alphas or alphanumerics
// you can store the result into an array, do some processing with them or whatever you want. start_ptr points to the beginning of the item_char_ptr to one char after the end.
} while ( *char_ptr++ )
Likely there are some bugs, but this is the structure.
Just read a double with strtod().
If it works, the end pointer points to the position to read from; if it doesn't work advance by 1.
Keep at it until the end of the string
/* code untested */
double x;
char *end
char qihjuq[] = "a s d a s d g g 1 2 3 1 2 3 5 5.4 d 10.4";
char *p = qihjuq;
while (*p) {
errno = 0;
x = strtod(p, &end);
if (errno) {
p += 1;
} else {
printf("found %f\n", x);
p = end;
}
}
i'm newbie in C programming .
i have written this code for adding two numbers with 100 digits , but i don't know why the code does not work correctly , it suppose to move the carry but it doesn't .
and the other problem is its just ignoring the first digit (most significant digit) .
can anybody help me please ?
#include <stdio.h>
#include <ctype.h>
int sum[101] = {0};
int add(int a, int b);
void main()
{
static int a[100];
static int b[100];
char ch;
int i = 0;
int t;
for (t = 0; t != 100; ++t)
{
a[t] = 0;
}
for (t = 0; t != 100; ++t)
{
b[t] = 0;
}
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
a[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
i = 0;
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
b[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
for (;i!=0; --i)
{
add(a[i], b[i]);
}
for (i==0;i != 101; ++i)
{
printf("%d", sum[i]);
}
}
int add( int a , int b)
{
static int carry = 0;
float s = 0;
static int p = 101;
if (0 <= a+b+carry <= 9)
{
sum[p] = (a + b + carry);
carry = 0;
--p;
return 0;
}
else
{
if (10 <= a+b+carry < 20)
{
s = (((a+b+carry)/10.0 ) - 1) * 10 ;
carry = ((a+b+carry)/10.0) - (s/10);
}
else
{
s = (((a+b+carry)/10 ) - 2) * 10;
carry = ((a+b+carry)/10.0) - (s/10);
}
sum[p] = s;
--p;
return 0;
}
}
Your input loops have serious problem. Also you use i to count the length of both a and b, but you don't store the length of a. So if they type two numbers that are not equal length then you will get strange results.
The losing of the first digit is because of the loop:
for (;i!=0; --i)
This will execute for values i, i-1, i-2, ..., 1. It never executes with i == 0. The order of operations at the end of each iteration of a for loop is:
apply the third condition --i
test the second condition i != 0
if test succeeded, enter loop body
Here is some fixed up code:
int a_len;
for (a_len = 0; a_len != 100; ++a_len)
{
int ch = fgetc(stdin); // IMPORTANT: int, not char
if ( ch == '\n' || ch == EOF )
break;
a[a_len] = ch;
}
Similarly for b. In fact it would be a smart idea to make this code be a function, instead of copy-pasting it and changing a to b.
Once the input is complete, then you could write:
if ( a_len != b_len )
{
fprintf(stderr, "My program doesn't support numbers of different length yet\n");
exit(EXIT_FAILURE);
}
for (int i = a_len - 1; i >= 0; --i)
{
add(a[i], b[i]);
}
Moving onto the add function there are more serious problems here:
It's not even possible to hit the case of sum being 20
Do not use floating point, it introduces inaccuracies. Instead, doing s = a+b+carry - 10; carry = 1; achieves what you want.
You write out of bounds of sum: an array of size [101] has valid indices 0 through 100. But p starts at 101.
NB. The way that large-number code normally tackles the problems of different size input, and some other problems, is to have a[0] be the least-significant digit; then you can just expand into the unused places as far as you need to go when you are adding or multiplying.
I'm changing a program from normal array notation to pure pointer notation and I can't receive user input using getchar() in a while loop. I printed out was the program was receiving and it output upside down question marks. I wasn't sure why this was happening because I never changed the variable type. The problem is in the second function to receive user input. Thank you for the help.
#include <stdio.h>
#include <stdlib.h>
/* Function prototypes */
void fillS1(char * x);
void fillS2(char * x, char * y, char z);
void strFilter(char * a, char * b, char c);
int main(int argc, const char * argv[])
{
char s1[42];
char s2[22];
char x = 0;
fillS2(s2, s1, x);
return 0;
}
/* Function to generate a random string of 40 uppercase letters */
void fillS1(char randomlyGeneratedString[])
{
char * pointerToRandom = randomlyGeneratedString;
int i;
for (i = 0; i < 40; i++) {
*(pointerToRandom + i) = 'A' + rand() % 26;
}
pointerToRandom[40] = (char)0;
//printf("This is the generated string %s\n", pointerToRandom);
}
/* Function to get user input of characters */
void fillS2(char userString[], char randomString[], char replacementCharacter)
{
char * pointerToUserString = userString;
char * pointerToRandom = randomString;
int i = 0;
int n = 0;
int capitalLetterCheck = 0;
char loopContinue = 0;
char copyString[42];
char * pointerToCopyString = copyString;
fillS1(pointerToRandom);
do {
/* For loop to copy the first randomly generated string */
for(i = 0; i < 42; i++)
*(pointerToCopyString + i) = *(pointerToRandom + i);
i = 0;
capitalLetterCheck = 0;
/* While loop to to get user input */
printf("Please enter at least 2 capital letters and a maximum of 20.\n");
while (((*(pointerToUserString + i)) = getchar() != '\n')) {
/* Counter to determine how many characters were entered */
i++;
}
i++;
*(pointerToUserString + i) = '\0';
//printf("This is the value if i %i", i);
//printf("This is the user's string %s", pointerToUserString);
/* Capital letter check */
for (n = 0; n < 20; n++) {
if (((*(pointerToUserString + i)) >= 'A') && (*(pointerToUserString + i) <= 'Z'))
{
capitalLetterCheck++;
}
}
if (i < 3) {
printf("You need at least two letters\n");
}
else if (i > 21){
printf("You cannot have more than twenty letters\n");
}
else if (capitalLetterCheck >= 2) {
puts(pointerToUserString);
printf("Enter a character to replace occuring letters.\n");
scanf("%c", &replacementCharacter);
getchar();
strFilter(pointerToCopyString, pointerToUserString, replacementCharacter);
}
else
printf("You must have 2 capital letters.\n");
printf("Would you like to enter another string (y/n)?\n");
loopContinue = getchar();
getchar();
} while (loopContinue != 'n' && loopContinue != 'N');
}
/* Function to replace letters with the character chosen by the user */
void strFilter(char a[], char b[], char c)
{
char * pointerToA = a;
char * pointerToB = b;
int i = 0;
int n = 0;
while (n < 20) {
for (i = 0; i < 40; i++) {
if ((*(pointerToA + i)) == *(pointerToB + n)){
*(pointerToA + i) = c;
}
}
i = 0;
n++;
}
puts(a);
}
The problem is this in the if statement:
(*(pointerToUserString + i)) = getchar() != '\n'
Assignment is an expression, with lower precedence than comparison. This means the above is the same as:
(*(pointerToUserString + i)) = (getchar() != '\n')
So (*(pointerToUserString + i)) gets assigned the value of the expression getchar() != '\n' which is not what you want.
I'm trying to modify a previous program I wrote using pure pointer notation. It's a program that generates a random string of 40 uppercase letter, takes input of up to 20 uppercase letter, and input of a character. The program replaces reoccurring characters in the generated string with the character entered. Right now, I'm trying to pass the parameters of the randomly generated string so I can access them in the second function and can't figure out how to do it.
Thank you for the help.
#include <stdio.h>
#include <stdlib.h>
/* Function prototypes */
void fillS1(char * x);
void fillS2(char * x, char * y, char z);
void strFilter(char * a, char * b, char c);
int main(int argc, const char * argv[])
{
char s1[41];
char s2[21];
char x = 0;
char * pointerToS1;
char * pointerToS2;
pointerToS1 = s1;
pointerToS2 = s2;
fillS2(pointerToS2, pointerToS1, x);
return 0;
}
/* Function to generate a random string of 40 uppercase letters */
void fillS1(char * randomlyGeneratedPointer)
{
char randomlyGeneratedArray[41];
randomlyGeneratedPointer = randomlyGeneratedArray;
int i;
for (i = 0; i < 40; i++) {
*(randomlyGeneratedPointer + i) = 'A' + rand() % 26;
}
}
/* Function to get user input of characters */
void fillS2(char * userStringPointer, char * randomStringPointer, char replacementCharacter)
{
char userstring[21];
char randomString[41];
char copyString[42];
//char * pointerToCopyString = copyString;
userStringPointer = userstring;
int i = 0;
int n = 0;
int lowercaseCheck = 0;
char loopContinue = 0;
fillS1(randomStringPointer); //here is the function call for the randomly generated string.
printf("This is the random string: %s", randomStringPointer);
do {
/* For loop to copy the first randomly generated string */
for(i = 0; i < 42; i++)
*(randomStringPointer + i) = copyString[i];
randomStringPointer = copyString;
i = 0;
lowercaseCheck = 0;
/* While loop to to get user input */
printf("Please enter at least 2 capital letters and a maximum of 20.\n");
while ((((*(userStringPointer + i)) = getchar()) != '\n')) {
/* Counter to determine how many characters were entered */
i++;
}
/* Adding 1 to add to add null character */
i++;
*(userStringPointer + i) = '\0';
//printf("This is the user's string %s", userStringPointer);
/* Capital letter check */
for (n = 0; n < 20; n++) {
if (((*(userStringPointer + n)) >= 'a') && (*(userStringPointer + n) <= 'z')) {
lowercaseCheck++;
}
}
if (--i < 3) {
printf("You need at least two letters\n");
}
else if (i > 21){
printf("You cannot have more than twenty letters\n");
}
else if (lowercaseCheck == 0) {
puts(userStringPointer);
printf("Enter a character to replace occuring letters.\n");
scanf("%c", &replacementCharacter);
getchar();
//printf("this is the copy string before strFilter: %s", randomStringPointer);
//printf("This is the replacement character %c", replacementCharacter);
strFilter(randomStringPointer, userStringPointer, replacementCharacter);
}
else
printf("You must have 2 capital letters.\n");
printf("Would you like to enter another string (y/n)?\n");
loopContinue = getchar();
getchar();
} while (loopContinue != 'n' && loopContinue != 'N');
}
/* Function to replace letters with the character chosen by the user */
void strFilter(char * replacementCopyStringPointer, char * replacementUserStringPointer, char c)
{
int i = 0;
int n = 0;
while (n < 20) {
for (i = 0; i < 40; i++) {
if ((*(replacementCopyStringPointer + i)) == *(replacementUserStringPointer + n)){
*(replacementCopyStringPointer + i) = c;
}
}
i = 0;
n++;
}
puts(replacementCopyStringPointer);
}
randomlyGeneratedArray array in fillS1 would get destroyed once fillS1 function returns.
You should allocate the memory from heap for randomlyGeneratedArray.
randomlyGeneratedArray = (char *)malloc(sizeof(char)*41)
Also do the same for userStringPointer in fillS2.
That should solve the problem.
For difference between stack and heap read this question What and where are the stack and heap?
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;
}