Words frequency with number of letters (basic loop only) - c

I Want to write C program to print words length and their frequency by letters number with basic loops techniques. I could get the word length work but I stuck with frequency
(example: Do 2 not 3 judge 5 a 1 book 4 (had solved this))
there are # words with 1 letter
there are # words with 2 letter
etc...
#include <stdio.h>
int main(void) {
char word[30];
int i = 0,b=0,c=0,j=0,d=0;
printf("Please enter a word: ");
for (i = 0; i < 30 ; i++){
scanf("%s", word);
while (word[b]!='\0'){
b++;
}
printf("%s %d ", word, b);
b = 0;
}
return 0;
}

Your question wasn't completely clear. But from what I understood, you also wanted to print the number of times(frequency) a word of length 'l' is inputted by the user. So I will answer that :
You could just store the length of the word in an array that the user inputs. Once all the inputs are read, you can just print the frequency of each word length from the stored array
Refer the following code to understand what I meant :
#include <stdio.h>
int main(void) {
char word[30];
int i = 0,b=0,c=0,j=0,d=0;
int word_length_freq[30]={0}; //an array which will store the frequency of word length(all initialized to 0)
//eg. if word is "hello" it will increase count of word_length_freq[5] by 1
printf("Please enter a word: ");
for (i = 0; i < 3 ; i++){
scanf("%s", word);
while (word[b]!='\0'){
b++;
}
word_length_freq[b]++;
printf("%s %d ", word, b);
b = 0;
}
for(int i=1;i<30;i++){ //This will print the frequency of all words from length 1 to 30
printf("There are %d words of length %d\n",word_length_freq[i],i);
}
return 0;
}
I hope this solves your question !

Related

How to pass an array made of strings in C

I'm just trying to write a simple code where I enter a 3 letter word and then print out the word I entered. I tried doing this by creating the array, and then making a loop where the counter "i" keeps incrementing and the scan function keeps working for each index value of the letter I add.
But there seems to be some error in line 16, and even then not sure if the logic of the code is right.
#include <string.h>
#define ALEN 3
int main (void)
{
char array[ALEN];
int i;
printf("Enter a 3 letter word> ");
scanf("%s", array);
for(i=0; i<ALEN; i++)
{
array[i] = array[ALEN];
scanf("%s", &array[i]);
}
printf("\n");
printf("Word entered: %s", char array[i]);
return 0;
}```

Last letter is input + 1 for some reason

I'm doing an exercise to print 3 letters taken from the user. The first two letters end up fine, but the last one is always the letter that comes after what the user inputs for some reason (I've tried a few different combinations of inputs and it's always the same result):
#include <stdio.h>
int main(){
char userChar[3];
int i;
for (i = 1; i <= 3; i++){
printf("Enter letter %d\n", i);
scanf(" %c", &userChar[i]);
}
printf("%c %c %c", userChar[1], userChar[2], userChar[3]);
return 0;
}
The input is: abc
The output is: abd
What did I screw up? Thanks for your help!
Edit made recommended changes but still not working
I'll post this as an answer just to clarify the amendments
#include <stdio.h>
int main(){
char userChar[3];
int i;
for (i = 0; i < 3; i++){ // the loop range
printf("Enter letter %d\n", i + 1); // for human use
scanf(" %c", &userChar[i]);
}
printf("%c %c %c", userChar[0], userChar[1], userChar[2]); // the array indexing
return 0;
}
Program session
Enter letter 1
a
Enter letter 2
b
Enter letter 3
c
a b c

Why doesn't my strcmp actually detect the smallest between 2 words?

I'm trying to write a program that finds the "greatest" and "smallest" between a set of words inputted by the user. The program should stop listening for words assign as the user inputs a 4 letters long word and I can suppose that there aren't any words longer than 20 letters.
Here's how it should work:
Enter word: dog
Enter word: zebra
Enter word: rabbit
Enter word: catfish
Enter word: walrus
Enter word: cat
Enter word: fish
Smallest word: cat
Largest word: zebra
I tried debugging the code and I noticed that my function only runs the first "if" twice (until zebra is inputted) and then stops working. I don't really get why, every word there is smaller than zebra so it should always run. Also I don't get why the second "if" doesn't run.
Here's my code:
#include <stdio.h>
#include <string.h>
#define N 20
int read_line(char smallest[], char largest[]);
int main(){
char smallest[N], largest[N];
int check = 0;
while(check != 4){
check = read_line(smallest, largest);
}
printf("Smallest word: %s\n", smallest);
printf("Largest word: %s\n", largest);
return 0;
}
int read_line(char smallest[], char largest[]){
char input[N];
printf("Enter word: ");
scanf("%s", input);
if(strcmp(smallest, input) < 0){
printf("Smallest is: %s was: %s\n", input, smallest);
strcpy(smallest, input);
}
if(strcmp(largest, input) > 0){
printf("Largest is: %s was: %s\n", input, largest);
strcpy(largest, input);
}
return strlen(input);
}
As others have pointed out there might be a problem initialization. Since the array is not initialized you don't know what's there that's why a comment was saying it is generating an undefined behaviour. In my case I run your original code inputting twice and even after zebra it continued. Anyway is always better to initialize.
Just put a scanf outside the loop and initialize both values to the first input:
EDIT
I did not pay attention to strcmp usage because the main problem seemed to be the initalization.
From your code and comment it is clear that you are also messing with strcmp. You should have read the documentation:
int strcmp(const char *s1, const char *s2);
Upon completion, strcmp() shall return an integer greater than, equal
to, or less than 0, if the string pointed to by s1 is greater than,
equal to, or less than the string pointed to by s2, respectively.
So strcmp(smallest, input) ) returns a value < 0 if smallest is less (before in the dictionary pages to be clear) than input. You should change to if(strcmp(smallest, input) > 0) meaning smallest is greater than input or to if(strcmp(input, smallest) < 0)
strcmp(largest, input) returns > 0 if largest is bigger than input. Your condition strcmp(largest, input) > 0 is wrong. You want the opposite: you can invert the comparison: strcmp(largest, input) < 0 or invert the inputs: strcmp(input, largest) > 0.
#include <stdio.h>
#include <string.h>
#define N 21
int read_line(char smallest[], char largest[]);
int main(){
char smallest[N];
char largest[N];
int check = 0;
char firstInput[N];
printf("Enter word: ");
scanf("%s", firstInput);
printf("Smallest and largest initialized to: %s\n", firstInput);
strcpy(smallest, firstInput);
strcpy(largest, firstInput);
while(check != 4){
check = read_line(smallest, largest);
}
printf("Smallest word: %s\n", smallest);
printf("Largest word: %s\n", largest);
return 0;
}
int read_line(char smallest[], char largest[]){
char input[N];
printf("Enter word: ");
scanf("%s", input);
if(strcmp(smallest, input) < 0){
printf("Smallest is: %s was: %s\n", input, smallest);
strcpy(smallest, input);
}
if(strcmp(largest, input) > 0){
printf("Largest is: %s was: %s\n", input, largest);
strcpy(largest, input);
}
return strlen(input);
}
In my opinion this is the clearer initialization (and more correct) since it uses user's input and does not rely on any condition. However the code is less compact than other possible initializations since you are repeating some part of the code.
EDIT alternative initializations
There are other initialization methods. One is to initialize for example to the lowest letter:
char smallest[N];
for (int i=0; i<N-1; i++)
{
smallest[i] = 'z' ;
}
smallest[N-1] = '\0';
char biggest[N];
for (int i=0; i<N-1; i++)
{
biggest[i] = 'a' ;
}
biggest[N-1] = '\0';
In your original code this will print something like zzzzz.... and aaaa....
Another alternative is to initialize them to the numerical min and max values of the range of char types (typically -128 and 127):
#include<math.h>
...
char smallest[N] ;
char biggest[N] ;
for (int i=0; i<N-1; i++)
{
smallest[i] = (char) (pow(2,sizeof(char)*8)/2 - 1);
}
smallest[N-1] = '\0';
for (int i=0; i<N-1; i++)
{
biggest[i] = (char) -1*(pow(2,sizeof(char)*8)/2);
}
biggest[N-1] = '\0';
However in case in your first print will print thrash (better not to print at all ).
EDIT FOR scanf alternatives
When a user is inputting anything, especially a string, it is a good behaviour to test if that input conforms to what you are expecting. In C this becomes even more important since inputting a string longer than the length (actually length-1) of the array in which the string will be stored will cause Segmentation fault error and the program crashes.
There is a simple way to avoid this: instead of scanf("%s", firstInput); do, in your specific case, scanf("%20s", firstInput); i.e. the length of your input array minus 1 (N-1). The problem with this approach is that you cannot use a dynamic value: for example:
#define M 20
scanf("%Ms", firstInput);
does not work.
According to this post you could:
#define MAX_STRING_LENGTH 20
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
{
...
char word[MAX_STRING_LENGTH+1];
scanf(file, "%" STRINGIFY(MAX_STRING_LENGTH) "s", word);
...
}
or follow the approach of this post:
int scanner(const char *data, char *buffer, size_t buflen)
{
char format[32];
if (buflen == 0)
return 0;
snprintf(format, sizeof(format), "%%%ds", (int)(buflen-1));
return sscanf(data, format, buffer);
}
NOTE
If you mix words with and without capital letters, the ordering might not work anymore: Zookeeper (fantastic animal) comes before antilope.
Ok, there are multiple flaws in your program:
First of all, as other answers pointed out, you should #define N as 21, not 20, so as to leave room for the null character.
Secondly, you should initialize your strings.
And, most importantly, you have messed the order of your strcmp arguments. You should either pass first input and then the string you want to compare to, or change the inequality signs.
Finally, you should initialize largest as "" so that the first character equals zero and so the string is smaller than all possible strings. And you should initialize smallest to the largest possible string (e.g. "\xFF", although that will not work if the input string starts with the non-ASCII character '\xFF'). Then, when you enter the first string, it will be copied over both buffers. However, you'd better set a variable to check for the first input string given, and add a condition to copy it to both largest and smallest. This is slightly more complex, but works with all strings.
Here is your updated code:
#include <stdio.h>
#include <string.h>
#define N 21
int read_line(char smallest[], char largest[]);
int not_first = 0;
int main(){
char smallest[N], largest[N];
int check = 0;
while(check != 4){
check = read_line(smallest, largest);
}
printf("Smallest word: %s\n", smallest);
printf("Largest word: %s\n", largest);
return 0;
}
int read_line(char smallest[], char largest[]){
char input[N];
printf("Enter word: ");
scanf("%s", input);
if(strcmp(input, smallest) < 0 || !not_first){
printf("Smallest is: %s was: %s\n", input, (not_first)? smallest : "(none)");
strcpy(smallest, input);
}
if(strcmp(input, largest) > 0 || !not_first){
printf("Largest is: %s was: %s\n", input, (not_first)? largest : "(none)");
strcpy(largest, input);
}
not_first = 1;
return strlen(input);
}

Sort words in a string based on their vowel number

I must write a program in C that allows an user to say how many words they want to enter in a string and then I must sort those words based on their vowel number(the word with more vowels is first and the one with the least vowels is last - if two words have the same number of vowels then leave them in the order as they have appeared). For example:
string - "Aaaa Bbbbbbb B CD home Aaa BB A poke"
Sorted string - "Aaaa Aaa home poke A Bbbbbbb B CD BB"
I know how to write the first part, but for the sort part I have no idea. Can someone help me with that please?
EDIT: Currently I have this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#pragma warning (disable: 4996)
int main(){
char string1[20], string2[100] = { '\0' };
int N, i;
do{
printf("Enter the number of words you want to enter in the string: ");
scanf("%d", &N);
if (N < 2){
printf("You must enter at least two words.\n");
printf("Enter the number of words you want to enter in the string: ");
scanf("%d", &N);
}
} while (N < 2);
for (i = 0; i < N; i++){
printf("Enter a word: ");
scanf(" %[^\n]", string1);
if (strlen(string2) == 0)
strcpy(string2, string1);
else {
strcat(string2, " ");
strcat(string2, string1);
}
}
printf("%s\n", string2);
return 0;
}
You will want to create an array of structs that hold a pointer to the word and then the number of vowels in each word. Something like:
struct vowelcnt {
char *word;
int numvowels;
}
Then sort the array of structs (descending order based on numvowels. Then simply loop through the sorted structs outputting the word which would give you the words sorted in order of the number of vowels contained. Hope that helps.

Print the last string name in C

I am trying to learn C and here i got a program in which we have to take the input from the user as n number os strings, compare it and arrange it in a alphabetical order. After arranging them in a alphabetical order , i have to only print the last name which was occurring in the order.
Here is the code for the above problem:
#include<stdio.h>
#include<string.h>
int main()
{
int i,j,m,n,len;
char a[50][50],temp[100];
char last ;
printf("Enter the number of elements you wish to order : ");
scanf("%d",&m);
printf("\nEnter the names :\n");
for (i=0;i<m;i++){
scanf("%s",a[i]);
}
for (i=0;i<m;i++){
for (j=i+1;j<m+1;j++) {
if (strcmp(a[i],a[j])>0) {
strcpy(temp,a[i]);
strcpy(a[i],a[j]);
strcpy(a[j],temp);
}
}
}
printf("\n\nSorted strings are : ");
for (i=0;i<m+1;i++){
printf("%s \n",a[i]);
}
return 0;
}
~
The Answer goes this way:
Enter the number of elements you wish to order : 4
Enter the names :
territory
states
hello
like
Sorted strings are : S$???
hello
like
states
territory
My question goes that why am i getting "S$???" and i want only the last word "territory should be printed out not all the names".
Can anyone let me know where am i going wrong? It will be a great help.
Thanks
Tanya
You are sorting m+1 strings with indexes [0..m]. But you input only m strings.
Your indexes should never go above m-1.
\Check this code
In your code you get input as 4
then
a[0]=territory
a[1]=states
a[2]=hello
a[3]=like
But your code runs upper loop at most 3 time then i=3
In next loop j=i+1 then j=4
but a[4]=not exists
Thats why "S$???" occurs
Solution:
#include<stdio.h>
#include<string.h>
int main() {
int i, j, m, n, len;
char a[50][50], temp[100];
char last;
printf("Enter the number of elements you wish to order : ");
scanf("%d", &m);
printf("\nEnter the names :\n");
for (i = 0; i < m; i++) {
scanf("%s", a[i]);
}
for (i = 0; i < m - 1; i++) { // m - 1 enough maximum i = 2;
for (j = i + 1; j < m; j++) { // j maximum j = i + 1 j = 3
if (strcmp(a[i], a[j]) > 0) {
strcpy(temp, a[i]);
strcpy(a[i], a[j]);
strcpy(a[j], temp);
}
}
}
printf("\n\nSorted strings are : "); // print all words in sorted order
for (i = 0; i < m; i++) {
printf("%s \n", a[i]);
}
printf("Last Word:\n");
printf("%s\n", a[m - 1]); // a[3] contains last name
return 0;
}
this was my program it worked for me in turbo c++
#include<conio.h>
#include<iosream.h>
#include<ctype.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
void main()
{
clrscr();
char name[100];
int c=0;
// to take the name including spaces
gets(name);
//this line is to print the first character of the name
cout<<name[0];
//this loop is to print the fist character which is there after every space
for(int l=0;name[l]!='\0';l++)
{
if(name[l]==' ')
{
cout<<"."<<name[l+1];
//l+1 is used because l is the space and l+1 is the character that we need
}
}
//this loop is to find out the last space in the entire sting
for(int i=0;name[i]!='\0';i++)
{
if(name[l+1]==NULL)
{
//here we fond the last space in the string
for(int j=i;name[j]!=' ';j--)
{
c=j+1;
}
// c=j+1 is used bacause we have already taken the first letter of the that word
//no need of taking it again
}
}
//this loop starts from the last space and the position(of space) is stored in k
for(int k=c;name[k]!='\0';k++)
{
cout<<name[k];
}
getch();
}
output:
anentt ranjan shukla
a.r.shukla

Resources