C: outputs the total number of times the first word occurs - c

when I enter a sentence, this code should get the first word and count the how many times repeated.
firstWord(): This function gets the string as a parameter. Then, outputs the total number of times the first word occurs.
(this code consisting of 4 functions and in this func(firstWord()) I should use 'string' as a parameter, in main function I just call the firstWord func. )
number of times the first word occurs.
for ex: sentence is no changes and no suprises
first word no repeated 2 times.
here is the code.
void firstWord(char st3[]){
char firstw[20];
char *ptr;
int i=0;
int count=0;
ptr=strstr(st3,firstw);
while (ptr = '\0')
{
count++;
ptr++;
ptr = strstr(ptr, firstw);
}
printf("First word %s is repeated %d times\n", firstw, count);
}

The function does not make a sense.
You are using the uninitialized array firstw in a call of strtsr as for example
char firstw[20];
//..
ptr=strstr(st3,firstw);
that invokes undefined behavior.
Also there is a typo in the condition of the while statement
while (ptr = '\0')
Instead of using the equality operator == you are using the assignment operator = after which the pointer ptr becomes a null pointer.
At first you need to find the first word in the source string and then count how many times it is present in the source string.
Pay attention to that the function strstr can find a substring that does not form a word that is that is not delimited by white space characters.
Also at least the parameter of the function firstWord should be declared with the qualifier const because the source string is not changed within the function. And the return type of the function should not be void. The function should return the counter and the position and the length pf the first word in the source string as for example by using an object of a structure type.
The function can be implemented for example the following way as shown in the demonstration program below.
#include <stdio.h>
#include <string.h>
struct Word
{
char *pos;
size_t length;
size_t counter;
};
struct Word firstWord( const char *s )
{
const char *delim = " \t\n";
struct Word word = { .pos = NULL, .length = 0, .counter = 0 };
while ( *s )
{
s += strspn( s, delim );
if ( *s )
{
size_t n = strcspn( s, delim );
if ( word.pos == NULL )
{
word.pos = ( char * )s;
word.length = n;
word.counter = 1;
}
else
{
if ( n == word.length && strncmp( word.pos, s, n ) == 0 )
{
++word.counter;
}
}
s += n;
}
}
return word;
}
int main( void )
{
const char *s = " A AB A ABC A";
struct Word word = firstWord( s );
if ( word.pos != NULL )
{
printf( "The first word \"%.*s\" is found %zu time(s)\n",
word.length, word.pos, word.counter );
}
}
The program output is
The first word "A" is found 3 time(s)
Using that function you can for example sort an array of strings in the lexicographical order of first words and if the words are equal in the ascending order of their counters in strings.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Word
{
char *pos;
size_t length;
size_t counter;
};
struct Word firstWord( const char *s )
{
const char *delim = " \t\n";
struct Word word = { .pos = NULL, .length = 0, .counter = 0 };
while ( *s )
{
s += strspn( s, delim );
if ( *s )
{
size_t n = strcspn( s, delim );
if ( word.pos == NULL )
{
word.pos = ( char * )s;
word.length = n;
word.counter = 1;
}
else
{
if ( n == word.length && strncmp( word.pos, s, n ) == 0 )
{
++word.counter;
}
}
s += n;
}
}
return word;
}
int cmp( const void *a, const void *b )
{
const char *s1 = *( const char * const * )a;
const char *s2 = *( const char * const * )b;
struct Word word1 = firstWord( s1 );
struct Word word2 = firstWord( s2 );
size_t n = word1.length;
if ( word2.length < n ) n = word2.length;
int result = strncmp( word1.pos, word2.pos, n );
if ( result == 0 )
{
result = ( word2.length < word1.length ) - ( word1.length < word2.length );
if ( result == 0 )
{
result = ( word2.counter < word1.counter ) - ( word1.counter < word2.counter );
}
}
return result;
}
int main( void )
{
const char * s[] =
{
"CCC CCC CCC",
"CCC CCC",
"BB BB",
"A A",
"CC",
"BB",
"CCC",
"A"
};
const size_t N = sizeof( s ) / sizeof( *s );
for ( size_t i = 0; i < N; i++ )
{
puts( s[i]);
}
putchar( '\n' );
qsort( s, N, sizeof( const char * ), cmp );
for ( size_t i = 0; i < N; i++ )
{
puts( s[i]);
}
putchar( '\n' );
}
The program output is
CCC CCC CCC
CCC CCC
BB BB
A A
CC
BB
CCC
A
A
A A
BB
BB BB
CC
CCC
CCC CCC
CCC CCC CCC
If you need to write a function that just determines the first word in a string then it can look the following way as shown in the demonstration program below.
#include <stdio.h>
#include <string.h>
struct Word
{
char *pos;
size_t length;
};
struct Word firstWord( const char *s, const char *delim )
{
struct Word word = { .pos = NULL, .length = 0 };
while ( *s && word.pos == NULL )
{
s += strspn( s, delim );
if ( *s )
{
size_t n = strcspn( s, delim );
word.pos = ( char * )s;
word.length = n;
s += n;
}
}
if ( word.pos == NULL )
{
word.pos = ( char * )s;
}
return word;
}
int main( void )
{
const char *s = " A AB BA A";
struct Word word = firstWord( s, " \t\n" );
char first_word[word.length + 1];
strncpy( first_word, word.pos, word.length );
first_word[word.length] = '\0';
printf( "The first word is \"%s\" at position %zu\n",
first_word, word.pos - s );
}
The program output is
The first word is "A" at position 3

You don't consider that "cat can catch mice" should report only 1 occurrence of "cat".
Try this (or something like it):
void firstWord( char st3[] ) {
char *firstw = "EMPTY STRING";
int count = 0;
for( char *ptr = st3; ( ptr = strtok( ptr, " .,-" ) ) != NULL; ptr = NULL )
if( count == 0 ) {
firstw = ptr;
count++;
} else if( strcmp( ptr, firstw ) == 0 )
count++;
printf( "First word %s is repeated %d times\n", firstw, count );
}
Update
With the feedback "didn't work", I've added a few printf's to show that it does work...
void firstWord( char st3[] ) {
char *firstw = "EMPTY STRING";
int count = 0;
printf( "Using: '%s'\n", st3 );
for( char *ptr = st3; ( ptr = strtok( ptr, " .,-" ) ) != NULL; ptr = NULL )
if( count == 0 ) {
firstw = ptr;
count++;
} else if( strcmp( ptr, firstw ) == 0 )
count++;
printf( "First word %s occurs %d times\n\n", firstw, count );
free( st3 );
}
void my_main(void) {
firstWord( strdup( "cat can catch mice" ) );
firstWord( strdup( "cat cat catch cat" ) );
firstWord( strdup( " cat cat catch cat" ) );
firstWord( strdup( "dog dog dog dog dog" ) );
firstWord( strdup( "" ) );
}
Output:
Using: 'cat can catch mice'
First word cat occurs 1 times
Using: 'cat cat catch cat'
First word cat occurs 3 times
Using: ' cat cat catch cat'
First word cat occurs 3 times
Using: 'dog dog dog dog dog'
First word dog occurs 5 times
Using: ''
First word EMPTY STRING occurs 0 times

Related

How to compare a string with a substring to transform the equal parts between the first and second into '*' without using <string.h>

