Как передать указатель на строку, указатель на подстроку и вернуть что-то еще? - PullRequest
0 голосов
/ 18 октября 2018

Я нахожусь на MCU с чрезвычайно ограниченным пространством, и я каким-то образом теряю свою ссылку на C. Я хочу формат примерно такой:

int commandsubstring(char *stringaddress,char *substringaddress);

Однако я выполнил эту процедуру вASM, потому что у меня была какая-то проблема в C, и я просто хотел сделать это.Теперь, когда это сделано, я хочу это исправить.Функция выполняет чтение команды SCPI .Я беру формат "MEASure: VOLTage: DC?"и тогда я рекурсивно возвращаю команду.В моем примере хочу вернуть адрес подстроки

 MEASure:VOLTage:DC?
 ^       ^ 

Я хочу иметь возможность сделать что-то вроде:

char *cmd="MEASure:VOLTage:DC?";
char *subcmd;
commandsubstring(cmd, subcmd);
printf("%s\n", cmd);
printf("%s\n", subcmd);

И затем получить результат

 MEASure:VOLTage:DC?
 VOLTage:DC?

Я не уверен почему, но я теряю указатель где-то в процессе.В остальной части кода я просто возвращаю структуры, но из-за того, что эта конкретная часть является рекурсивной, я хотел попробовать что-то, что мне показалось более безопасным, но я просто не могу получить правильный C, и это просто брейногде-то.Любая помощь будет принята с благодарностью.

Редактировать Это не вопрос о токенизации, а просто правильный способ правильно вернуть другое место в той же строке.

Ответы [ 4 ]

0 голосов
/ 18 октября 2018

Предполагая, что подкоманда идентифицируется 1-й :, вы можете сделать это следующим образом:

#include <stdio.h>
#include <string.h>

int main(void)
{
  const char * cmd = "MEASure:VOLTage:DC?";
  puts(cmd);
  const char * subcmd = strchr(cmd, ':');
  if (NULL == subcmd || !*(++subcmd))
  {
    fprintf(stderr, "No sub-command found.\n");
  }
  else
  {
    puts(subcmd);
  }
}

Чтобы сделать это как функцию, выполните

#include <stdio.h>
#include <string.h>
#include <assert.h>

const char * find_subcmd(const char * cmd)
{
  assert(NULL != cmd);

  char * subcmd = strchr(cmd, ':');
  return (NULL == subcmd || !*(++subcmd)) ?NULL :subcmd;
}

int main(void)
{
  const char * cmd = "MEASure:VOLTage:DC?";
  puts(cmd);
  const char * subcmd = find_subcmd(cmd);
  if (NULL == subcmd)
  {
    fprintf(stderr, "No sub-command found.\n");
  }
  else
  {
    puts(subcmd);
  }
}

или

#include <stdio.h>
#include <string.h>
#include <assert.h>

int find_subcmd(const char * cmd, char const ** psubcmd )
{
  assert(NULL != cmd);
  assert(NULL != psubcmd);

  char * subcmd = strchr(cmd, ':');
  *psubcmd = (NULL == subcmd || !*(++subcmd)) ?NULL :subcmd;

  return *psubcmd ?0 :-1;
}

int main(void)
{
  const char * cmd = "MEASure:VOLTage:DC?";
  const char * subcmd = NULL;
  puts(cmd);
  if (-1 == find_subcmd(cmd, &subcmd))
  {
    fprintf(stderr, "No sub-command found.\n");
  }
  else
  {
    puts(subcmd);
  }
}

Обратите внимание, что в любом из приведенных выше решений subcmd просто указывает "в", на что указывает cmd.Данные не копируются.

0 голосов
/ 18 октября 2018

Когда вы делаете это:

char *cmd="MEASure:VOLTage:DC?";
char *subcmd;
commandsubstring(cmd, subcmd);

Вы передаете значение из subcmd в функцию.Внутри функции это, вероятно, присвоение значения именованному параметру, который не меняет переменную в вызывающей функции.

Самый простой способ справиться с этим - удалить второй параметр и вернуть соответствующий указатель,назначив его на subcmd:

char *commandsubstring(char *stringaddress);

...

subcmd = commandsubstring(cmd);
0 голосов
/ 18 октября 2018

Может быть, этот пример поможет:

#include <stdio.h>

int commandsubstring(char *stringaddress,char **substringaddress)
{
    char * ptr = stringaddress;
    while (ptr!=0) {
        if ((*ptr)==':') { 
            *substringaddress = ptr+1; 
            break;
        }
        ptr++;
    }
    return 0;
}

int main()
{
    char *cmd="MEASure:VOLTage:DC?";
    char *subcmd;
    commandsubstring(cmd, &subcmd);
    printf("%s\n", cmd);
    printf("%s\n", subcmd);

    return 0;
}
0 голосов
/ 18 октября 2018

Глядя на предоставленное вами объявление и пример использования, я бы сказал, что вам нужен указатель на указатель в качестве второго аргумента.То, что у вас есть, это указатель на символ.

То, что у вас есть, очень похоже на неопределенное поведение:

/* Takes two pointer by value */
int commandsubstring(char *stringaddress,char *substringaddress);

void foo(void) 
{
   char *cmd="MEASure:VOLTage:DC?";
   char *subcmd;                  /* an uninitialized variable, could be anything */
   commandsubstring(cmd, subcmd); /* you pass an uninitilized variable in */
   printf("%s\n", cmd);
   printf("%s\n", subcmd);        /* you use an uninitialized variable. Nothing has changed it since it was declared. */
}

Ваш запрос "правильный способ правильно вернутьдругое расположение в той же строке " звучит для меня как" способ правильно вернуть указатель на символ в той же строке ".Есть два способа: вы можете использовать возвращаемое значение или использовать OUT-параметр.

Представьте, что это не char *, вам нужно изображение int для какой-то функции.Вот вам "int" варианты:

/* You want (int) from you functions */
int use_int_return_value(void);
void use_int_out_parameter(int *pint_to_result);

/* You want (char *) from you functions */
char * use_pchar_return_value(void);
void use_pchar_out_parameter(char ** pchar_to_result);
...