Haxify
Haxify

Reputation: 429

Substring in c without using functions

I've seen many solutions for getting substring of a string with usage of strndup or memcpy or strncpy and etc,.

I was wondering if there's a way to get substring without using those functions; even if it's unnecessary.

EDIT: I tried making function myself; I don't remember what the problem was but something went wrong and I ended up not using it.

char *substring(char *str, int start, int length) { 
    char *s = malloc(sizeof(char)*(length+1));

    for(int i=start; i<start+length; i++) {
        s[i-start] = str[i];  
    }
    s[length] = '\0';

    return s;
}

Upvotes: 2

Views: 3161

Answers (2)

Dale Moore
Dale Moore

Reputation: 1

Wow!!! So many variables and tests and lots of indentation.

In the 1970's, some considered it poor style to not have all of the return statements at the bottom of the routine, but that thinking has mostly disappeared.

For some reason, many programmers write their conditionals to test if one variable is equal, not equal, greater, or less than something else. They believe that conditionals should be boolean values and nothing else. But C allows tests of int, char or others equal or not equal to zero. Zero can be NULL or NUL or any other zero value. This is legal and appropriate. if (variable) return NULL;

Some consider conditionals with side effects, such as, if (*h++ == *n++) continue; where variables h and n are modified, to not be great style. To avoid that, I suppose you can rewrite it as if (*h == *n) { h++; n++; continue;}

Here is my version. It is not worse than the version you supplied on this page. But I want to believe it is shorter, simpler, and easier to understand. My style is not perfect. Nobody has perfect style. I supply this only for contrast.

char * strstr( const char *haystack, const char *needle) {
  const char *h = haystack, *n = needle;
  for (;;) {
    if (!*n) return (char *)h;
    if (!*h) return NULL;
    if (*n++ == *h++) continue;
    h = ++haystack;
    n = needle;
  }
}

Upvotes: 0

David C. Rankin
David C. Rankin

Reputation: 84531

There are a number of ways to recreate strstr. The following is a quick implementation using the inch-worm method, where you simply use pointers to search for the beginning of the substring in string, then if found, compare every character in substring with the corresponding character in string. If all characters match, the substring is found, return a pointer to the beginning of substring in string.

If a character fails the test, look for another character in string that matches the first character in substring, until string is exhausted.

There are probably several more checks that can be inplemented, but this example should get you started:

#include <stdio.h>
#include <stdlib.h>

char *strstr2 (char *str, char *sub)
{
    if (!str || !sub) return NULL;              /* validate both strings    */

    char *p = NULL;                             /* general pointer          */
    char *sp = NULL;                            /* substring pointer        */
    char *rp = NULL;                            /* return pointer           */
    char matched = 0;                           /* matched flag             */
    size_t szstr = 0;                           /* string length            */
    size_t szsub = 0;                           /* substring length         */

    p = sub;
    while (*p++) szsub++;                       /* strlen of substr         */

    p = str;
    while (*p++) szstr++;                       /* strlen of str            */

    if (szsub > szstr) return NULL;             /* szstr < szsub - no match */

    p = str;

    while (p < (p + szstr - szsub + 1))
    {
        while (*p && *p != *sub) p++;           /* find start of sub in str */

        if ((str + szstr) == p) return NULL;    /* if end reached - no sub  */

        rp = p;                                 /* save return pointer      */
        sp = sub;                               /* set sp to sub            */
        matched = 1;                            /* presume will match       */
        while (*sp)                             /* for each in substring    */
            if (*p++ != *sp++) {                /* check if match fails     */
                matched = 0;                    /* if failed, no match      */
                break;                          /* break & find new start   */
            }
        if (matched)                            /* if matched, return ptr   */
            return rp;                          /* to start of sub in str   */
    }

    return NULL;                                /* no match, return NULL    */
}

int main() {

    char *string = NULL;
    char *substr = NULL;
    char *begin = NULL;

    printf ("\nEnter string : ");
    scanf ("%m[^\n]%*c", &string);

    printf ("\nEnter substr : ");
    scanf ("%m[^\n]%*c", &substr);

    if ((begin = strstr2 (string, substr)) != NULL)
        printf ("\nSubstring found beginning at : %s\n\n", begin);
    else
        printf ("\nSubstring NOT in string.\n\n");

    if (string) free (string);
    if (substr) free (substr);

    return 0;
}

output:

$ ./bin/strstr

Enter string : This is the full string or "haystack".

Enter substr : g or "

Substring found beginning at : g or "haystack".

$ ./bin/strstr

Enter string : This is the full string or "haystack".

Enter substr : g or '

Substring NOT in string.

Upvotes: 3

Related Questions