I have to request a first word to compare it to a second word, and replace all occurrences with '*' working character by character without using the <string.h> library.
Exercise:
Write a C program that receives two words entered from the keyboard as input. Consider that each word can contain a maximum of 30 characters. The program must be case sensitive, ie it must distinguish lowercase letters from uppercase letters and must also be able to analyze numbers, symbols and punctuation marks. The program must replace each occurrence of the second word in the first word with the '*' character. For example, enter the words
abchdfffchdchdtlchd
and
chd
the program should display the word
ab*fff**tl*
#include <stdio.h>
#include <stdlib.h>
#define MAX 30
int main()
{
char string1 [MAX+1], string2 [MAX+1],replace = '*';
int nChar1 = 0, nChar2 = 0, flag = 0, h=0;
printf ("Enter a word (max 30 characters): ");
scanf ("%[^\n ]", &string1);
fflush (stdin);
printf ("\nYou wrote this word: %s\n", string1);
for (int i=0; i<(MAX+1); i++)
{
if (string1[i] == '\0')
break;
else
nChar1++;
}
printf ("The characters are: %d\n", nChar1);
printf ("\nEnter a word you want to change with '*' in the first string: ");
scanf ("%[^\n ]", &string2);
fflush (stdin);
printf ("\nYou wrote this word: %s\n", string2);
for (int j=0; j<(MAX+1); j++)
{
if (string2[j] == '\0')
break;
else
nChar2++;
}
printf ("The characters are: %d\n", nChar2);
for (int i=0, j=0, z=0; i<nChar1, j<nChar2; i++, j++)
{
if (string1[i] == string2[j])
{
for (int k=0; k<nChar2; k++)
{
if (string1[i+k] == string2[j+k])
flag++;
else
flag=0;
}
}
j=0;
if (flag == nChar2)
{
string1[h] = replace;
h++;
}
else
{
h++;
}
string1[z+1] = string1[h];
}
printf("\n%s", string1);
return 0;
}
Decompose the task into several separate functions.
One function will calculate the length of the passed string.
Another function will find a substring in a string.
And the third function will do the replacement of the target substring with a character.
Here is a demonstrative program.
#include <stdio.h>
size_t length( const char *s )
{
size_t n = 0;
while ( *s++ ) ++n;
return n;
}
char * find_substring( const char *s1, const char *s2 )
{
size_t n1 = length( s1 );
size_t n2 = length( s2 );
const char *target = NULL;
if ( ( *s2 != '\0' ) && !( n1 < n2 ) )
{
for ( size_t i = 0, n = n1 - n2 + 1; !target && i < n; i++ )
{
if ( s1[i] == s2[0] )
{
size_t j = 1;
while ( j != n2 && s1[i+j] == s2[j] ) ++j;
if ( j == n2 ) target = s1 + i;
}
}
}
return ( char * )target;
}
char * replace( char *s1, const char *s2, char c )
{
int done = 0;
size_t n2 = length( s2 );
for ( char *p = s1, *q = s1; !done; )
{
char *tmp = find_substring( q, s2 );
if ( tmp == NULL )
{
if ( p != q )
{
while ( ( *p++ = *q++ ) );
}
done = 1;
}
else
{
if ( p == q )
{
p = tmp;
}
else
{
while ( q != tmp ) *p++ = *q++;
}
*p++ = c;
q = tmp + n2;
}
}
return s1;
}
int main(void)
{
{
char s1[] = "abc";
const char *s2 = "chd";
puts( replace( s1, s2, '*' ) );
}
{
char s1[] = "achd";
const char *s2 = "chd";
puts( replace( s1, s2, '*' ) );
}
{
char s1[] = "chda";
const char *s2 = "chd";
puts( replace( s1, s2, '*' ) );
}
{
char s1[] = "chd";
const char *s2 = "chd";
puts( replace( s1, s2, '*' ) );
}
{
char s1[] = "abchdfffchdchdtlchd";
const char *s2 = "chd";
puts( replace( s1, s2, '*' ) );
}
return 0;
}
The program output is
abc
a*
*a
*
ab*fff**tl*

How to Reverse a sentence word by word?

