strlen не соответствует строке нулевой длины

Я создаю параллельную подпрограмму DataStage, которая представляет собой функцию C или C++, вызываемую из IBM (ранее Ascential) DataStage. Ошибка, если одна из переданных строк имеет нулевую длину. Если я поставлю это в самую первую строку функции:

return strlen(str);

затем он возвращает 0 для вызовов, которые передают пустые значения в str. Однако, если я поставлю это в первую строку...

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

то он не возвращается и уходит в бесконечный цикл

Я сбит с толку - он отлично работает в тестовой обвязке, но не в DataStage.

Может быть, есть что-то странное в том, как DataStage передает пустые строки в подпрограммы C?

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;
}

person PhilHibbs    schedule 25.11.2011    source источник
comment
Вы уверены, что ни один из аргументов не может быть NULL IIRC, strlen() вызывает UB при вызове с NULL аргументами.   -  person sbi    schedule 25.11.2011
comment
Просто предположение, возможно, функция получает многобайтовые символы, передаваемые через такие указатели?   -  person alk    schedule 25.11.2011


Ответы (4)


Для того, что вы делаете, есть встроенная функция, она называется strcspn. Эта функция принимает две строки и ищет в первой строку первое вхождение любого из символов второй строки.

Я предлагаю использовать это, чем RYO...

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

person Nim    schedule 25.11.2011
comment
+1, если вы ссылаетесь на хорошую ссылку, а не на одну из самых полных ошибок ссылок в сети. - person R.. GitHub STOP HELPING ICE; 25.11.2011
comment
@R.. хе-хе, я почти уверен, что на приведенной выше странице нет ошибок, TBH, man strcspn действительно лучший вариант! - person Nim; 25.11.2011
comment
Я сомневаюсь, что у кого-то есть ошибки (функция достаточно проста), но я каждый раз съеживаюсь, когда вижу, как люди выставляют этот ужасный рейтинг страницы... - person R.. GitHub STOP HELPING ICE; 25.11.2011
comment
Спасибо за это, я мог бы использовать это в своей функции, чтобы заменить основную логику, но мне нужно обернуть ее, чтобы я мог связать ее с DataStage. - person PhilHibbs; 25.11.2011

Как насчет этого?

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;
}

Кроме того, я не совсем понимаю смысл цикла while... (и нет, я не имею в виду, что это можно записать как for). Я имею в виду, что, с одной стороны, вы выполняете поиск (strstr), который сам будет реализован как цикл, и все же у вас есть некоторый внешний цикл. Может быть, вы на самом деле хотели иметь chars на своем месте, то есть:

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;
}

...? То есть ищите каждый из символов в пределах chars внутри строки, обозначенной str...

person 0xC0000022L    schedule 25.11.2011
comment
Нет, ему нужно перебрать str, чтобы найти первый символ, который находится в chars, а не наоборот. Возможно, вы правы в отношении нулевого тестирования параметров, но я совершенно уверен, что DataStage не передает нулевые значения. Я обновлю здесь, если найду иное! - person PhilHibbs; 25.11.2011

Если NULL явно не является частью игры, по крайней мере, на этапе разработки, всегда полезно добавить предварительную проверку указателей, полученных функцией:

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

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

(Отрицательные значения -1 и -2 сообщают вызывающему абоненту, что что-то пошло не так)

Или сделать это более расслабленным способом, молча принимая строки указателя NULL как ""-строку:

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

  if (!chars)
    return 0;
...

Если вы единственный, кто использует этот API, вы можете #ifndef BUILD_RELEASE отменить эти проверки для сборки релиза, если что-то будет протестировано стабильно.

person alk    schedule 25.11.2011
comment
Для этой цели уже существует макрос assert, и он гораздо лучше помогает при отладке, поскольку прерывает программу, а не продолжает работу с ошибочным состоянием после обнаружения ошибки. - person R.. GitHub STOP HELPING ICE; 25.11.2011
comment
Фил, вы можете прокомментировать этот ответ вместо того, чтобы добавлять свой ответ к самому сообщению, а затем пометить этот ответ как принятый. - person BoltClock; 25.11.2011

Я предполагаю, что это проблема strlen, когда длина строки равна 0. Например,

символ с1[0]; символ *s2="а";

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

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

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

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

Вы получите странный ответ об использовании strlen, и вы можете подробно проверить его исходный код (http://[1]:%20https://code.woboq.org/userspace/glibc/string/strlen)..c.html). В двух словах, вы можете использовать sizeof вместо strlen для строки char или избежать регистра нулевой длины, используя strlen.

person Shawn    schedule 09.05.2020
comment
Добро пожаловать в SO, пожалуйста, обратитесь к этому, чтобы лучше представить свой вопрос/ответ: meta.stackoverflow.com/a/251362/3519504< /а> - person Sandeep Kumar; 10.05.2020