简体   繁体   中英

C string search get part of string

I am trying to make a small test function that when passed a char * will search that string for a certain sub string and then output the next characters after the white space until the next whitespace.

I made a basic implementation using strstr() and strncpy() but this method is kind of static and only works for one search term at a time with a fixed output of the next characters.

int ParseCommand(char *command)
{
    char *pSearch = strstr(command, CommandOne);
    char str[100];

    if (pSearch != NULL)
    {
        pSearch += strlen(CommandOne) + 1;
        strncpy(str, pSearch, 2);
        printf("%s\n\n", str);
    }

    printf("%s\n", command);
    return 0;
}

What this code sample does is if you pass say ParseCommand("ten hats 10 are cool") and CommandOne is equal to "hats" the function will output "10" . Although this does work it performs the operations too statically and will make it hard for it to search for more commands within char *command . I essentially need something that will loop through command until strstr() finds a command inside the passed string and then copy everything from after the command to the next white space.

I know how I would search for the commands (I am going to create a pointer char array with all my search terms and loop through them all until strstr() does not return null) but how about would I copy the next "word" after the searched term?

Overall I need some pseudocode logic to search for search terms within a sentence and then copy the data preseeding it until the next whitespace is reached. (Copy the next word after the search term in the sentence.)

I whipped a quick prototype and it seems to work.

char *ParseCommand(char *command, char *find)
{
    char *p, *q, *t;

    p = strstr(command, find);

    if (p != NULL) {
        /* skip to the next word */
        for (q = p; *q != '\0' && *q != ' '; q++)
            ;
        if (*++q != '\0') {
            for (p = q; *q != '\0' && *q != ' '; q++)
                ;
            t = malloc(q - p);
            return strncpy(t, p, q - p);
        }
    }

    return NULL;
}

Test it with, ParseCommand("ten hats 10 are cool", "hats") and it returns 10 .

HTH.

One problem is designing the interface to the function; the interface you've got is too simple, especially if you need to pick up after you've found the first string. So, I propose a more complex interface:

int find_word_following(char *haystack, const char *needle, char **bgn, char **end);

The haystack is the string to be scanned. The needle is the word to be found. The bgn and end arguments are pointers (outputs) which the function will set to the start of the word after the needle and the end of the word plus one. The return value is either 0 (no word was found) or 1 (a word was found). If *bgn == *end on return and a word was found, then there wasn't another word after it. I've chosen not to specify const char * on the haystack because bgn and end will point to locations in the haystack, and the const-correctness gets messy; the code does not modify haystack, though.

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

int find_word_following(char *haystack, const char *needle, char **bgn, char **end);

int main(void)
{
    char *haystack = "ten hats 10 are cool";
    char *needle   = "hats";
    char *bgn;
    char *end;

    while (find_word_following(haystack, needle, &bgn, &end))
    {
        printf("Found <<%*.*s>>\n", (int)(end - bgn), (int)(end - bgn), bgn);
        needle = "are";  // Change search term
        haystack = end;  // Start where previous scan left off
    }
    return(0);
}

With that much specification, the function isn't dreadfully hard to write:

int find_word_following(char *haystack, const char *needle, char **bgn, char **end)
{
    assert(haystack != 0 && needle != 0 && bgn != 0 && end != 0);
    char *word = strstr(haystack, needle);

    if (word == 0)
        return(0);
    word += strlen(needle);
    // Skip to end of word (in case we found 'hatstand')
    while (*word != '\0' && !isspace(*word))
        word++;
    while (isspace(*word))   // Skip spaces after word
        word++;
    *bgn = word;             // Start of following word
    while (*word != '\0' && !isspace(*word))
        word++;
    *end = word;
    return(1);
}

You could probably replace those loops by appropriate invocations of strspn() and strcspn() .

The output of the program is:

Found <<10>>
Found <<cool>>

A variant that looks for exact words is:

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

int find_word_following(char *haystack, const char *needle, char **bgn, char **end);

int find_word_following(char *haystack, const char *needle, char **bgn, char **end)
{
    assert(haystack != 0 && needle != 0 && bgn != 0 && end != 0);
    size_t length = strlen(needle);
    char *word;
    while ((word = strstr(haystack, needle)) != 0)
    {
        if ((word == haystack || (word > haystack && isspace(*(word - 1)))) &&
            isspace(word[length]))
        {

            word += length;
            while (isspace(*word))   // Skip spaces after word
                word++;
            *bgn = word;             // Start of following word
            while (*word != '\0' && !isspace(*word))
                word++;
            *end = word;
            return(1);
        }
        haystack = word + length;
    }
    return(0);
}

int main(void)
{
    char *haystack = "ten hatstands with hats on are OK";
    char *needle   = "hats";
    char *bgn;
    char *end;

    while (find_word_following(haystack, needle, &bgn, &end))
    {
        printf("Found <<%*.*s>>\n", (int)(end - bgn), (int)(end - bgn), bgn);
        needle = "are";  // Change search term
        haystack = end;  // Start where previous scan left off
    }
    return(0);
}

The output (note the different input string) is:

Found <<on>>
Found <<OK>>

Why not use strtok() to tokenize the string? And then parse the string for a command.

You will probably need a grammar for this (write on in Recursive Descent) way.

SPARKOT ADVICE EDIT(thanks): If you want a faster string search algorithm, look at Boyer-Moore Algorithm .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM