counting occurrence of character and printing them out - c

I've managed to get the frequency of the alphabet from my input. I also found the largest occurred character. But i dont know how to print the actual character. Right now my program displays A-Z and display the occurrence for each alphabet. I want to be able on the next line print out the largest occurred letter and how many times it occurred.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 200
int readLine(char string[]);
void find_frequency(char string[], int count[]);
int maxArray(int a[]);
int main(void)
{
char array[MAX];
int freq[MAX];
int nrOfChar;
int i;
char c;
int max;
printf("Command Line Tool\n");
printf("Please enter text here: ");
nrOfChar = readLine(array);
for(c = 'A'; c<= 'Z'; c++)
{
printf("%c ", c);
}
find_frequency(array, freq);
printf("\n");
for(i=0;i<26;i++)
{
printf("%d ", freq[i]);
}
printf("\n");
max=maxArray(freq);
printf("Print letter and how many occurrence.\n");
printf("Finished excuting.\n");
return 0;
}
int readLine(char string[])
{
int ch;
int i=0;
while (isspace(ch = getchar()))
;
while (ch != '\n' && ch != EOF)
{
if (i < MAX)
{
string[i++] = ch;
ch = getchar();
}
}
string[i] = '\0';
return i;
}
void find_frequency(char string[], int count[])
{
int i;
for(i = 0; string[i] != '\0'; i++)
{
if (string[i] >= 'A' && string[i] <= 'Z' )
{
count[string[i]-'A']++;
}
}
}
int maxArray(int a[])
{
int i, max=0;
for (i=0; i<26; i++)
{
if (a[i]>max)
{
max=a[i];
}
}
return max;
}

Below I've incorporated various folks' suggestions from the comments as well as some other fixes and style changes for you to consider:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define ALPHABET_LENGTH 26
#define MAXIMUM_CHARACTERS 200
int readLine(char string[], int maximum);
void findFrequency(char string[], int count[]);
int findMaximumIndex(int array[], int length);
int main(void)
{
char characters[MAXIMUM_CHARACTERS];
int frequencies[ALPHABET_LENGTH];
printf("Command Line Tool\n");
printf("Please enter text here: ");
(void) readLine(characters, MAXIMUM_CHARACTERS);
for (char c = 'A'; c <= 'Z'; c++)
{
printf("%c ", c);
}
printf("\n");
findFrequency(characters, frequencies);
for (int i = 0; i < ALPHABET_LENGTH; i++)
{
printf("%d ", frequencies[i]);
}
printf("\n");
int maximum = findMaximumIndex(frequencies, ALPHABET_LENGTH);
printf("%c occurred most often (%d times)\n", maximum + 'A', frequencies[maximum]);
printf("Finished excuting.\n");
return 0;
}
int readLine(char string[], int maximum)
{
int c, count = 0;
while (isspace(c = getchar()))
;
while (c != EOF && c != '\n')
{
if (count < maximum - 1)
{
string[count++] = c;
c = getchar();
}
}
string[count] = '\0';
return count;
}
void findFrequency(char string[], int count[])
{
for (int i = 0; string[i] != '\0'; i++)
{
char c = string[i];
if (c >= 'A' && c <= 'Z' )
{
count[c - 'A']++;
}
}
}
int findMaximumIndex(int array[], int length)
{
int index = 0;
for (int i = 1; i < length; i++)
{
if (array[i] > array[index])
{
index = i;
}
}
return index;
}
EXAMPLE OUTPUT
> ./a.out
Command Line Tool
Please enter text here: IN TEACHING OTHERS WE TEACH OURSELVES
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
2 0 2 0 6 0 1 3 2 0 0 1 0 2 2 0 0 2 3 3 1 1 1 0 0 0
'E' occurred most often (6 times)
Finished excuting.
>
Things yet to ponder: your output won't look as nice if any character occurs more than 9 times -- how can you fix that; you might want to deal with mixed case as an option in your readLine() routine to uppercase the input; there may be a (multi-way) tie for the most frequently occuring letter, can you deal with that; your readLine() returns a count of characters that you don't do anything with -- how might it be useful (possibly in error checking)?

Related

Why does my letter counter display 0 when put in a function

