I'm doing a course online in C and this is the assignment:
You are still conducting linguistic research! This time, you'd like to
write a program to find out how many letters occur multiple times in a
given word. Your program should read a word from the input and then
sort the letters of the word alphabetically (by their ASCII codes).
Next, your program should iterate through the letters of the word and
compare each letter with the one following it. If these equal each
other, you increase a counter by 1, making sure to then skip ahead far
enough so that letters that occur more than twice are not counted
again. You may assume that the word you read from the input has no
more than 50 letters, and that the word is all lowercase.
The solution they provide:
#include <stdio.h>
int main(void)
{
char word[51];
int length = 0;
int i, j;
char swap;
int repeats = 0;
scanf("%s", word);
while (word[length]!='\0')
length++;
//Sort the word by alphabetical order
for(j=0;j<length-1; j++) {
for(i=0;i<length-1;i++) {
if (word[i] > word[i+1]) {
swap = word[i];
word[i] = word[i+1];
word[i+1] = swap;
}
}
}
i = 0;
//Check for repeating characters in the sorted word
while (i<length-1) {
if (word[i]==word[i+1]) {
repeats++;
j=i+2;
//Continues through the word until it reaches a new character
while (j<length && word[i]==word[j])
j++;
i = j;
} else {
i++;
}
}
printf("%d", repeats);
return 0;
}
I understand everything up to code "//check for repeating characters in the sorted word//".
Specifically I don't understand the purpose or logic of "j=i+2" (especially the "+2") and how it relates to the next section of code "//continues through the word until it reaches a new character". I don't think this was adequately explained in the tutorials provided by the course.
Any insight or feedback is much appreciated.
Imagine your word is printed on paper, and you examine it through a small hole in a cardboard sheet. You can only see 2 letters at a time.
First, look at the beginning of the word. Identical letters? If not, shift by 1 position and repeat. If yes:
You found one repeated letter. Now you should find where the repeated run ends. To do that, shift your examination hole to the end of the repeated run.
It is possible to do this shift correctly in several ways. The way they implemented is until the first of the two visible letters is different from the repeated letters you found earlier. To do that, first you should shift by 2 positions, because at that position in code you know that the two letters are identical. But you could shift by 1 position instead — that would be correct too.
Another correct implementation — shift until you see two different letters in the hole. This may be easier to implement and more intuitive.
Related
Task:
Create a function maxRepeatingLetter that receives a string and as a result returns the letter that is repeated the most times in the given string (if more than one letter meets the given condition, return the first letter of the English alphabet). It is assumed that there will be at least one letter in the string.
Code:
#include <stdio.h>
char maxRepeatingLetter(const char *s)
{
int i, max = 0, maxIndex = 0;
int letter[26] = {0};
const char *pom = s;
while (*pom != '\0')
{
if ((*pom >= 'a' && *pom <= 'z'))
{
letter[*pom - 97]++;
}
if (*pom >= 'A' && *pom <= 'Z')
{
letter[*pom - 65]++;
}
pom++;
}
for (i = 0; i < 26; i++)
{
if (letter[i] > max)
{
max =letter[i]; maxIndex = I;
}
return maxIndex + 65;
}
int main ()
{
printf("Most repeating letter is: %c",
maxRepeatingLetter("input for letter to repeat"));
return 0;
}
My current task is being able to explain the code above and how it works. And I need to input a minor change into it, for example, to add something to the code, or make it simpler. But not to lose the main functions the code has.
Is anyone willing to explain the code above in 2-3 lines? And if you could, assist me or hint me, or even show me, what changes to the code I could apply.
I can see that you have to distinguish lowercase and uppercase and you can have only letters not symbols such as ? | ^ ! ecc... so I'll try to give you some advice:
Try to indent the code, it will be more readable to an external eye.
Using the variable letter is a good idea but i don't get the point of using pom.
If you can use use the function strlen() from the library string.h, otherwise implementing it by yourself could be a good exercise.
letter[*pom - 97]++, letter[*pom - 65]++ and maxIndex + 65 are dependant from the ASCII table, try letter[*pom - 'a']++, letter[*pom - 'A']++ and maxIndex + 'A'.
The for loop doesn't work, you missed a brackets so the if isn't in the for.
The code explanation is pretty easy, first of all you use the arrayletter of 26 elements because in the alphabet we have 26 letters, so the i-th element correspond to the i-th letter of the alphabet.
You loop once on the string and save in the i-th element letter the number of occurrence of the i-th letter.
With the if in for loop you are simply finding the max in that array, once found it, you return the index of the max, the index is the letter occuring more often.
Sorry for my bad English tell me if you need more help.
It is very straightforward if you are looking for an explanation of the above code. I recommend using multiple prints to understand how things are happening. Here are my few tips.
function maxRepeatingLetter() is updating the counter table letter[] each time the character appears.
After that, the code tries to find the highest number in the counter table letter[].
I've been asked to find the number of characters that are compared during naive string matching. This was the function we were asked to implement:
// Count the number of characters compared while finding all occurences of the pattern in the given text
// Characters must be matched from left to right
int charactersCompared(char *pattern, char *text);
So if the text is:"ABCEDF" and the pattern is: "EF" the number of characters I would compare using the brute force method would be 6 (comparing the first letter of text with the first letter of the pattern. If it does not match, compare the second letter of the text with the first letter of the pattern again.
If it matches, continue with the comparing the next letters of both text and pattern and so on)
After figuring out a logic with many example cases, I implemented the above function this way:
int charactersCompared(char *pattern, char *text)
{
int i,j,comp=0;
int flag;
for(i=0;text[i]!='\0';i++) //iterating through all the letters of text
{
for(j=0;pattern[j]!='\0';j++)
{
comp++; //to count one comparision.
if(text[i+j]==pattern[j]) //to check if similar to pattern
{
flag=1;
continue;
}
else
{
if(flag==1)
{
flag=0;
comp--;
}
break;
}
}
}
//printf("VALUE OF C=%d\n",comp);
return comp;
}
This works fine for the pair(ABCDEF,EF) (where the count is 6) but not for other test cases which include multiple occurrences of the pattern in text such as:
Text: ABCDEFGHEIEF
Pattern: EF
I'm supposed to get 14 comparisions whereas my output is 12. I don't understand where I am missing out.
If anyone can point out what is the faulty logic, it'd be of great help. Or if there is an easier way to do this, suggestions appreciated. The only constraint is that the method has to be a brute force method (i.e I can't really change the part where i compare each character of each string).
Thank you for your time!
Please note that in worse case is n(m-n+1) , where n is length of pattern and m is length of text. Now, Since you only want to compute comparisons, there's no need for variable flag. Prefer KISS principle.
for(i=0;text[i]!='\0';i++) //iterating through all the letters of text
{
for(j=0;pattern[j]!='\0';j++)
{
comp++; //to count one comparison.
if(text[i+j]==pattern[j]) //to check if similar to pattern
continue;
break;
}
}
printf("VALUE OF C=%d\n",comp);
So i figured out why my program incremented comp extra number of times in the answer posted by #E.N.D . It was because the outer for loop continued until each letter in the text was not compared. But when we do it manually, it's only until the the number of letters remaining in text while comparision are equal to or more than the number of letters in pattern. So i changed a condition
int charactersCompared(char *pattern, char *text)
{
int i,j,comp=0; //int flag;
int lenp=length(pattern),lent=length(text);
for(i=0;i<=lent-lenp;i++)
{
for(j=0;pattern[j]!='\0';j++)
{
comp++;
if(text[i+j]==pattern[j])
{
continue;
}
break;
}
}
//printf("VALUE OF C=%d\n",c);
return comp;
}
This makes sense and works! Thanks for those who tried to answer!
I'm right now writing a code for my coursework that analyzes a manually inserted text. I'm supposed to find the total number of non-space characters, and total words. Also, I'm supposed to find any repeated words in the string, then display them with the number of repetitions. I'm stuck in finding repeated words and displaying the number of repetitions. Also, my knowledge to C is limited, with the topics I know including pointers, strings, files, and functions, loops, if conditions, etc... Below is my code so far:
#include <stdio.h>
int num, numi, text, length, length1, word;
numi = 0;
word = 1;
int main()
{
char text[] = "Dennis MacAlistair Ritchie (September 9, 1941 - October 12, 2011) was an American computer scientist. He created the C programming language and, with long-time colleague Ken Thompson, the Unix operating system and B programming language. Dennis Ritchie was born in Bronxville, New York. His father was Alistair E. Ritchie, a long-time Bell Labs scientist and co-author of The Design of Switching Circuits on switching circuit theory. As a child, Dennis moved with his family to Summit, New Jersey, where he graduated from Summit High School. He graduated from Harvard University with degrees in physics and applied mathematics.";
printf("Welcome to UNM Text Editor. Your original text is:\n\n");
printf("%s", text);
length = strlen(text);
for (numi=0; numi<=length; numi++)
{
if (text[numi] == ' ')
{
length1++;
if (text[numi + 1] != ' ')
{
word++;
}
}
}
printf("\n\nThe total number of characters (without spaces) is: %d", length-length1);
printf("\nThe total number of words is: %d", word);
}
According to what I've read in comments you already solved first two points so i'm going to focus mainly on repetitions.
To do it you can use Trie data structure, please take a look at below link.
https://www.geeksforgeeks.org/trie-display-content/
it's in C++ but not so many things from C++ are really used so it can be easily rewrite to C. You need to add only a few lines to GeeksForGeeks code to make it work. Because it's your coursework perhaps you shouldn't just use whole code but write own one, but I would like to show you and general idea,
Add variable number of occurrences of "string" to struct:
struct TrieNode
{
struct TrieNode* children[alpha_size];
bool isLeaf;
int occurrence; // <-- I ADDED IT HERE
}
in the end of insert_node_function add:
...
pCrawl->isLeaf = true;
pCrawl->occurrence++; // <-- I ADDED IT HERE
...
Display only when number of occurrences bigger than 1
void display(struct TrieNode* root, char str[], int level)
{
// If node is leaf node, it indicates end
// of string, so a null character is added
// and string is displayed
if (isLeafNode(root) && root->occurrence > 1) // <-- I ADDED IT HERE
{
str[level] = '\0';
cout << str << " " << root->occurrence << endl; // <-- I ADDED IT HERE
}
...
One thing that remains is how to read a single word from "text" (char text in your example). To make it easier you can remove all duplicated spaces and go through the text once again. Then you can copy word treating space as a delimiter (for instance by using strncat) and insert to trie.
To understand how trie works try to google it. There should be loads of info about it.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I need to make a code that identifies the longest string of characters that a separated by space. If there are characters of same length, write them both.
Ex:
Input = Java flow car tree
Output = Java flow tree
Her is the code i wrote
#include <stdio.h>
#include <stdlib.h>
int main()
{
char cuv[100], big[100];
int i;
printf("Scrieti cuvintele\n");
gets(cuv);
cuv[0] = big[0];
for(i = 0; cuv[i] = '/0'; i++){
if(cuv[i] > big[i]){
big[i] = cuv[i];
}
}
printf("%s", big);
return 0;
}
The problem is i dont know very well how char works. So i have little clue on what to do. I ask of you on how to use the char set to be able to count strings in a specific way.
Here is a very simple solution. Try to understand the code. Note the code uses some of the functions from #include<string.h>. So, before going through the code please go through string.h header file and understand the standard functions it provides.
Anyways, here is a very basic program,(feel free to modify it to your needs)
#include<stdio.h>
#include<string.h>
#define MAX 256
int main(){
char input[MAX],*tmp=NULL;
char *word_list[MAX],*word=NULL;
int flag[MAX];
int i=0,index=0,m=0,largest_len=0;
//Get Input From User
printf("Enter Input:\n");
fgets(input,MAX,stdin);
//If using fgets then use strchr() to locate '\n' and replace it with '\0'(null terminating char)
if((tmp=strchr(input,'\n')) != NULL){
*tmp='\0';
}
//Use strtok() function to split the sentence/input into words separated by space
//and store them in an array of char pointers(or more like array of strings)
word = strtok(input," ");
word_list[index] = word;
index++;
while(word != NULL && i<MAX){
word=strtok(NULL," ");
if(word != NULL){
word_list[index] = word;
index++;
}
}
//find the word with the largest lenght
for(i=0;i<index;i++){
if(strlen(word_list[i]) >= largest_len){
largest_len = strlen(word_list[i]);
}
}
//Then store the index of words which have their lenght equal to the largest lenght
for(i=0;i<index;i++){
if(strlen(word_list[i]) == largest_len){
flag[m] = i;
m++;
}
}
//Print the largest words
m=0;
printf("Largest Word('s):");
for(i=0;i<index;i++){
if(flag[m] == i){
printf("%s ",word_list[i]);
m++;
}
}
return 0;
}
The code you've posted doesn't seem to even come close to what you're trying to do -- so much so that it's really not salvageable towards a solution.
That said, think about your "large" (complete) problem as a series of smaller problems instead; each smaller problem is easier to solve than the single larger problem. Your problems seem to be:
1) Input your raw data.
2) Split your raw data into words. You could manually walk through your data looking for spaces and doing what you feel appropriate when you find them, or you could figure out how to use strtok() to parse data for you. Given where you are with your language understanding, doing it manually is probably a better learning experience.
3) Determine the length of the largest word in your collection.
4) Go through your entire collection and output each word whose length is equal to that largest length.
For problem 1, you seem to have this accomplished (but pay attention to the suggestions people have given you about better ways to do it).
Problem 2 might be the most challenging. There are several ways one can go about it. I'm not going to provide a solution, but this snippet is a small start:
for (i = 0; cuv[i] != '\0'; ++i) {
/* do something */
}
Pay attention to the middle term of the for loop; it's not making an assignment to cuv[i] (I point this out because in your posted program, you are making an assignment, which is really not what you intend.) It is comparing the character to the standard C string termination.
You'll need to look at each character as you go through the loop and decide if you are increasing the current word, ending the previous word, starting a new word, or just skipping repetitive whitespace.
You'll need to store a pointer to each word somewhere so that the full set of words will be available to steps 3 and 4.
Note that you could perform step 3 while you're doing this but you should not for now. It would make your program more efficient, but it merges the steps together and while learning, you don't need that.
Problem 3 requires you to be aware that strlen(const char *s) will return the length of s, where s is a properly terminated C string.
To solve this you will simply iterate through your full set of words and inspect the length of each; if the length is greater than the previous maximum you will increase your stored maximum. Something like:
unsigned int maxLength = 0;
for (i = 0; i < numberOfWords; ++i) {
if (strlen(word[i]) > maxLength)
maxLength = strlen(word[i]);
}
Finally, for step 4 you will iterate through your list of words again, deciding which ones to print out. Something like:
for (i = 0; i < numberOfWords; ++i) {
if (strlen(word[i]) == maxLength)
printf("%s\n", word[i]);
}
Hey this is my first post here. i have been assigned with an excercise to count the most frequent word in c programming language. first and foremost i need to read a number which tells me how many words i will have to read. then i need to use calloc with max element size 50. after that i read the strings. my original idea was to create a one-dimensional array which im gonna later sort alphabetically and then counting and printing the most frequent word would be easy. but after some hours of research i found out i need to use a two-dimensional array and things went out of control. ive been studying computer science for 3 months now and this exercise seems tough. do u have any other suggestions?. the example was this:
10
hello
world
goodbye
world
thanks
for
all
hello
the
fish
hello
my code so far is
int main()
{
int i, n, j, temp;
int *a;
printf("Eisagete to plhthos twn leksewn:");
scanf("%d",&n);
a = (int*)calloc(n,50);
printf("Eisagete tis %d lekseis:\n",n);
for( i=0 ; i < n ; i++ )
{
scanf("%d",&a[i]);
}
for (i = 0 ; i < ( n - 1 ); i++)
{
for (j = 0 ; j < n - i - 1; j++)
{
if (a[j] > a[j+1])
{
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
dont mind the printfs they are in greek and they are just there to make it look better. i also want to point out that this version is used for integers and not for strings just to start off.
im currently trying a linear search but im not sure if it will help
As you point out, the code you show is related to reading and sorting integers; it is only loosely related to the word counting problem.
How would you count the occurrences of each number? You'd have to
Read the next number;
If you already have a tally for the number, you add one to the tally for that number;
If you've not seen the number before, you create a tally for it and set its count to one.
When all the numbers are read, you search through the set of tallies, looking for the one with the largest count.
Record the number and count of the first entry.
For each subsequent entry:
If the count is larger than the current maximum, record the new maximum count and the entry.
Print the information about the number with the largest count and what that count is.
Replace numbers with words and the general outline will be very similar. You might allocate storage for each string (distinct word) separately.
It is easy to count the number of distinct words or the total number of words as you go. Note that you do not need to store all the words; you only need to store the distinct words. And the count at the front of the list is computer science education gone astray; you don't need the count to make it work (but you probably have to live with it being in the data; the simplest thing is to ignore the first line of input since it really doesn't help very much at all). The next simplest thing is to note that unless they're fibbing to you, the maximum number of distinct words will be the number specified, so you can pre-allocate all the space you need in one fell swoop.
Very simple. Store your words in a 2D array the loop through it and each time you take a word loop through it again starting from the current index and check if there is an equal. ech time the child loop ends check if the number of occurrences is bigger than the last maximum.
#include <stdio.h>
int main()
{
int i, j, occurrence=0, maximum = 0;
char *index_max = NULL;
char wl[10][10] = {"hello","world","goodbye","world","thanks","for","all","hello","the","world"};
for (i=0; i<10; i++){
occurrence = 0;
for (j=i; j<10; j++){
if (!strcmp(*(wl+i), *(wl+j))){
occurrence++;
}
}
if (occurrence>maximum){
maximum = occurrence;
index_max = *(wl+i);
}
}
if (index_max != NULL){
printf("The most frequent word is \"%s\" with %d occurrences.\n", index_max, maximum);
}
return 0;
}