Word length frequency in C Program - c

I am trying to write a simple C program to output the length of words and output their frequencies. For example, if the user inputs "hey" my program would output Length of word: 3 Occurrences 1, and so on with a larger string inputted. I just cannot seem to loop it properly. I thought of setting both counters when a delimiter is seen to count both the length of the word at the time and its occurrence but I have not found a way for it to work. How can I fix my loop? My code is below. I'd appreciate any help. I should include my program only runs correctly for one word inputted but not a whole sentence or multiple sentences.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
const char delim[] = ", . - !*()&^%$##<> ? []{}\\ / \"";
const int n_delim = 31;
#define SIZE 1000
int is_delim(int c);
int main(){
char string[SIZE];
int wordlength = 0, wl[SIZE];
int word = 0, i;
printf("Enter your input string:");
fgets(string, SIZE, stdin);
string[strlen(string) - 1] = '\0';
printf("Word Length\tCount\n");
int seen = 0;
int l;
for (i = 0; i < strlen(string); i++){
if (is_delim(string[i])){
wl[word++] = wordlength;
l = wordlength;
seen++;
printf("%d\t\t%d\n", l, seen);
wordlength = 0;
}
wordlength++;
}
return 0;
}
int is_delim(int c){
register int i;
for (i = 0; i < n_delim; i++)
if (c == delim[i]) return 1;
return 0;
}

The trick is that wl[n] holds the count of words
of length n. Also, you don't need to keep calling strlen()
on every iteration, just check for the zero byte at the end.
The optimizer will do this for you, if you enable it.
The odd-looking for(;1;) is so that the loop counts
the final word, which is terminated by the zero byte.
memset(wl,0,sizeof(wl));
for(wordStart=maxLength=i=0;1;i++) {
if(is_delim(string[i]) || string[i]==0) {
int wordLength= i-wordStart;
if(wordLength>0)
wl[wordLength]++;
if(wordLength>maxLength)
maxLength= wordLength;
wordStart= i+1;
}
if(string[i]==0)
break;
}
for(i=1;i<=maxLength;i++) {
if(wl[i]>0) {
printf("%d words of length %d.\n",wl[i],i);
}
}

You really should use strtok for this. Right now, you never compare the last string with the current one so you can't tell them apart. You can use strcmp for this. Finally instead of manually testing the length of the string you should use strlen. Here is how your loop could look like
int seen = 0;
pch = strtok(string, delim);
last = pch;
while(pch != NULL) {
if(strcmp(last, pch) != 0) {
printf("%s:\t%d\t\t%d\n", last, (int)strlen(last), seen);
seen = 1;
}else {
seen++;
}
last = pch;
pch = strtok(NULL, delim);
}
printf("%s:\t%d\t\t%d\n", last, (int)strlen(last), seen);
Note, you should set the variable seen to 0 before the loop.

Related

find palindromes in the row and display them

A string consisting of words, no longer than 100 characters, is supplied. Words consist of Latin characters and are separated by a single space. It is necessary to output to the standard output stream a string containing only the words palindromes.
The source data must be read into memory as a whole and all manipulations must be carried out in memory, the result obtained in memory and then printed.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check(char str[])
{
int i, length;
length = strlen(str);
for (i = 0; i < length; i++)
if (str[i] != str[(length - 1) - i]) return 0;
return 1;
}
int main(void)
{
char str[100];
char* t;
gets(str);
t = strtok(str, " ");
while (t != NULL) {
if (check(t) == 1) {
printf("%s ", t);
}
t = strtok(NULL, " ");
}
_getch();
return 0;
}
this is my code (it fails the tests)
Please help me fix the code
Instead of fgets use function getline(&buffer, &size, stdion) for example.
Your for loop in the check function works fine but resolve another problem, than that you expected.
Palindrome a word or group of words that is the same when you read it forwards from the beginning or backwards from the end.

Why does strlen() not represent the actual length of my string?

