How to get the most frequent letter in a word? - c

I am trying to get the most frequent letter in a string with only uppercased letters and no spaces between words. to do that I used a function maxArray(array, sizeof array) that gives the biggest number in the array in order to count how many times the letter is repeated and store the info in another array in the same position of each letter in the string. But in the two algorithms I have came up with it doesn't work.
PS: I am just a beginner.
Here is the code:
int maxArray(int *tab, int n) {
int i, tmp;
tmp = tab[0];
for (i = 1; i < n; i++) {
if (tmp < tab[i])
tmp = tab[i];
}
return tmp;
}
//first algo(didn't finish it)
char occurencedelettre(char *string) {
int *array;
int i, j, compt, max;
for (i = 0; string[i] !='\0'; i++) {
compt = 0;
for (j = 0; string[j] !='\0'; j++) {
if (string[i] == string[j])
compt++;
}
array[i] = compt;
}
return array;
}
//second one
char occurencedelettre(char *string) {
int count[25] = { 0 };
int x = 0;
char result;
for (int i = 0; string[i] != '\0'; i++) {
count[string[i]]++;
if (x < count[string[i]]) {
x = count[string[i]];
result = string[i];
}
}
return result;
}

The second approach is almost correct except for these problems:
the array should have a length of 26
you must subtract 'A' from the value of the letter to get an index between 0 and 25, assuming the word only contains uppercase letters in ASCII.
you must intialize result to return 0 (or any other specific value) for an empty word.
Here is a modified version:
char occurencedelettre(const char *string) {
size_t count[26] = { 0 };
size_t x = 0;
char result = '\0';
for (size_t i = 0; string[i] != '\0'; i++) {
count[string[i] - 'A']++;
if (x < count[string[i]]) {
x = count[string[i]];
result = string[i];
}
}
return result;
}
The first approach is more cumbersome and slower, but also more generic as it may work for any word contents. Here is a modified version:
char occurencedelettre(const char *string) {
char result = 0;
size_t max_count = 0;
for (size_t i = 0; string[i] != '\0'; i++) {
size_t count = 1;
for (size_t j = i + 1; string[j] != '\0'; j++) {
if (string[i] == string[j])
count++;
}
if (max_count < count) {
max_count = count;
result = string[i];
}
}
return result;
}
Note that you can adapt the first approach for any word contents, assuming 8-bit bytes:
char occurencedelettre(const char *string) {
size_t count[256] = { 0 };
size_t x = 0;
char result = '\0';
for (size_t i = 0; string[i] != '\0'; i++) {
count[(unsigned char)string[i]]++;
if (x < count[(unsigned char)string[i]]) {
x = count[(unsigned char)string[i]];
result = string[i];
}
}
return result;
}

Related

how to write a function char* in c that returns words sorted in order of their length?

