Adrian
Adrian

Reputation: 11

Type a function getWord () that takes a string and returns a pointer to the beginning of the word

I need to type a function getWord () that takes a string and an integer as argument. The function should return a pointer to the beginning of the word to which it refers. If word is 0, a pointer to the first word in the string will be returned, if word is 1, a pointer to the second word will be returned, etc. If word is greater or equal to the number of words in the string, NULL must be returned.

Example run:

ptr = getWord ("hello you", 1); / * "you" returns * / 

ptr2 = getWord ("a string", 0); / * "a" returns * / 

ptr3 = getWord ("one word", 2); / * NULL returns * /

    void getWord(char string[])
{
    int i;

    for (i = 0; i < strlen(string); i++)
    {
        if (isalpha(string[i]))
            printf("%c", string[i]);

        if (string[i] == ' ')
            break;
    }


}

Upvotes: 1

Views: 8529

Answers (4)

Shakiba Moshiri
Shakiba Moshiri

Reputation: 23784

Try this simple idea.
First try to implement a next function like this:

char* next( const char* str )
{
    const char delimiter = ' ';

    // skip all characters up to the first ' '
    while( *str != delimiter && *str != '\0' ) ++str;

    // may the first characters is ' ', so skip it as well
    while( *str == delimiter ) ++str;

    return str;
}

okay, let's test:

int main( )
{
    const char* first = next( "one two three four five" );
    puts( first );

    first = next( first );
    puts( first );

    first = next( first );
    puts( first );

    first = next( first );
    puts( first );
}

its output:

LSP ❱ ./a.out 
two three four five
three four five
four five
five
LSP ❱ 

Now we need to tell the next function that not only goes to the next word but also count how many, thus is becomes:

char* next( const char* str, int index )
{
    const char delimiter = ' ';

   // take care of index for us
    while( index-- ){

        while( *str != delimiter && *str != '\0' ) ++str;
        while( *str == delimiter ) ++str;

    }

    if( *str == '\0' ) return NULL;

    return str;
}

let's test:

int main( )
{
    puts( next( "one two three four five", 0 ) );
    puts( next( "one two three four five", 1 ) );
    puts( next( "one two three four five", 2 ) );
    puts( next( "one two three four five", 3 ) );
    puts( next( "one two three four five", 4 ) );

    if( next( "one two three four five", 5 ) == NULL )
        puts( "NULL was returned" );
}

and:

LSP ❱ ./a.out 
one two three four five
two three four five
three four five
four five
five
NULL was returned
LSP ❱ 

feature:

int main( )
{
    // 1. skip white space 
    puts( next( "one      two     three      four        five", 3 ) );
    // returns: 'four        five'

    puts( "---------------" );

    // 2. easy iteration over a string 
    const char* first = "one two three four five";
    while( ( first = next2( first ) ) != NULL )
    {
        puts( first );
    }
}

outputs:

LSP ❱ ./a.out 
four        five
---------------
two three four five
three four five
four five
five
LSP ❱ 

For returning just a word based on an index, you can use strdup see man 3 strdup and strchr, see man 3 strchr. Thus inside the next function you should add (after while loop):

char* next( char* str, int index )
{
    const char delimiter = ' ';

    while( index-- ){

        while( *str != delimiter && *str != '\0' ) ++str;
        while( *str == delimiter ) ++str;
        if( *str == '\0' ) return NULL;

    }

    // duplicate the current string
    char* result = strdup( str );

    // find the first whitespace and make it as NUL
    result [strchr( result, ' ' ) - result ] = '\0';

    if( *result == '\0' ) return NULL;

    return result;
}

and inside the main:

int main( )
{
    char* r = next( "one      two     three      four        five", 3 );
    if( r != NULL )
    {
        puts( r );
        free( r );
    }
    else
    {
        puts( "there is no word at index 3" );
    }

    char* s = next( "one      two     three      four        five", 8 );
    if( s != NULL )
    {
        puts( s );
        free( s );
    }
    else
    {
        puts( "there is no word at index 8" );
    }
}

test:

LSP ❱ gcc -fsanitize=address temp.c
LSP ❱ ./a.out 
four
there is no word at index 8
LSP ❱ 

NOTE for next2 just add:

if( *str == '\0' ) return NULL;

to the first next and names it next2
Also you should check the return value of strdup it may be NULL

Upvotes: 0

H.S.
H.S.

Reputation: 12669

This getWord() returns the (n+1)th word of input string:

char * getWord(char * string, int n)
{
        char str[1024] = {'\0'};
        char * delim = " \t";
        char * pch = NULL;
        char * result = NULL;
        int i = 0;

        if (string == NULL)
                return NULL;

        strcpy (str, string);
        pch = strtok (str, delim);
        while (pch != NULL)
        {
                if (i == n)
                        break;
                pch = strtok (NULL, delim);
                i++;
        }

        if (pch != NULL)
        {
                result = (char *)malloc(strlen(pch) + 1);
                if (result == NULL)
                        printf ("Failed to allocate memory\n");
                else
                        strcpy (result, pch);
        }
        return result;
}

If this function returns the result as not NULL, make sure to free the memory allocated to "result" variable in the function which is calling getWord().

The main() will look something like this -

int main ()
{
        char * ptr;
        ptr = getWord ("hello you", 1);
        if (ptr != NULL)
        {
                printf ("ptr = %s\n", ptr);
                free(ptr);
        }
        else
                printf ("ptr is NULL");
        return 0;
}

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 310950

We beginners should help each other.:)

Here you are.

#include <stdio.h>
#include <string.h>

char * getWord(const char *s, size_t n)
{
    while ( ( s += strspn(s, " \t") ) != '\0' && n-- )
    {
        s += strcspn(s, " \t");
    }

    return *s ? (char *)s : (char *)0;
}

int main( void )
{
    char *s = "Hi Adrian. How are you?";
    size_t n = 0;

    for (char *p; (p = getWord(s, n)) != NULL; ++n)
    {
        printf("%zu: %s\n", n, p);
    }

    printf("\nThere are %zu words in the string\n", n);

    return 0;
}

The output of the demonstrative program is

0: Hi Adrian. How are you?
1: Adrian. How are you?
2: How are you?
3: are you?
4: you?

There are 5 words in the string

If you want to get the output like this

0: Hi
1: Adrian.
2: How
3: are
4: you?

There are 5 words in the string

then just rewrite the loop in main the following way

for (char *p; (p = getWord(s, n)) != NULL; ++n)
{
    size_t len = strcspn(p, " \t");
    printf("%zu: %*.*s\n", n, ( int )len, ( int )len, p);
}

Upvotes: 1

shubham srivastava
shubham srivastava

Reputation: 1

This is what you can do

char* get_word (char *string,int req_num)
{
int i;
int ns;//number of spaces
int *sp;
ns=0;
for(i=0;string[i]!='\0';i++)
{
//check for a spaces and increment ns
if (string[i]==' ')
{
++ns;
sp=(int*)realloc(sp,ns*sizeof(int));
sp[ns-1]=(int)&string[i+1];
}
//check what place you have to return
if(req_num>=ns)
return NULL;
else
return (char*)sp[req_num];
}
}

This code is very un-optimized and you can comeup with ways to restructure the code to optimize it to run it faster.

Upvotes: 0

Related Questions