basically I have a string composed of multiple words like this: "Hello world test".
Either if I try to print it with a structure like this
printf("%s", string);
or like this
for (int i = 0; i < strlen(string); ++i) {
printf("%c", string[i];
}
I always get this as an output: Hello world and I get a strlen of 11 instead of 16 too.
If I try to print out the same exact string with an int counter that previously counts the single chars in the string
for (int i = 0; i < counter; ++i) {
printf("%c", string[i];
}
I actually get the correct output Hello world test, which leads be to believe that the elements are correctly assigned in the string but for some reason %s and strlen just ignores the ones after the last space.
Why would that happen? What is going on? How can I fix this?
EDIT:
Actual code as requested:
#include <stdio.h>
#include <string.h>
typedef int BOOL;
#define TRUE 1
#define FALSE 0
int main() {
char sentence[64] = " ", reversal[64] = " ", reversal_copy[64] = " ";
int index = 0, counter = 0;
BOOL reset = TRUE, last_cycle = FALSE;
printf("Enter a sentence: ");
for (int i = 0; sentence[strlen(sentence) - 1] != '\n'; i++) {
scanf("%c", &sentence[i]);
}
/* Copies the input in a string reversing it */
for (int h = strlen(sentence) - 2, k = 0; h >= 0; h--, k++) {
reversal[k] = sentence[h];
}
/* Detects the first character of a word and the last character of the same word before a space,
switching the first char with the last, the second with the pre-last and so on*/
for (int i = 0; i < strlen(reversal); i++) {
if (reset == TRUE) {
index = i;
reset = FALSE;
}
if (i == strlen(reversal) - 1) {
last_cycle = TRUE;
counter++;
}
if (reversal[i] != ' ') {
counter++;
if (last_cycle == TRUE) {
goto reversing;
}
}
else {
reversing:
for (int h = index, z = counter; h < counter; h++, z--) {
reversal_copy[h] = reversal[z - 1];
reversal_copy[z - 1] = reversal[h];
}
if (last_cycle == FALSE) {
reversal_copy[i] = ' ';
}
reset = TRUE;
counter++;
}
}
printf("%lu ", strlen(reversal_copy));
for (int i = 0; i < counter; i++) {
printf("%c", reversal_copy[i]);
}
printf("%s\n\n", reversal_copy);
return 0;
}
if strlen() returns 11 then you have a \0 char after the world "world".
strlen and printf both determine "what is a string" by using the 0 terminator, so no surprise that they behave the same.
While this is difficult to answer without a Minimal, Complete, and Verifiable example, I will explain the most likely reason for the behavior you're observing.
Both printf with the %s format specifier and strlen give you the length of the null-terminated string pointed to by the relevant argument. If they are printing/reporting a length of 11, but iterating through the entire char array with a hard-coded value of 16 gives you the output "hello world test", then the character after world is clearly the null character, '\0'.
Try running your program with the input "A" as an example - see that even a single word exhibits the problem.
Something is going wrong when you reverse the last word. You are putting the trailing '\0' in front of it. It probably has to do with the special casing and the goto around the last_cycle logic, which is very hard to follow.
I think it's probably related to the fact that you have two counter++s in that code path.
Consider using some functions to make the code cleaner:
len = strlen(reversal);
for (start=0; start<len; start++) {
end = find_space_or_null(reversal, start);
if (end > start) {
reverse_chars(reversal, start, end-1);
start = end;
}
}
the program takes a string inputted by the user like "the sky is blue" and prints out "blue is sky the"
That's a perfect job for strtok():
#include <stddef.h>
#include <stdio.h>
#include <string.h>
enum { MAX_LINE = 120 };
int main()
{
char buffer[MAX_LINE];
fgets(buffer, MAX_LINE, stdin);
size_t length = strlen(buffer);
if (length && buffer[length - 1] == '\n') // get rid of the newline
buffer[--length] = '\0';
char *tokens[MAX_LINE] = { 0 }; // there can't be more than 60 tokens, but hey
if ((tokens[0] = strtok(buffer, " ")) == NULL) // no tokens? nothing to do.
return 0;
size_t i = 1;
for (; tokens[i - 1] && i < sizeof(tokens); ++i)
tokens[i] = strtok(NULL, " "); // tokenize the buffer
--i; // the very last was NULL anyway.
while (--i) // print it reverse
printf("%s ", tokens[i]);
puts(buffer);
}
Sample Output:
The quick brown fox jumps over the lazy dog
dog lazy the over jumps fox brown quick The

Program to find the longest word in a string

I wrote a program to find the longest word in a string and print the number of letters in the longest word. But the code is not printing. I analyzed the program many times but I could not find the solution.
#include <stdio.h>
#include <string.h>
int main() {
char string[100] = "Hello Kurnool";
int i = 0, letters = 0, longest = 0;
start:
for (; string[i] !=' '; i++) {
letters++;
}
if (letters >= longest)
longest = letters;
if (string[i] == ' ') {
letters = 0;
i++;
goto start;
}
printf("%d", longest);
return 0;
}
Using goto is highly discouraged. You should convert your code to use a loop.
The main problem in your code is you do not stop the scan when you reach the end of the string.
Here is a modified version:
#include <stdio.h>
int main() {
char string[100] = "Hello Kurnool";
int i, letters, longest = 0, longest_pos = 0;
for (i = 0; string[i] != '\0'; i++) {
for (letters = 0; string[i] != '\0' && string[i] != ' '; i++) {
letters++;
}
if (letters > longest) {
longest = letters;
longest_pos = i - longest;
}
}
printf("longest word: %d letters, '%.*s'\n",
longest, longest, string + longest_pos);
return 0;
}
Note that the implementation can be simplified into a single loop:
#include <stdio.h>
int main() {
char string[100] = "Hello Kurnool";
int i, start = 0, longest = 0, longest_pos = 0;
for (i = 0; string[i] != '\0'; i++) {
if (string[i] == ' ') {
start = i + 1;
} else {
if (i - start > longest) {
longest = i - start;
longest_pos = start;
}
}
}
printf("longest word: %d letters, '%.*s'\n",
longest, longest, string + longest_pos);
return 0;
}
Below is my approach. You should use C's string manipulation functions. This is the correct way to deal with strings in C.
In the code below, first I acquire the required bytes to store the input string in heap. Then I use strtok to split the string into tokens based on a delemeter and get the length of each sub string. Finally I free the space that I have allocated with malloc.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define phrase "Hello Kurnool"
int main()
{
char* string = malloc(strlen(phrase)+1);
strcpy(string,phrase);
int longest=0;
char *token;
char delimeter[2] = " ";
/* get the first token */
token = strtok(string, delimeter);
/* walk through other tokens */
while( token != NULL ) {
printf( " %s\n", token );
if(longest < strlen(token)){
longest = strlen(token);
}
token = strtok(NULL, delimeter);
}
printf("%d",longest);
free(string);
return 0;
}
People say - dont use goto but there is nothing inherently wrong with goto. Only thing is if goto is not used judiciously, it makes code more difficult to understand and maintain. For example, the way you have used it in your program ( instead of goto, a loop is perfect fit in such cases). Check this:
To use goto or not?
What is wrong with using goto?
Coming to your code, the for loop condition does not have check for terminating null character
for (; string[i] !=' '; i++) {
Hence it will not stop at the end of string.
To find the number of letters in longest word of string, you can do:
#include <stdio.h>
#include <string.h>
int main() {
char string[100] = "Hello Kurnool";
int i, letters = 0, longest = 0;
for (i = 0; string[i] != '\0'; i++) {
if (string[i] != ' ') {
letters++;
if (letters > longest) {
longest = letters;
}
} else {
letters = 0;
}
}
printf("longest : %d\n", longest);
return 0;
}
First of all,Please avoid using Goto, it is not a good practice.
Secondly, your loop will run infinite times when it iterates the second time because:
for(;string[i]!=' ';i++) // Here String[i] will never be equal to ' ' As there is no white space after your last word.
You can never expect what might be going wrong with your program if you are using
goto statement
which is never advisable to use rather it's bad programming if you use it. Secondly it looks like you are stuck in an infinite loop so her is a solution to your problem:
#include<stdio.h>
#include<string.h>
void main()
{
char s[1000];
scanf("%s",s);
int i=0;
int letters;
int longest=0;
while(s[i]!=NULL)
{
if(s[i]==' ')
{
if(longest>=letters)
{longest=letters;}
letters=0;
}
else
{letters++;}
}
printf("%d\n",longest);
}
So, what I have done is assuming a string s which is the input given by the user. You itterate through s till the last input given by the user after which it encounters a NULL character. Now you are searching for the length of the longest word, so you create a variable letters for counting the no. of letters in each word of the string. And if the string s encounters a space indicating the end of a word, then you check if the variable longest is greater than or less than the word count. And again you initialize letters to 0, so that it can start counting the next word from 0 again.So, by this method at the end i.e. after the while loop terminates we get our required output which is stored in the variable longest.
So, I guess this will print the no. of letters in the longest word.

Program that checks if an array is a palindrome

I'm trying to create a program that checks if a given array/string is a palindrome or not and its not working. The program just prints "0" on every given array, even on palindromes.
int main()
{
char string[100]= {0};
char stringReverse[100]= {0};
int temp = 0;
int firstLetter = 0;
int lastLetter = 0;
printf("Please enter a word or a sentence: ");
fgets(string, 100, stdin);
strcpy(stringReverse , string); // This function copies the scanned array to a new array called "stringReverse"
firstLetter = 0;
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
// This while reverses the array and insert it to a new array called "stringReverse"
while(firstLetter < lastLetter)
{
temp = stringReverse[firstLetter];
stringReverse[firstLetter] = stringReverse[lastLetter];
stringReverse[lastLetter] = temp;
firstLetter++;
lastLetter--;
}
printf("%s %s", stringReverse, string);
if ( strcmp(stringReverse , string) == 0)
{
printf("1");
}
else
{
printf("0");
}
}
Lets say we implement a simple fun to do that
int check_palindrome (const char *s) {
int i,j;
for (i=0,j=strlen(s)-1 ; i<j ; ++i, --j) {
if (s[i] != s[j]) return 0; // Not palindrome
}
return 1; //Palindrome
}
I think this is far more simpler ;)
For the code posted in question:
Be aware of fgets(). It stops in the first '\n' or EOF and keeps the '\n' character.
So if you give radar for ex, the result string will be "radar\n", which doesn't match with "\nradar"
The Problem:
Let's say you enter the string RACECAR as input for your program and press enter, this puts a newline character or a '\n' in your buffer stream and this is also read as part of your string by fgets, and so your program effectively ends up checking if RACECAR\n is a palindrome, which it is not.
The Solution:
After you initialize lastLetter to strlen(string) - 1 check if the last character in your string (or the character at the lastLetter index is the newline character (\n) and if so, decrease lastLetter by one so that your program checks if the rest of your string (RACECAR) is a palindrome.
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
// Add these 2 lines to your code
// Checks if the last character of the string read by fgets is newline
if (string[lastLetter] == '\n')
lastLetter--;
fgets adds a '\n' at the end.
So if the user entered "aba", string contains "aba\n".
reverseString contains "\naba".
So it doesn't match.
After the fgets, add this code
int l = strlen(string) - 1;
string[l] = 0;
This will strip out the '\n' at the end before copying it to reverseString.
That aside, you can do this whole program inplace without the need of a second buffer or strcpy or strlen calls.
You have several issues in your code:
first you forgot the last closing brace };
then you forgot to remove the trailing \n (or maybe also \r under Windows) in string;
you don't need to revert the string into a new string; a one-pass check is enough:
Here is a working code:
#include <stdio.h>
#include <string.h>
int main()
{
char string[100]= {0};
int temp = 0;
int firstLetter = 0;
int lastLetter = 0;
printf("Please enter a word or a sentence: ");
fgets(string, 100, stdin);
firstLetter = 0;
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
while ((string[lastLetter]=='\n')||(string[lastLetter]=='\r')) {
lastLetter--;
}
// This while reverses the array and insert it to a new array called "stringReverse"
temp = 1;
while(firstLetter < lastLetter)
{
if (string[firstLetter] != string[lastLetter]) {
temp = 0;
break;
}
firstLetter++;
lastLetter--;
}
if ( temp )
{
printf("1");
}
else
{
printf("0");
}
}
You can do it by this simpleway also.
#include <stdio.h>
#include <string.h>
int main()
{
char string[10], revString[10];
printf("Enter string for reversing it...\n");
scanf("%s", string);
int stringLength = strlen(string);
for(int i = 0; string[i] != '\0'; i++, stringLength--)
{
revString[i] = string[stringLength - 1];
}
if(strcmp(string, revString) == 0)
printf("Given string is pelindrom\n");
else
printf("Given string is not pelindrom\n");
}
#include<stdio.h>
#include<string.h>`enter code here`
void fun(char *a);
int main ()
{
char p[100];
char *s=p;
printf("enter the string");
scanf("%[^\n]",s);
fun(s);
}
void fun(char *a)
{
if(*a && *a!='\n')
{
fun(a+1);
putchar(*a);
}
}
// use this approach better time complexity and easier work hope this helps

C Programming: Counting word length occurences in a string

How would you be able to count word lengths and output their occurrences from a string using gets() or fgets()? For example, here is code doing so but using getchar()below. I think writing it in gets() would make it easier to incorporate all of the delimiters in the program rather than having to manually set if statements for each one of those would it not?
#include <string.h>
#include <ctype.h>
const char delim[] = ", . - !*()&^%$##<> ? []{}\\ / \"";
#define SIZE 100
int main(void){
int length[SIZE] = { 0 };
int name[SIZE];
int i = 0, ch, word_len = 0;
int count = 0;
printf("enter sentence: ");
while (1){
ch = getchar();
if (isalpha(ch)){
++word_len;
}
else if (ch == ' ' || ch == '.'){
if (word_len)
length[word_len - 1]++;//-1: to 0 origin
if (ch == '.')
break;
word_len = 0;
}
}
printf("Word Length \tCount \n");
for (i = 0; i<sizeof(length) / sizeof(*length); ++i){
if (length[i])
printf(" %d \t\t%d\n", i + 1, length[i]);
}
return 0;
}
You can build your custom delimiter detection function.
// globals
const char *delim = " .,;:!?\n\0";
const int n_delim = 9;
int is_delim(int c)
{
register int i;
for (i = 0; i < n_delim; i++)
if (c == delim[i]) return 1;
return 0;
}
This function will return 1 every time it can match c with delim. So you can use it like this:
fgets(buffer, 200, stdin);
for (i = 0; i < strlen(buffer); i++) {
if (is_delim(buffer[i])) {
wl[words++] = length;
length = 0;
continue;
}
length++;
}
I'm assuming you're familiar with the fgets function.
You basically will loop through your buffer, making comparisons with each character. Every loop iteration you check if the current character is a word delimiter, if it is, you save the current length and set length=0 for a new word, and at every iteration you increment the length.
You'll need to come up with a way of either not inserting the zero length values due to double delimiters or just ignore them when you're printing the results.
Basically you want to split a string into words, based on some delimiters, and compute their length. The C standard library provides the strtok function, which does exactly what you need: it splits the given string into multiple tokens.

Resources