Write a function that takes a string as a parameter and returns its words sorted in order of their length first and then in alphabetical order on line separated by '^'
here is examples of output
There will be only spaces, tabs and alphanumeric caracters in strings.
You'll have only one space between same size words and ^ otherwise.
A word is a section of string delimited by spaces/tabs or the start/end of the string. If a word has a single letter, it must be capitalized.
A letter is a character in the set [a-zA-Z]
here is my code, but it returns nothing I think issue in last function....
#include <unistd.h>
#include <stdlib.h>
int is_upper(char c)
{
return c >= 'A' && c <= 'Z';
}
int my_lower(char c)
{
if (is_upper(c))
return c + 32;
return c;
}
int my_strlen(char *s)
{
int i = 0;
for (; s[i]; i++)
;
return i;
}
int my_is(char c)
{
return c == ' ' || c == '\t';
}
char *my_strsub(char *s, int start, int end)
{
char *res = malloc(end - start);
int i = 0;
while (start < end)
res[i++] = s[start++];
res[i] = 0;
return res;
}
int cmp_alpha(char *a, char *b)
{
while (*a && *b && *a == *b)
{
a++;
b++;
}
return my_lower(*a) <= my_lower(*b);
}
int cmp_len(char *a, char *b)
{
return my_strlen(a) <= my_strlen(b);
}
void my_sort(char *arr[], int n, int(*cmp)(char*, char*))
{
char *tmp;
for (int i = 0; i < n; i++)
for (int j = 0; j < n - 1; j++)
{
if ((*cmp)(arr[j], arr[j + 1]) == 0)
{
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
char* long(char *s)
{
int start = 0, idx = 0;
char *words[my_strlen(s) / 2 + 1];
for (int i = 0; s[i]; i++)
{
if (!my_is(s[i]) && i > 0 && my_is(s[i - 1]))
start = i;
if (my_is(s[i]) && i > 0 && !my_is(s[i - 1]))
words[idx++] = my_strsub(s, start, i);
if (!s[i + 1] && !my_is(s[i]))
words[idx++] = my_strsub(s, start, i + 1);
}
my_sort(words, idx, &cmp_alpha);
my_sort(words, idx, &cmp_len);
char* res = malloc(100);
int pushed=0;
for (int i = 0; i < idx - 1; i++)
{
res[pushed]=*words[i];
if (my_strlen(&res[pushed]) < my_strlen(&res[pushed + 1]))
{
res[pushed]=res[94];
}
else
{
res[pushed]=res[32];
}
pushed++;
}
res[pushed]='\0';
return res;
}
int main()
{
long("Never take a gamble you are not prepared to lose");
return 0;
}
Apart from the off-by-one allocation error in my_strsub, separating and sorting the words seems to work well. Only then you confuse the result character array with a character pointer array, e. g. with res[pushed]=*words[i] you write only the first character of a word to the result. The last for loop of ord_alphlong could rather be:
if (idx)
for (int i = 0; ; )
{
char *word = words[i];
int lng = my_strlen(word);
if (100 < pushed+lng+1) exit(1); // too long
for (int i = 0; i < lng; ) res[pushed++] = word[i++];
if (++i == idx) break; // last word
res[pushed++] = lng < my_strlen(words[i]) ? '^' // other size
: ' '; // same size
}
Of course in order to see the result of the function, you'd have to output it somehow.

Selection of unique characters

Please, help with the code.
Requirement:
Write a function my_union that takes two strings and returns, without doubles, the characters that appear in either one of the strings.
Example:
Input: "zpadinton" && "paqefwtdjetyiytjneytjoeyjnejeyj"
Output: "zpadintoqefwjy"
My code:
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
char *my_union(char *a, char *b) {
char *str;
// Algorithm for excluding nonunique characters from string a(given in
// parameters).
str[0] = a[0];
int k = 1;
str[k] = '\0';
for (int i = 1; a[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == a[i]) {
is = false;
break;
}
}
if (is) {
str[k] = a[i];
k++;
str[k] = '\0';
}
} // In this case we are excluding excess character 'n' from "zpadinton", so
// str is equal to "zpadinto".
// Algorithm for adding unique characters from array b(given in parameters)
// into str.
for (int i = 0; b[i] != '\0'; i++) {
bool is = true;
for (int j = 0; str[j] != '\0'; j++) {
if (str[j] == b[i]) {
is = false;
break;
}
}
if (is) {
strncat(str, &b[i], 1);
}
}
return str;
}
The first algorithm is almost identical with second, but it doesn't work(. Mb I messed up with memory, give some advice, pls.
If you mean, get the unique characters from two strings and store them into a new string, try this code ;
First, you must allocate a memory for str. In your code, str is not pointing allocated memory location, so you will probably get segmentation fault.
int contains(const char * str,char c)
{
for (int i = 0; i < strlen(str); ++i)
if(str[i] == c)
return 1;
return 0;
}
char * my_union(char *a, char*b)
{
char * res = (char*)malloc(sizeof(char)*(strlen(a) + strlen(b)));
int pushed = 0;
for (int i = 0; i < strlen(a); ++i)
{
if(!contains(res,a[i])){
res[pushed] = a[i];
pushed++;
}
}
for (int i = 0; i < strlen(b); ++i)
{
if(!contains(res,b[i])){
res[pushed] = b[i];
pushed++;
}
}
return res;
}
int main(int argc, char const *argv[])
{
char string1[9] = "abcdefgh";
char string2[9] = "abegzygj";
char * result = my_union(string1,string2);
printf("%s\n", result);
return 0;
}
Also, do not forget the free the return value of my_union after you done with it.

passing char array to function from scanf in c

I have following function in c code
void analyze_text(char text[]) {
...
for (int i = 0; i < text_length || text[i] != '\0'; i++) {
...
}
}
In main function i would like to pass some string to it. If i do something like this
char text[4000] = "some text here";
analyze_text(text);
this is cool and do the goal, but i would like to have some user input present and I am not sure how to get char[] out of it. I tried following 2 and none of them seemed to work:
char text[4000];
scanf("%s",text);
analyze_text(text);
OR
char text[4000];
int c;
int count=0;
c = getchar();
count = 0;
while ((count < 4000) && (c != EOF)) {
text[count] = c;
++count;
c = getchar();
}
analyze_text(text);
I know that the first one should return pointer to char array, but second one should return char array itself, or not?
Its been like 10 years since i havent been working with c/c++. Can anybody give me some hint please?
update (whole function):
void analyze_text(char text[]) {
int printable_text_length = 0;
int text_length = strlen(text);
int word_count = 0;
int sentence_count = 0;
int in_sentence = 0;
int in_word = 0;
int count[ASCII_SIZE] = { 0 };
for (int i = 0; i < text_length || text[i] != '\0'; i++) {
int c = text[i];
if (!isspace(c)) {
printable_text_length++;
}
if (isalpha(c)) {
in_word = 1;
in_sentence = 1;
count[tolower(c)]++;
}
if (text[i] == ' ' && text[i + 1] != ' ' && in_word==1) {
word_count++;
in_word = 0;
}
if (text[i] == '.' && in_sentence==1) {
sentence_count++;
in_sentence = 0;
}
}
if (in_word == 1) { word_count++; }
if (in_sentence == 1) { sentence_count++; }
char charIndexes[ASCII_SIZE];
for (int i = 97; i <= 122; i++) {
charIndexes[i] = i;
}
for (int i=97; i <= 122; i++) {
for (int j = i + 1; j <= 122; j++) {
if (count[i] > count[j]) {
int temp = count[j];
count[j] = count[i];
count[i] = temp;
int temp2 = charIndexes[j];
charIndexes[j] = charIndexes[i];
charIndexes[i] = temp2;
}
}
}
...printf...
}
The issue with
char text[4000];
scanf("%s",text);
analyze_text(text);
is that scanf identifies space-separated chunks, so you'll only read the first one.
In order to read up to a whole line from the user, try fgets:
char text[4000];
fgets(text, 4000, stdin);
analyze_text(text);
You may want to check the return value of fgets for error detection.
You can use dyanamic array of char to pass it into the function.
Here is the code
#include <stdio.h>
#include <stdlib.h>
void analyze_text(char* text) {
for (int i = 0; text[i] != '\0'; i++) {
printf("%c\n",text[i] );
}
}
int main() {
char* text = (char *)malloc(4000 * sizeof(char));
scanf("%s", text);
analyze_text(text);
return 0;
}
and here is the output with input = 'abhishek'
a
b
h
i
s
h
e
k
remember that strlen in dyanamc array will not give the length of input array.

Function that takes a string and "filters out" all the non digit characters and all but the first dot in C?

For example: Say that the string is "90.%7."
The function would filter out the % and the second dot.
The function would thus return "90.7"
I'm flexible as to how it would return it.
Everything i have done so far hasn't worked. Sad Face.
Thanks.
Edit: I figured out how to do it.
Check out this code
void filter(const char * input, char * output)
{
int length = strlen(input);
int dot_was_seen = 0;
int i;
int j = 0;
for( i = 0 ; i < length ; i++)
{
if(input[i] >= 0x30 && input[i] <= 0x39)
output[j++] = input[i];
else if(!dot_was_seen && input[i] == 0x2E)
{
output[j++] = input[i];
dot_was_seen = 1;
}
}
output[j] = 0;
}
int main()
{
char input[] = "90.%7.";
char output[32];
filter(input, output);
printf(output);
return 0;
}

Anagram Solver, array[26] not working correctly

I've nearly finished my anagram solver program where I input two strings and get the result of whether they are anagrams of each other. For this example i'm using 'Payment received' and 'Every cent paid me'.
The problem i'm getting is when I output the letterCount arrays, letterCount1 is incorrect (it doesn't think there is a character 'd' but there is.) but letterCount2 is correct.
Can anyone see a problem with this because i'm completely baffled?
#include <stdio.h>
#include <string.h>
int checkAnagram(char string1[], char string2[])
{
int i;
int count = 0, count2 = 0;
int letterCount1[26] = {0};
int letterCount2[26] = {0};
for(i = 0; i < strlen(string1); i++)
{
if(!isspace(string1[i]))
{
string1[i] = tolower(string1[i]);
count++;
}
}
for(i = 0; i < strlen(string2); i++)
{
if(!isspace(string2[i]))
{
string2[i] = tolower(string2[i]);
count2++;
}
}
if(count == count2)
{
for(i = 0; i < count; i++)
{
if(string1[i] >='a' && string1[i] <= 'z')
{
letterCount1[string1[i] - 'a'] ++;
}
if(string2[i] >='a' && string2[i] <= 'z')
{
letterCount2[string2[i] - 'a'] ++;
}
}
printf("%s\n", string1);
for(i = 0; i < 26; i++)
{
printf("%d ", letterCount1[i]);
printf("%d ", letterCount2[i]);
}
}
}
main()
{
char string1[100];
char string2[100];
gets(string1);
gets(string2);
if(checkAnagram(string1, string2) == 1)
{
printf("%s", "Yes");
} else
{
printf("%s", "No");
}
}
That's because your count holds the count of non-space characters, but you keep the strings with the spaces.
For example, the string "hello world" has 11 characters, but if you run it through the loops your count will be 10 (you don't count the space). However, when you later go over the strings and count the appearance of each letter, you will go over the first 10 characters, therefore completely ignoring the last character - a 'd'.
To fix it, you need to go over all characters of the string, and only count the alphanumeric ones.
I fixed it for you:
#include <stdio.h>
#include <string.h>
int checkAnagram(char string1[], char string2[])
{
int i;
int count = 0, count2 = 0;
int letterCount1[26] = {0};
int letterCount2[26] = {0};
int len1 = strlen(string1);
int len2 = strlen(string2);
for(i = 0; i < len1; i++)
{
if(!isspace(string1[i]))
{
string1[i] = tolower(string1[i]);
count++;
}
}
for(i = 0; i < len2; i++)
{
if(!isspace(string2[i]))
{
string2[i] = tolower(string2[i]);
count2++;
}
}
if(count == count2)
{
for (i=0; i<len1; i++)
if (!isspace(string1[i]))
letterCount1[string1[i]-'a']++;
for (i=0; i<len2; i++)
if (!isspace(string2[i]))
letterCount2[string2[i]-'a']++;
int flag = 1;
for(i = 0; flag && i < 26; i++)
if (letterCount1[i] != letterCount2[i])
flag = 0;
return flag;
}
return 0;
}
main()
{
char string1[100];
char string2[100];
gets(string1);
gets(string2);
if(checkAnagram(string1, string2) == 1)
{
printf("%s", "Yes");
} else
{
printf("%s", "No");
}
}
First, don't calculate an string's length inside a loop. I extracted them into len1 and len2 variables.
Second, your loop was wrong! You shouldn't go up to count, you should go up to that string's length.
Third, you didn't return anything from checkAnagram function.

Resources