I was trying to reverse a sentence word by word. (how are you -> you are how) First of all I create a char sentence and reverse and temp. Sentence given by user to reverse. Temp catches the word to change the location in the sentence.Then I use strcat to concatenate each word. Here is the problem. I can find the word which is end of the sent(takes input) but when I'm trying to concatenate to reverse, it add this word to sentence and an error occurs. What's the problem?
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* subs(char* temp, char* src, int start, int end);
int main() {
char sent[15]; //input sentence
char rev[15]; // output sentence
char *temp=(char*)calloc(1,sizeof(char)); //for the word
scanf(" %[^\n]%*c", &sent); // takin' input
int i, end, start;
i = strlen(sent);
//find the beggining and ending of the indexes of the word in sentence
while (i > 0) {
while (sent[i] == ' ') {
i--;
}
end = i-1;
while (sent[i] != ' ') {
i--;
}
start = i + 1;
//add the word to temp and concatenate to reverse
temp=subs(temp, sent, start, end);
strncat(rev, temp,end-start+3);
}
rev[strlen(sent)] = '\0';
printf("%s", rev);
return 0;
}
char* subs(char* temp, char* src, int start, int end) {
int i = 0, control;
// resize the temp for the wırd
temp = (char*)realloc(temp,end-start+3);
for (; i < (end - start) + 1; i++) {
control = (start + i);
temp[i] = src[control];
}
//adding blank and null character to end of the word.
temp[i] = ' ';
temp[++i] = '\0';
return temp;
}
I will just copy my good answer from this question that was not yet closed Reverse a string without strtok in C
. So I can not use this reference to close your question as a duplicate.
A standard approach is to reverse each word within a string and then to reverse the whole string.
The standard C function strtok is not appropriate in this case. Instead use the standard C functions strspn and strcspn.
Here you are.
#include <stdio.h>
#include <string.h>
static char * reverse( char *s, size_t n )
{
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[ i ];
s[ i ] = s[ n - i - 1 ];
s[ n - i - 1 ] = c;
}
return s;
}
char * reverse_by_words( char *s )
{
const char *delim = " \t";
char *p = s;
while ( *p )
{
p += strspn( p, delim );
if ( *p )
{
char *q = p;
p += strcspn( p, delim );
reverse( q, p - q );
}
}
return reverse( s, p - s );
}
int main(void)
{
char s[] = "5 60 +";
puts( s );
puts( reverse_by_words( s ) );
return 0;
}
The program output is
5 60 +
+ 60 5
If you want to keep leading and trailing spaces as they were in the original string then the functions can look the following way
#include <stdio.h>
#include <string.h>
static char *reverse( char *s, size_t n )
{
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n - i -1 ];
s[n - i - 1] = c;
}
return s;
}
char * reverse_by_words( char *s )
{
const char *delim = " \t";
char *first = s, *last = s;
for ( char *p = s; *p; )
{
p += strspn( p, delim );
if ( last == s ) first = last = p;
if ( *p )
{
char *q = p;
p += strcspn( p, delim );
last = p;
reverse( q, p - q );
}
}
reverse( first, last - first );
return s;
}
int main(void)
{
char s[] = "\t\t\t5 60 +";
printf( "\"%s\"\n", s );
printf( "\"%s\"\n", reverse_by_words( s ) );
return 0;
}
The program output is
" 5 60 +"
" + 60 5"

Reverse a string without strtok in C

Working on a program that uses RPN (Reverse Polish Notation).
I have a function that reverses all the words of string without using strtok or triggering printf (unlike all the solutions found online and here).
The function actually works partially as it prints all the words of a given string except the last one and I need help figuring out what's going on.
char *extract(char s[]) {
if (s[0] == '\0')
return NULL;
int i = 0;
char *p = NULL;
while (s[i] != '\0') {
if (s[i] == ' ')
p = s + i;
i++;
}
if (p != NULL) {
*p = '\0';
return p + 1;
}
}
And then it's called in main like this:
char s[MAX] = "5 60 +";
while(s != NULL){
printf("%s\n", extract(s));
}
The output is + 60 with the cursor endessly waiting for something
but the expected output should be + 60 5
A standard approach is to reverse each word within a string and then to reverse the whole string.
Here you are.
#include <stdio.h>
#include <string.h>
static char * reverse( char *s, size_t n )
{
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[ i ];
s[ i ] = s[ n - i - 1 ];
s[ n - i - 1 ] = c;
}
return s;
}
char * reverse_by_words( char *s )
{
const char *delim = " \t";
char *p = s;
while ( *p )
{
p += strspn( p, delim );
if ( *p )
{
char *q = p;
p += strcspn( p, delim );
reverse( q, p - q );
}
}
return reverse( s, p - s );
}
int main(void)
{
char s[] = "5 60 +";
puts( s );
puts( reverse_by_words( s ) );
return 0;
}
The program output is
5 60 +
+ 60 5
If you want to keep leading and trailing spaces as they were in the original string then the functions can look the following way
#include <stdio.h>
#include <string.h>
static char *reverse( char *s, size_t n )
{
for ( size_t i = 0; i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n - i -1 ];
s[n - i - 1] = c;
}
return s;
}
char * reverse_by_words( char *s )
{
const char *delim = " \t";
char *first = s, *last = s;
for ( char *p = s; *p; )
{
p += strspn( p, delim );
if ( last == s ) first = last = p;
if ( *p )
{
char *q = p;
p += strcspn( p, delim );
last = p;
reverse( q, p - q );
}
}
reverse( first, last - first );
return s;
}
int main(void)
{
char s[] = "\t\t\t5 60 +";
printf( "\"%s\"\n", s );
printf( "\"%s\"\n", reverse_by_words( s ) );
return 0;
}
The program output is
" 5 60 +"
" + 60 5"

