tech74
tech74

Reputation: 1375

Extract a substring in C

i am trying to extract the username from this uri field in ANSI C code on linux using gcc

mail:[email protected]

so i need to strip the mail: and everything after the @. Are there any built in functions in C to extract substrings

Upvotes: 7

Views: 7929

Answers (4)

Baltasarq
Baltasarq

Reputation: 12212

Another solution, which does not rely in any special possibility, and is easily capable of detecting errors is the following one. Note that you'll have to free the string when the function extractUsername() succeeds.

Note that in C you just navigate in a sequence of chars, using pointer arithmetic. There are a few standard library functions, but they are much more simpler than anything able to extract information from the string.

There are still other issues for error detection, such as the presence of more than one '@', for example. But this should be enough as a starting point.

// Extract "mail:[email protected]"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char * MailPrefix = "mail:";
const char AtSign = '@';

char * extractUserName(const char * eMail)
{
    int length = strlen( eMail );
    char * posAtSign = strrchr( eMail, AtSign );
    int prefixLength = strlen( MailPrefix );

    char * toret = (char *) malloc( length + 1 );
    if ( toret != NULL
      && posAtSign != NULL
      && strncmp( eMail, MailPrefix, prefixLength ) == 0 )
    {
        memset( toret, 0, length  +1 );
        strncpy( toret, eMail + prefixLength, posAtSign - prefixLength - eMail );
    }
    else {
        free( toret );
        toret = NULL;
    }

    return toret;
}

int main()
{
    const char * test = "mail:[email protected]";

    char * userName = extractUserName( test );

    if ( userName != NULL ) {
        printf( "User name: '%s'\n", userName );
        free( userName );
    } else {
        fprintf( stderr, "Error: invalid e.mail address\n" );
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

Upvotes: 0

strager
strager

Reputation: 90012

void getEmailName(const char *email, char **name /* out */) {
    if (!name) {
        return;
    }

    const char *emailName = strchr(email, ':');

    if (emailName) {
        ++emailName;
    } else {
        emailName = email;
    }

    char *emailNameCopy = strdup(emailName);

    if (!emailNameCopy) {
        *name = NULL;

        return;
    }

    char *atSign = strchr(emailNameCopy, '@');

    if (atSign) {
        *atSign = '\0'; // To remove the '@'
        // atSign[1] = '\0';  // To keep the '@'
    }

    if (*name) {
        strcpy(*name, emailNameCopy);
    } else {
        *name = emailNameCopy;
    }
}

This creates a pointer to the : character (colon) within the string. (It does not make a copy of the string.) If the : is found, point to the character after it. If the : doesn't exist, just use the beginning of the string (i.e. assume no mail: prefix).

Now we want to strip everything from the @ onward, so we make a copy of the string (emailNameCopy) and later cut off the @.

The code then creates a pointer to the @ character (atSign) within the string. If the @ character exists (i.e. strchr returns non-NULL), the character at the @ is set to zero, marking the end of the string. (A new copy isn't made.)

We then return the string, or copy it if a buffer was given.

Upvotes: 0

Roberto Luis Bisb&#233;
Roberto Luis Bisb&#233;

Reputation: 2090

You could use also strtok. Look at this example

/* strtok example */
#include <stdio.h>
#include <string.h>

    int main ()
    {
      char str[] ="mail:[email protected]";
      char * pch;
      pch = strtok (str," :@");
      while (pch != NULL)
      {
        printf ("%s\n",pch);
        pch = strtok (NULL, " :@");
      }
      return 0;
    }

Hope it helps.

Upvotes: 3

Jerry Coffin
Jerry Coffin

Reputation: 490128

char *uri_field = "mail:[email protected]";

char username[64];

sscanf(uri_field, "mail:%63[^@]", username);

If you might have other "junk" at the beginning (not necessarily just mail:), you could do something like this instead:

sscanf(uri_field, "%*[^:]:%63[^@]", username);

Upvotes: 8

Related Questions