PhilHibbs
PhilHibbs

Reputation: 943

strlen inconsistent with zero length string

I'm creating a DataStage parallel routine, which is a C or C++ function that is called from within IBM (formerly Ascential) DataStage. It is failing if one of the strings passed in is zero length. If I put this at the very first line of the function:

return strlen(str);

then it returns 0 for the calls that pass in empty values into str. If I put this at the first line, however...

if (strlen(str)==0) {return 0;}

then it does not return and goes into an infinite loop

I'm baffled - it works fine in a test harness, but not in DataStage.

Maybe there is something odd about the way DataStage passes empty strings to C routines?

int pxStrFirstCharList(char *str, char *chars )
{
  if (strlen(str)==0) {return 0;}
  if (strlen(chars)==0) {return 0;}
  int i = 0;
  //Start search
  while (str[i]) //for the complete input string
  {
    if (strchr(chars, str[i]))
    {
      return i+1;
    }
    ++i;
  }
  return 0;
}

Upvotes: 1

Views: 3154

Answers (4)

Shawn
Shawn

Reputation: 57

I guess it is the strlen's issue when the length of the string is 0. For example,

char s1[0]; char *s2="a";

printf("%d %s\n", sizeof(s1), s1);//0 @

printf("%d %s\n", strlen(s1), s1);//3 @

printf("%d %s\n", sizeof(s2), s2);//8 a

printf("%d %s\n", strlen(s2), s2);// 1 a

You will get a weird answer for using strlen and you can check its source code in detail(https://code.woboq.org/userspace/glibc/string/strlen.c.html). In nutshell, you can use sizeof instead of strlen for char string or avoid 0 length case by using strlen.

Upvotes: 0

Nim
Nim

Reputation: 33645

There is a builtin function for what you are doing, it's called strcspn. This function takes two strings, and searches the first one for the first occurance of any of the characters of the second string.

I suggest using that than RYO...

http://www.cplusplus.com/reference/clibrary/cstring/strcspn/

Upvotes: 1

alk
alk

Reputation: 70981

If NULL is not explicitly part of the game, at least during development phase, it's always a good idea to add a precondition check on pointers received by a function:

int pxStrFirstCharList(char *str, char *chars )
{
  if (!str)
    return -1;

  if (!chars)
    return -2;
....

(The negative values -1 and -2 than tell the caller that something went wrong)

Or doing it in a more relaxed way, silently accepting NULL pointer strings as ""-string:

int pxStrFirstCharList(char *str, char *chars )
{
  if (!str)
    return 0;

  if (!chars)
    return 0;
...

If you are the only one using this API you could #ifndef BUILD_RELEASE these checks away for a release build if anything is tested stable.

Upvotes: 0

0xC0000022L
0xC0000022L

Reputation: 21319

How about this?

int pxStrFirstCharList(char *str, char *chars )
{
  if (str && chars && (0 != strlen(str)) && (0 != strlen(chars)))
  {
    int i = 0;
    //Start search
    while (str[i]) //for the complete input string
    {
      if (strchr(chars, str[i]))
      {
        return i+1;
      }
      ++i;
    }
  }
  return 0;
}

Also, I don't quite get the point of the while loop ... (and no, I don't mean that this could be written as for). What I mean is that on one hand you are doing a search (strstr) that itself will be implemented as a loop and still you have some outer loop. Could it be that you actually wanted to have chars in its place, i.e.:

int pxStrFirstCharList(char *str, char *chars )
{
  if (str && chars && (0 != strlen(str)) && (0 != strlen(chars)))
  {
    int i = 0;
    //Start search
    while (chars[i]) //for the complete input string
    {
      if (strchr(str, chars[i]))
      {
        return i+1;
      }
      ++i;
    }
  }
  return 0;
}

...? That is, look for each of the characters within chars inside the string denoted by str ...

Upvotes: 0

Related Questions