how to compare two 2 d string without using strcmp

I have data file in which some data is kept.
example: welcome user HII if while
I have made 2D character array to store all the keywords in c.
now I want two know if the data file contain the keyword or not.
enter code here
for(i=0;i<32;i++)
for(j=0;j<no_of_words_in_file;j++)
if(k[i]==t[j])
printf("%s is keyword",t[j]);
here the k[i] represents the 2D character array where all the keywords in c are stored and t[i] represents the 2D character array where all the words of file are stored.
I want to compare these 2D arrays without using strcmp.
To compare two strings without using standard C functions you can use a loop like that
#include <stdio.h>
int main(void)
{
char key[] = "while";
char word1[] = "while";
char word2[] = "when";
size_t i = 0;
while ( key[i] != '\0' && key[i] == word1[i] ) ++i;
int equal = key[i] == word1[i];
printf( "key == word1: = %d\n", equal );
i = 0;
while ( key[i] != '\0' && key[i] == word2[i] ) ++i;
equal = key[i] == word2[i];
printf( "key == word2: = %d\n", equal );
return 0;
}
The program output is
key == word1: = 1
key == word2: = 0
Or you can write a separate function. For example
#include <stdio.h>
int equal( const char *s1, const char *s2 )
{
while ( *s1 != '\0' && *s1 == *s2 )
{
++s1; ++s2;
}
return *s1 == *s2;
}
int main(void)
{
enum { N = 10 };
char key[][N] ={ "if", "while" };
const size_t N1 = sizeof( key ) / sizeof( *key );
char words[][N] = { "welcome", "user", "HII", "if", "while" };
const size_t N2 = sizeof( words ) / sizeof( *words );
for ( size_t i = 0; i < N2; i++ )
{
for ( size_t j = 0; j < N1; j++ )
{
if ( equal( key[j], words[i] ) )
{
printf( "\"%s\" == \"%s\"[%zu]\n", key[j], words[i], i );
}
}
}
return 0;
}
the program output is
"if" == "if"[3]
"while" == "while"[4]

How to bubble sort an array with unknown length in C

I need help to write a code that gets an array of unknown size and bubble sort it, every word between the spaces, ( only one space)
for example
bad dba = abd abd;
I wrote a code that gets a known size of strings,and I try to modify it and I can't think of anything.
Thanks in advance.!
my code so far is:
gets(strB);
do
{
flag = 0;
for
(q = 0; 'dont know what to put here'-J ; q++) {
if
(strB[q] > strB[q + 1])
{
// Swap
temp2 = strB[q];
strB[q] = strB[q + 1];
strB[q + 1] = temp2;
flag = 1;
}
}
j++;
} while
(flag != 0);
puts(strB);
We beginners should help each other.:)
If I have understood correctly you need to sort each word delimited by white spaces within a string.
You should write two functions. The first function splits a string into substrings and call a bubble sort function for each substring. The second function is a bubble sort function.
It can be done the following way
#include <stdio.h>
#include <ctype.h>
void bubble_sort( char *first, char *last )
{
for ( size_t n = last - first, sorted = n; !( n < 2 ); n = sorted )
{
for ( size_t i = sorted = 1; i < n; i++ )
{
if ( first[i] < first[i-1] )
{
char c = first[i];
first[i] = first[i-1];
first[i-1] = c;
sorted = i;
}
}
}
}
char * sort( char *s )
{
for ( char *p = s; *p; )
{
while ( isspace( ( unsigned char )*p ) ) ++p;
if ( *p )
{
char *q = p;
while ( *p && !isspace( ( unsigned char )*p ) ) ++p;
bubble_sort( q, p );
}
}
return s;
}
int main(void)
{
char s[] = "bad dba";
puts( s );
puts( sort( s ) );
return 0;
}
The program output is
bad dba
abd abd
Take into account that the function gets is an unsafe function and is not supported any more by the C Standard. Instead use the C standard function fgets.
To remove the appended new line character by the function fgets use the following trick
#include <string.h>
//...
fgets( s, sizeof( s ), stdin );
s[ strcspn( s, "\n" ) ] = '\0';
//...

Resources