I'm very new to C and trying to create a counter for how many times the letter "a" appears in a string. I get it working by putting it directly into main, however when I put it into a function, my printf outputs 0.
#include <stdio.h>
#include <string.h>
#define STRING_LENGTH 50
void letter_counter(char input[STRING_LENGTH], int count, char letter ) {
int i;
for (i = 0; i < strlen(input); i++){
if (input[i] == letter) {
count++;
}
}
}
int main() {
int a1 = 0;
char a = 'a';
printf("Please write a word\n");
char input[STRING_LENGTH] = {0};
fgets(input,STRING_LENGTH,stdin);
input[strlen(input) - 1] = 0;
letter_counter(input, a1, a);
printf("%i\n", a1);
}
You are not returning the value of what you have counted. It looks like you think that a1 is going to contain the total, but it's not.
Your letter_counter function needs to return an int value, not void.
int letter_counter(char input[STRING_LENGTH], char letter ) {
int i;
int count = 0;
for (i = 0; i < strlen(input); i++){
if (input[i] == letter) {
count++;
}
return count;
}
Then you need to assign the return value of the function to a variable:
a1 = letter_counter(input, a);

What is the error in this program. Some in main function looping statement to get input

Code:
#include <stdio.h>
#include <string.h>
void check(char *s, char *b)
{
int l, l1;
l = strlen(s);
l1 = strlen(b);
int i = 0, j = 0, count = 0;
while (i < l & j < l1)
{
if (s[i] == b[j])
{
j = j + 1;
count++;
}
i = i + 1;
}
if (count == l1)
{
printf("POSITIVE");
}
else
{
printf("NEGATIVE");
}
}
int main()
{
char s[100], b[100];
scanf("%s", s);
int a, i;
scanf("%d", &a);
for (i = 0; i < a; i++)
{
scanf("%d", &b[i]);
check(s, b);
}
}
Input:
CORONAVIRUS
3
abdce
ravus
onarous
Expected output:
NEGATIVE
POSITIVE
NEGATIVE
My output is like:
NEGATIVENEGATIVENEGATIVE
This is wrong.
scanf("%d", &b[i]);
You have asked the compiler to expect a int input by writing %d. However, you are entering a string. Change it to:
scanf("%s", b);
Also, you are making comparisons between lowercase and uppercase. In that case, change the lowercase character to uppercase character using the function toupper(). Or alternatively use tolower() to change it to lower case.
Your comparison should look like this to make case insensitive character comparison.
if (s[i] == b[j])
Change it to:
if (s[i] == b[j] || s[i]==toupper(b[j]) || tolower(s[i])==b[j])
Your complete code may look like this:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void check(char *s, char *b)
{
int l, l1;
l = strlen(s);
l1 = strlen(b);
int i = 0, j = 0, count = 0;
while (i < l & j < l1)
{
if (s[i] == b[j] || s[i]==toupper(b[j]) || tolower(s[i])==b[j])
{
j = j + 1;
count++;
}
i = i + 1;
}
if (count == l1)
{
printf("POSITIVE\n");
}
else
{
printf("NEGATIVE\n");
}
}
int main()
{
char s[100], b[100];
scanf("%s", s);
int a, i;
scanf("%d", &a);
for (i = 0; i < a; i++)
{
scanf("%s", b);
check(s, b);
}
return 0;
}

Program that reads three lines of text and counts each alphabet letter (C)

I'm fairly new to coding and am currently enrolled in a course at school teaching C. We have been given an assignment that requires as follows:
Write a program that inputs three lines of text and uses the function strchr to determine the number of occurrences of each letter of the alphabet (uppercase and lowercase should be counted as the same). Store the totals for each letter in an array and print the result.
Here's the code I've written so far:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define SIZE 100
int main(void) {
int alphabet[26] = { 0 };
char string[3][SIZE];
int i, j;
int c;
printf("Enter three lines of text:\n");
for (i = 0; i <= 2; i++) {
fgets(string[i], SIZE, stdin);
}
for (i = 0; i <= 2; i++) {
for (j = 0; &string[i][j] != '\0'; j++) {
string[i][j] = tolower(string[i][j]);
}
for (j = 0; &string[i][j] != '\0'; j++) {
if (strchr(&string[i][j], ('a' + j)) != NULL) {
alphabet[j]++;
}
}
}
printf("\n");
for (i = 0; i < 26; i++) {
printf("%c: %d\n", ('a' + i), alphabet[i]);
}
printf("\n");
return 0;
}
The problem with the current program I have is that the counter for the array alphabet[] doesn't seem to be incrementing the count properly.
The output should count, for example, increment by 1 for each occurrence of every letter, but the results are all 0.
Any other tips or words of advice are greatly appreciated!
Your test for end of line is wrong,
no need to loop several time just parse the string and count the letters
You want letter between 'a'and 'z', check if the char is in the range and count it
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define SIZE 100
int main(void) {
int alphabet[26] = { 0 };
char string[3][SIZE];
int i, j;
printf("Enter three lines of text:\n");
for (i = 0; i <= 2; i++) {
fgets(string[i], SIZE, stdin);
}
for (i = 0; i <= 2; i++) {
for (j = 0; string[i][j] != '\0'; j++) {
char c = tolower(string[i][j]);
if (c >= 'a' && c <= 'z') {
alphabet[c - 'a']++;
}
}
}
printf("\n");
for (i = 0; i < 26; i++) {
printf("%c: %d\n", ('a' + i), alphabet[i]);
}
printf("\n");
return 0;
}
You need to change loop terminating condition from &string[i][j] != '\0'; to string[i][j] != '\0';
strchr will return the address from the string where match was found, so you should save the non null address to pass it to next call to strchr
Something like this:
tmpPtr = &string[i][j];
while ((tmpPtr=strchr(tmpPtr, string[i][j])) != NULL) {
alphabet[string[i][j] - 'a']++;
}

C program that finds out 2 most common letters in a string, and reverses them in the same string

This is what I have at the moment:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENG_LETTERS 26
#define STR_LEN 100
int main()
{
int countArray[ENG_LETTERS] = {0};
char str[STR_LEN] = { 0 };
char engChar = 'a' - 1;
int length = 0;
int i , j = 0;
int max = 0;
int index = 0;
printf("Please enter a string:\n");
fgets(str , STR_LEN , stdin);
length = strlen(str);
for(i = 0 ; i <= length;i++)
{
if(str[i] == '\n')
{
str[i] = '\0';
}
}
for(i = 0;i < ENG_LETTERS;i++)
{
engChar++;
for(j = 0;j <= length - 1;j++)
{
if(str[j] == engChar)
{
countArray[i]++;
}
}
}
engChar = 'a'- 1;
for(i = 0; i <= ENG_LETTERS - 1;i++)
{
engChar++;
printf("There are %d %c letters\n", countArray[i],engChar);
}
system("PAUSE");
return 0;
}
This basically lets me check how many letters are in the whole. I tried searching the whole internet to check how can I find the 2 most frequent, and reverse them in the string*. Am I doing something wrong? How can I improve?
(When I say reverse them in a string, I mean that instead of " i love this game i do i do " there will be " o live thos game o di o di" since "i" is the most frequent and "o" is the second most.)
here is sample, how you can count 2 most frequent symbols:
int freq[ENG_LETTERS] = { 0 };
char str[STR_LEN] = { 0 };
char *pStr = str;
int i, max, max2; // max - most frequent one, max2 - second most frequent
printf("Please enter a string:\n");
fgets(str, STR_LEN, stdin);
while (*pStr) {
if ((*pStr >= 'a') && (*pStr <= 'z'))
++freq[(*pStr) - 'a']; // convert from symbol to index
++pStr;
}
max = max2 = 0; // lets assume that first letter (a) is most frequent one
for (i = 1; i < ENG_LETTERS; ++i) {
if (freq[i] > freq[max]) {
max2 = max; max = i; // save old max and update new max
} else if (freq[i] > freq[max2])
max2 = i;
}
max += 'a'; // convert indexes back to symbols
max2 += 'a';
printf("%c %c\n", max, max2);
pStr = str; // swap max symbols
while (*pStr) {
if (*pStr == max) *pStr = max2;
else if (*pStr == max2) *pStr = max;
++pStr;
}
printf("%s\n", str);
One proposal, the idea is to:
compute frequencies
sort the results with qsort and a comparator function
swap the 2 characters in the string
static int frequencyComparator (void const *a, void const *b)
{
const Histo* ha=a;
const Histo* hb=b;
return hb->freq-ha->freq;
}
struct Histo
{
char c;
int freq;
};
Histo histo[ENG_LETTERS]={0};
char str[STR_LEN] = { 0 };
char *pStr = str;
printf("Please enter a string:\n");
fgets(str, STR_LEN, stdin);
int index=0;
while(*pStr!=0)
{
index=(*pStr)-'a';
if(index>=0 && index<26)
{
histo[index].c=(*pStr);
histo[index].freq++;
}
pStr++;
}
qsort (histo, ENG_LETTERS, sizeof(Histo), frequencyComparator);
if(histo[0].freq>0 && histo[1].freq>0)
{
printf("%c %c\n", histo[0].c, histo[1].c);
pStr = str;
while(*pStr!=0)
{
if(*pStr==histo[0].c) *pStr=histo[1].c
else if(*pStr==histo[1].c) *pStr=histo[0].c
pStr++;
}
}
printf("%s\n", str);

K&R 1.19 exercise ("reverse" func)

Here is the task:
Write a function reverse(s) that reverses the character string s . Use it to write a program that reverses its input a line at a time.
Ok, now, my performing:
#include <stdio.h>
#define LIM 40
char line[LIM];
int c;
int reverse(char line[], int lim);
int len;
int main(void) {
while ((len = reverse(line, LIM)) > 0) {
;
}
printf("\n END OF THE PROGRAM \n");
return 0;
}
********** THE REVERSE FUNCTION*********
int reverse(char s[], int lim) {
char rev[LIM];
int i;
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
s[i] = c;
}
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
int r;
for (r = 0; r < lim - 1; ++r) {
rev[r] = s[i];
--i;
}
int x;
for (x = 0; x < lim - 1; ++x) {
putchar(rev[x]);
}
printf("\n");
return r;
}
It seems to work correctly, but there are some bugs related to the output.
For example:
INPUT: hello everybody OUTPUT: ydobyreve olleh
INPUT: abc OUTPUT: cba'
INPUT: ABC OUTPUT: CBA'
INPUT: ABC ABC OUTPUT: CBA CBA
INPUT: se se OUTPUT: es es'
See? Some strange " ' " occurs in the end of output and I can't figure out any pattern why these "artifacts" get printed. It happens randomly (for me). Could you please suggest anything, what's wrong in the code?
Your reverse function has problems:
You should not store the newline into the s array as you do not want it to take part in the reverse operation.
You should stop the subsequent for loop when you reach the end of the string in s, not run all the way to the end of the buffer.
You should null terminate the rev array.
You do not need to output the rev array one character at a time, use is as a string.
Here is a corrected and simplified version:
#include <stdio.h>
#define LIM 40
int reverse(char line[], int size);
int main(void) {
char line[LIM];
int len;
while (reverse(line, LIM) > 0) {
continue;
}
printf("\n END OF THE PROGRAM \n");
return 0;
}
/* THE REVERSE FUNCTION */
int reverse(char s[], int size) {
char rev[size];
int i, r, c, len;
for (i = 0; i < size - 1 && (c = getchar()) != EOF && c != '\n'; i++) {
s[i] = c;
}
len = i;
s[i] = '\0';
for (i = 0; i < len; i++) {
rev[len - i - 1] = s[i];
}
rev[i] = '\0';
printf("%s\n", rev);
return len;
}
A bit more modular solution. I wasn't exactly sure what K&R meant by "one line at a time". But this will reverse the string until it finds a newline. Then wait for the user and repeat.
#include <stdio.h>
#define MAXLINE 1000
int get_line(char s[], int limit);
int reverse(char to[], char from[], int l);
int main() {
int size;
char line[MAXLINE];
while ((size = get_line(line, MAXLINE)) > 0) {
char revline[size];
int len = reverse(revline, line, size);
printf("%s\n", revline);
}
return 0;
}
int reverse(char to[], char from[], int l) {
int i;
int j = l - 2;
for (i = 0; i < l; i++, j--) {
to[i] = from[j];
}
to[i] = '\0';
return i;
}
// read a line into s until limit
// return length of line
int get_line(char s[], int limit) {
int c = 0;
int i = 0;
for (i = 0; i < limit-1 && (c = getchar()) != '\n'; ++i) {
s[i] = c;
}
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
Output:
testing one two
owt eno gnitset
three four
ruof eerht
five six
xis evif

Resources