I want to know how to count how many words are in a string.
I use strstr to compare and it works but only works for one time
like this
char buff = "This is a real-life, or this is just fantasy";
char op = "is";
if (strstr(buff,op)){
count++;
}
printf("%d",count);
and the output is 1 but there are two "is" in the sentence, please tell me.
For starters you have to write the declarations at least like
char buff[] = "This is a real-life, or this is just fantasy";
const char *op = "is";
Also if you need to count words you have to check whether words are separated by white spaces.
You can do the task the following way
#include <string.h>
#include <stdio.h>
#include <ctype.h>
//...
size_t n = strlen( op );
for ( const char *p = buff; ( p = strstr( p, op ) ) != NULL; p += n )
{
if ( p == buff || isblank( ( unsigned char )p[-1] ) )
{
if ( p[n] == '\0' || isblank( ( unsigned char )p[n] ) )
{
count++;
}
}
}
printf("%d",count);
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
char buff[] = "This is a real-life, or this is just fantasy";
const char *op = "is";
size_t n = strlen( op );
size_t count = 0;
for ( const char *p = buff; ( p = strstr( p, op ) ) != NULL; p += n )
{
if ( p == buff || isblank( ( unsigned char )p[-1] ) )
{
if ( p[n] == '\0' || isblank( ( unsigned char )p[n] ) )
{
count++;
}
}
}
printf( "The word \"%s\" is encountered %zu time(s).\n", op, count );
return 0;
}
The program output is
The word "is" is encountered 2 time(s).
Parse the string, in a loop.
As OP has "but there are two "is" in the sentence", it is not enough just to look for "is" as that occurs 4x, twice in "This". Code needs to parse the string for the idea of a "word".
Case sensitively is also a concern.
char buff = "This is a real-life, or this is just fantasy";
char op = "is";
char *p = buff;
char *candidate;
while ((candidate = strstr(p, op)) {
// Add code to test if candidate is a stand-alone word
// Test if candidate is beginning of buff or prior character is a white-space.
// Test if candidate is end of buff or next character is a white-space/punctuation.
p += strlen(op); // advance
}
For me, I would not use strstr(), but look for "words" with isalpha().
// Concept code
size_t n = strlen(op);
while (*p) {
if (isalpha(*p)) { // Start of word
// some limited case insensitive compare
if (strnicmp(p, op, n) == 0 && !isalpha(p[n]) {
count++;
}
while (isalpha(*p)) p++; // Find end of word
} else {
p++;
}
}
Related
The problem with this function is that it looks after all the substrings, but not for words like for example if I'm looking for "hi" within "hifive to to evereyone" it returns 1
int HowManyString(char *satz,char *word) {
int coun = 0;
while (strlen(word)<strlen(satz)) {
if (strstr(satz,word)==NULL) {
return coun;
} else {
satz=strstr(satz,word)+strlen(word);
if(*(satz)==' '||*(satz)=='\0'){
coun++;
} else {
return coun;
}
}
}
return coun;
}
Using your approach with the standard function strstr your function can look the following way as shown in the demonstration program below
#include <stdio.h>
#include <string.h>
#include <ctype.h>
size_t HowManyString( const char *s1, const char *s2 )
{
size_t count = 0;
size_t n = strlen( s2 );
for ( const char *p = s1; ( p = strstr( p, s2 ) ) != NULL; p += n )
{
if ( ( p == s1 || isblank( ( unsigned char )p[-1] ) ) &&
( p[n] == '\0' || isblank( ( unsigned char )p[n] ) ) )
{
++count;
}
}
return count;
}
int main( void )
{
const char *s1 = "hifive";
const char *s2 = "hi";
printf( "%zu\n", HowManyString( s1, s2 ) );
s1 = "fivehi";
printf( "%zu\n", HowManyString( s1, s2 ) );
s1 = "hi five";
printf( "%zu\n", HowManyString( s1, s2 ) );
s1 = "five hi";
printf( "%zu\n", HowManyString( s1, s2 ) );
}
The program output is
0
0
1
1
If the source string can contain the new line character '\n' when within the function use isspace instead of isblank.
Here is a function that achieves what you are looking for:
int count_words(const char *sentence, const char *word)
{
int counter = 0;
for (const char *p = sentence; *p; ++p) {
// Skip whitespaces
if (isspace(*p))
continue;
// Attempt to find a match
const char *wp = word, *sp = p;
while (*wp != '\0' && *sp != '\0' && *wp == *sp) {
++wp;
++sp;
}
// Match found AND a space after AND a space before
if (*wp == '\0' && (isspace(*sp) || *sp == '\0') && (p == sentence || isspace(*(p-1)))) {
++counter;
p = sp - 1;
}
// End of sentence reached: no need to continue.
if (*sp == '\0')
return counter;
}
return counter;
}
Usage:
int main(void)
{
const char sentence[] = "I is Craig whoz not me, not him, not you!";
const char word[] = "not";
int occ = count_words(sentence, word);
printf("There are %d occurences.\n", occ);
}
Output:
There are 3 occurences.
I', learning C and I'm getting no output for some reason, probably I don't return as I should but how I should? (described the problem in the comments below :D)
Any help is appreciated!
#include <stdio.h>
#include <ctype.h>
#include <string.h>
char *makeUpperCase (char *string);
int main()
{
printf(makeUpperCase("hello")); //Here there is no output, and when I'm trying with the format %s it returns null
return 0;
}
char *makeUpperCase(char *string)
{
char str_out[strlen(string) + 1];
for (int i = 0; i < strlen(string); ++i)
str_out[i] = toupper(string[i]);
printf(str_out); //Here I get the output.
return str_out;
}
You declared within the function a local variable length array that will not be alive after exiting the function
char str_out[strlen(string) + 1];
So your program has undefined behavior.
If the function parameter declared without the qualifier const then it means that the function changes the passed string in place. Such a function can be defined the following way
char * makeUpperCase( char *string )
{
for ( char *p = string; *p != '\0'; ++p )
{
*p = toupper( ( unsigned char )*p );
}
return string;
}
Otherwise you need to allocate dynamically a new string. For example
char * makeUpperCase( const char *string )
{
char *str_out = malloc( strlen( string ) + 1 );
if ( str_out != NULL )
{
char *p = str_out;
for ( ; *string != '\0'; ++string )
{
*p++ = toupper( ( unsigned char )*string );
}
*p = '\0';
}
return str_out;
}
Here is a demonstration program.
#include <stdop.h>
#include <stdlib.h>
#include <string.h>
char *makeUpperCase( const char *string )
{
char *str_out = malloc( strlen( string ) + 1 );
if (str_out != NULL)
{
char *p = str_out;
for (; *string != '\0'; ++string)
{
*p++ = toupper( ( unsigned char )*string );
}
*p = '\0';
}
return str_out;
}
int main( void )
{
char *p = makeUpperCase( "hello" );
puts( p );
free( p );
}
The program output is
HELLO
The problem is that printf() is buffering output based on a bit complex mechanism. When you are outputting to a terminal, printf() just buffers everything until the buffer fills (which is not going to happen with just the string "hello", or until it receives a '\n' character (which you have not used in your statement)
So, to force a buffer flush, just add the following statement
fflush(stdout);
after your printf() call.
For example:
str = "I have a meeting"
word = "meet"
should give 0 since there is no such word
I tried strstr(str, word) but it checks for substring, so it gives 1 for this example
I assume that words are sequences of characters separated by blank characters.
You can use the function strstr but you need also to check that blanks precede and follow the found substring or that the returned pointer points to the beginning of the sentence or the found substring forms the tail of the sentence.
Here is a demonstration program that shows how such a function can be defined.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char * is_word_present( const char *sentence, const char *word )
{
const char *p = NULL;
size_t n = strlen( word );
if ( n != 0 )
{
p = sentence;
while ( ( p = strstr( p, word ) ) != NULL )
{
if ( ( p == sentence || isblank( ( unsigned char )p[-1] ) ) &&
( p[n] == '\0' || isblank( ( unsigned char )p[n] ) ) )
{
break;
}
else
{
p += n;
}
}
}
return ( char * )p;
}
int main( void )
{
char *p = is_word_present( "I have a meeting", "meet" );
if ( p )
{
puts( "The word is present in the sentence" );
}
else
{
puts( "The word is not present in the sentence" );
}
p = is_word_present( "I meet you every day", "meet" );
if ( p )
{
puts( "The word is present in the sentence" );
}
else
{
puts( "The word is not present in the sentence" );
}
return 0;
}
The program output is
The word is not present in the sentence
The word is present in the sentence
I am practicing and I came across an exercise. The exercise says I am to manually write a function that finds the index of the last occurrence in a string. Now, I get that this has maybe been asked before but I cannot find what is the problem with my code. It works for almost all instances, but not so when the last occurrence of the word is at the beginning of the string.
What I have tried: I used pointers to store the addresses of the ends of both the sentence and the word we are looking for. I then used a while loop to iterate through the string. If the current character matches the last character of the word we are searching for, we enter another while loop which compares the two. If the pointer that points to the beginning of the word and the one we used to iterate through the word are equal, the word is found.
Here is some code:
#include <stdio.h>
int find_last( char *str, char *word)
{
char *p, *q;
char *s, *t;
p=str; /* Pointer p now points to the last character of the sentence*/
while(*p!='\0') p++;
p--;
q = word;
while(*q!='\0') q++; /* Pointer q now points to the last character of the word*/
q--;
while(p != str) {
if(*p == *q) {
s=p; /* if a matching character is found, "s" and "t" are used to iterate through */
/* the string and the word, respectively*/
t=q;
while(*s == *t) {
s--;
t--;
}
if(t == word-1) return s-str+1; /* if pointer "t" is equal by address to pointer word-1, we have found our match. return s-str+1. */
}
p--;
}
return -1;
}
int main()
{
char arr[] = "Today is a great day!";
printf("%d", find_last(arr, "Today"));
return 0;
}
So, this code should return 0 but it returns -1.
It works in every other instance I tested! When ran in CodeBlocks, the output is as expected (0), but using any other online IDE I could find the output is still -1.
For starters the parameters of the function shall have the qualifier const and its return type should be either size_t or ptrdiff_t.
For example
ptrdiff_t find_last( const char *str, const char *word );
In any case the function shall be declared at least like
int find_last( const char *str, const char *word );
The function should emulate the behavior of the standard C function strstr. That is when the second argument is an empty string the function should return 0.
If either of the arguments is an empty string then your function has undefined behavior due to these statements
p=str; /* Pointer p now points to the last character of the sentence*/
while(*p!='\0') p++;
p--;
^^^^
q = word;
while(*q!='\0') q++; /* Pointer q now points to the last character of the word*/
q--;
^^^^
If the string pointed to by str contains only one symbol then your function returns -1 because the condition of the loop
while(p != str) {
evaluates to false independent on whether the both strings are equal each other or not.
This loop
while(*s == *t) {
s--;
t--;
}
again can invoke undefined behavior because there can be an access to memory that precedes the string word.
And this statement
if(t == word-1) return s-str+1;
also can invoke the undefined behavior by the same reason.
The function can be defined as it is shown in the demonstrative program below.
#include <stdio.h>
int find_last( const char *str, const char *word )
{
const char *p = str;
int found = !*word;
if ( !found )
{
while ( *p ) ++p;
const char *q = word;
while ( *q ) ++q;
while ( !found && !( p - str < q - word ) )
{
const char *s = p;
const char *t = q;
while ( t != word && *( s - 1 ) == *( t - 1) )
{
--s;
--t;
}
found = t == word;
if ( found ) p = s;
else --p;
}
}
return found ? p - str : -1;
}
int main(void)
{
const char *str = "";
const char *word = "";
printf( "find_last( str, word ) == %d\n", find_last( str, word ) );
word = "A";
printf( "find_last( str, word ) == %d\n", find_last( str, word ) );
str = "A";
printf( "find_last( str, word ) == %d\n", find_last( str, word ) );
str = "ABA";
printf( "find_last( str, word ) == %d\n", find_last( str, word ) );
str = "ABAB";
printf( "find_last( str, word ) == %d\n", find_last( str, word ) );
str = "ABCDEF";
printf( "find_last( str, word ) == %d\n", find_last( str, word ) );
str = "ABCDEF";
word = "BC";
printf( "find_last( str, word ) == %d\n", find_last( str, word ) );
return 0;
}
The program output is
find_last( str, word ) == 0
find_last( str, word ) == -1
find_last( str, word ) == 0
find_last( str, word ) == 2
find_last( str, word ) == 2
find_last( str, word ) == 0
find_last( str, word ) == 1
Input: I want to be something END. END is is that specific word. I need to store all my words.
do
{
scanf("%s", row[p]);
p++;
}while(strcmp(niz,'END')!=0);
Is this the right way ?
#include<stdio.h>
#include<string.h>
/*Description: How to scanf a string until a specific word occurs*/
int main(){
char row[6][10];
int p=0;
//I want to be something END. ( 6 words for input.)
printf("Please enter a word.\n");
/*
do
{
scanf("%s", row[p]);
p++;
}while(strcmp(row[p],"END")!=0);
//Above loop runs forever(or until row runs out of space), because p increments after info is read
*/
do
{
scanf("%s", row[p]);
p++;
}while(strcmp(row[p-1],"END")!=0);
//This loop ends once string just read in from keyboard/user equals "END"
return 0;
}
If I have understood your question correctly then you need something like the following.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
char * string_toupper( char *s )
{
for ( char *p = s; *p; ++p ) *p = toupper( ( unsigned char )*p );
return s;
}
int main( void )
{
enum { N = 50 };
char word[N];
char tmp[N];
const char *s = "one two three four end five";
for ( int offset = 0, pos = 0;
sscanf( s + offset, "%s%n", word, &pos ) == 1 && strcmp( string_toupper( strcpy( tmp, word ) ), "END" ) != 0;
offset += pos )
{
puts( word );
}
}
The program output is
one
two
three
four
Or something like the following
#include <stdio.h>
#include <ctype.h>
#include <string.h>
char * string_toupper( char *s )
{
for ( char *p = s; *p; ++p ) *p = toupper( ( unsigned char )*p );
return s;
}
int main( void )
{
enum { N = 50 };
char word[N];
for ( char tmp[N]; scanf( "%s", word ) == 1 && strcmp( string_toupper( strcpy( tmp, word ) ), "END" ) != 0; )
{
puts( word );
}
}
If to enter
one two three four end
then the output will be
one
two
three
four