Проблема, с которой вы столкнулись, связана с перекрывающимися правилами.
Запрос www.mysite.nl/adminer
Соответствует обоим: traefik.frontend.rule=Host:mysite.nl, www.mysite.nl, cdn.mysite.net
и traefik.frontend.rule=Host:www.mysite.nl;PathPrefixStrip:/adminer
Поэтому Traefik не знает, на какие запросы направлять.
Используйте метку traefik.frontend.priority
, чтобы установить порядок соответствия (из https://docs.traefik.io/configuration/backends/ докер / # на контейнерах [/ д0])
Решение:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char ** split(const char * str, const char * delim)
{
/* count words */
char * s = strdup(str);
if (strtok(s, delim) == 0)
/* no word */
return NULL;
int nw = 1;
while (strtok(NULL, delim) != 0)
nw += 1;
strcpy(s, str); /* restore initial string modified by strtok */
/* split */
char ** v = malloc((nw + 1) * sizeof(char *));
int i;
v[0] = strdup(strtok(s, delim));
for (i = 1; i != nw; ++i)
v[i] = strdup(strtok(NULL, delim));
v[i] = NULL; /* end mark */
free(s);
return v;
}
int main()
{
char ** v = split("bob is great", " ");
for (int i = 0; v[i] != NULL; ++i) {
puts(v[i]);
free(v[i]);
}
free(v);
return 0;
}
Как видите, я добавляю нулевой указатель в конце вектора в виде метки, но его можно легко изменить, чтобы он возвращал количество слов и т. Д.
Выполнение:
bob
is
great
Второе решение с учетом замечаний алка:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char ** split(const char * str, const char * delim)
{
/* count words */
char * s = strdup(str);
if ((s == NULL) /* out of memory */
|| (strtok(s, delim) == 0)) /* no word */
return NULL;
size_t nw = 1;
while (strtok(NULL, delim) != 0)
nw += 1;
strcpy(s, str); /* restore initial string modified by strtok */
/* split */
char ** v = malloc((nw + 1) * sizeof(char *));
if (v == NULL)
/* out of memory */
return NULL;
if ((v[0] = strdup(strtok(s, delim))) == 0) {
/* out of memory */
free(v);
return NULL;
}
size_t i;
for (i = 1; i != nw; ++i) {
if ((v[i] = strdup(strtok(NULL, delim))) == NULL) {
/* out of memory, free previous allocs */
while (i-- != 0)
free(v[i]);
free(v);
return NULL;
}
}
v[i] = NULL; /* end mark */
free(s);
return v;
}
int main()
{
const char * s = "bob is still great";
char ** v = split(s, " ");
if (v == NULL)
puts("no words of not enough memory");
else {
for (int i = 0; v[i] != NULL; ++i) {
puts(v[i]);
free(v[i]);
}
free(v);
}
return 0;
}
Когда из памяти возвращается значение NULL (в предыдущем версия это была строка для разделения), конечно, есть и другие способы сигнализировать, что легко
Выполнение в valgrind:
==5078== Memcheck, a memory error detector
==5078== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==5078== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==5078== Command: ./a.out
==5078==
bob
is
still
great
==5078==
==5078== HEAP SUMMARY:
==5078== in use at exit: 0 bytes in 0 blocks
==5078== total heap usage: 7 allocs, 7 frees, 1,082 bytes allocated
==5078==
==5078== All heap blocks were freed -- no leaks are possible
==5078==
==5078== For counts of detected and suppressed errors, rerun with: -v
==5078== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)
Подход к разделению строки с неизвестным количеством слов и обеспечению их доступности в ответе функции потребовал бы функции, которая возвращает указатель на указатель на символ . Это позволяет использовать настоящий динамический подход, при котором вы выделяете некоторое начальное количество указателей (скажем, 2, 4, 8
и т. Д.), Совершая один проход через строку, используя strtok
, отслеживая количество используемых указателей, выделяя хранилище для каждого токена ( слово), когда вы идете и когда количество используемых указателей равно выделенному количеству, вы просто realloc
сохраняете дополнительные указатели и продолжаете.
Краткий пример реализации функции splitstring()
, которая делает это похожим на следующее:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NPTR 8 /* initial number of pointers to allocate */
#define MAXD 32 /* maximum no chars for delimiter */
#define MAXC 1024 /* maximum no chars for user input */
char **splitstring (const char *str, const char *delim, size_t *nwords)
{
size_t nptr = NPTR, /* initial pointers */
slen = strlen (str); /* length of str */
char **strings = malloc (nptr * sizeof *strings), /* alloc pointers */
*cpy = malloc (slen + 1), /* alloc for copy of str */
*p = cpy; /* pointer to cpy */
*nwords = 0; /* zero nwords */
if (!strings) { /* validate allocation of strings */
perror ("malloc-strings");
free (cpy);
return NULL;
}
if (!cpy) { /* validate allocation of cpy */
perror ("malloc-cpy");
free (strings);
return NULL;
}
memcpy (cpy, str, slen + 1); /* copy str to cpy */
/* split cpy into tokens */
for (p = strtok (p, delim); p; p = strtok (NULL, delim)) {
size_t len; /* length of token */
if (*nwords == nptr) { /* all pointers used/realloc needed? */
void *tmp = realloc (strings, 2 * nptr * sizeof *strings);
if (!tmp) { /* validate reallocation */
perror ("realloc-strings");
if (*nwords) /* if words stored, return strings */
return strings;
else { /* no words, free pointers, return NULL */
free (strings);
return NULL;
}
}
strings = tmp; /* assign new block to strings */
nptr *= 2; /* update number of allocate pointers */
}
len = strlen (p); /* get token length */
strings[*nwords] = malloc (len + 1); /* allocate storage */
if (!strings[*nwords]) { /* validate allocation */
perror ("malloc-strings[*nwords]");
break;
}
memcpy (strings[(*nwords)++], p, len + 1); /* copy to strings */
}
free (cpy); /* free storage of cpy of str */
if (*nwords) /* if words found */
return strings;
free (strings); /* no strings found, free pointers */
return NULL;
}
int main (void) {
char **strings = NULL,
string[MAXC],
delim[MAXD];
size_t nwords = 0;
fputs ("enter string : ", stdout);
if (!fgets (string, MAXC, stdin)) {
fputs ("(user canceled input)\n", stderr);
return 1;
}
fputs ("enter delimiters: ", stdout);
if (!fgets (delim, MAXD, stdin)) {
fputs ("(user canceled input)\n", stderr);
return 1;
}
if ((strings = splitstring (string, delim, &nwords))) {
for (size_t i = 0; i < nwords; i++) {
printf (" word[%2zu]: %s\n", i, strings[i]);
free (strings[i]);
}
free (strings);
}
else
fputs ("error: no delimiter found\n", stderr);
}
(примечание : счетчик слов nwords
передается как указатель на функцию splitstring()
, позволяющий обновлять число слов внутри функции и возвращать их обратно в вызывающую функцию, возвращая при этом указатель на указатель на символ из самой функции )
Пример использования / вывода
$ ./bin/stringsplitdelim
enter string : my dog has fleas and my cat has none and snakes don't have fleas
enter delimiters:
word[ 0]: my
word[ 1]: dog
word[ 2]: has
word[ 3]: fleas
word[ 4]: and
word[ 5]: my
word[ 6]: cat
word[ 7]: has
word[ 8]: none
word[ 9]: and
word[10]: snakes
word[11]: don't
word[12]: have
word[13]: fleas
(примечание : a ' '
(пробел) было введено в качестве разделителя выше, что приводит к delim
содержит " \n"
(именно то, что вы хотите) благодаря использованию функции линейно-ориентированного ввода fgets
для пользовательского ввода)
Использование памяти / проверка ошибок [1124 ]
В любом написанном вами коде, который динамически распределяет память, у вас есть 2 обязанности в отношении любого выделенного блока памяти: (1) всегда сохраняет указатель на начальный адрес для блок памяти, таким образом, (2) он может быть освобожден ] когда он больше не нужен.
Крайне важно, чтобы вы использовали программу проверки ошибок памяти, чтобы гарантировать, что вы не пытаетесь получить доступ к памяти или писать за пределами / за пределами выделенного блока, пытаться прочитать или основать условный переход на неинициализированном значении и, наконец, , чтобы подтвердить, что вы освобождаете всю выделенную память.
Для Linux valgrind
является нормальным выбором. Есть похожие проверки памяти для каждой платформы. Все они просты в использовании, просто запустите вашу программу через него.
$ valgrind ./bin/stringsplitdelim
==12635== Memcheck, a memory error detector
==12635== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==12635== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==12635== Command: ./bin/stringsplitdelim
==12635==
enter string : my dog has fleas and my cat has none and snakes don't have fleas
enter delimiters:
word[ 0]: my
word[ 1]: dog
word[ 2]: has
word[ 3]: fleas
word[ 4]: and
word[ 5]: my
word[ 6]: cat
word[ 7]: has
word[ 8]: none
word[ 9]: and
word[10]: snakes
word[11]: don't
word[12]: have
word[13]: fleas
==12635==
==12635== HEAP SUMMARY:
==12635== in use at exit: 0 bytes in 0 blocks
==12635== total heap usage: 17 allocs, 17 frees, 323 bytes allocated
==12635==
==12635== All heap blocks were freed -- no leaks are possible
==12635==
==12635== For counts of detected and suppressed errors, rerun with: -v
==12635== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Всегда подтверждайте, что вы освободили всю выделенную память и что ошибок памяти нет.
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.