1

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;
}
PhilHibbs
  • 859
  • 1
  • 13
  • 30
  • 3
    Are you sure neither of the arguments could be `NULL` IIRC, `strlen()` invokes UB when called with `NULL` arguments. – sbi Nov 25 '11 at 13:43
  • Just a guess, is the function perhaps getting multi-byte characters passed via such pointers? – alk Nov 25 '11 at 19:36

4 Answers4

1

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/

Nim
  • 33,299
  • 2
  • 62
  • 101
0

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.

Shawn
  • 49
  • 2
  • Welcome to SO, please refer to this for better presenting your question/answer: https://meta.stackoverflow.com/a/251362/3519504 – Sandeep Kumar May 09 '20 at 22:40
0

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 ...

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
  • No, it needs to loop through `str` to find the first character that is in `chars` and not the other way around. You may be right about null-testing the parameters but I'm fairly sure that DataStage does not pass nulls. I'll update here if I find otherwise! – PhilHibbs Nov 25 '11 at 16:14
0

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.

alk
  • 69,737
  • 10
  • 105
  • 255
  • 1
    The `assert` macro already exists for this purpose and it's a much better debugging aid since it aborts the program rather than continuing with erroneous state once an error is detected. – R.. GitHub STOP HELPING ICE Nov 25 '11 at 15:08
  • Phil, you may want to comment on this answer instead of appending your reply to the post itself, and then mark this answer as accepted. – BoltClock Nov 25 '11 at 17:17