Гость
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Разбить строку / 25 сообщений из 25, страница 1 из 1
12.10.2020, 16:01
    #40007770
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Нужно поделить строку по пробелам но не до конца.

допустим строка "ааа ббб ввв ггг"
нужно получить
"ааа"
"ббб"
"ввв ггг"
то есть третяя строка без разделения.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
static uint32_t PARSER_ParseInputString(char* str, char** args)
{
    uint32_t argc=0;

    args[argc] = strtok(str, " ");

    while (args[argc] != NULL)
    {
        if(argc == 2)
            break;
         
        args[++argc] = strtok (NULL, " ");
    }

    return argc;
}             


если if(argc == 2) результат
args[0] = "ааа"
args[1] = "ббб"
args[2] = "ввв " - ггг обрезается

если if(argc == 1) результат
args[0] = "ааа"
args[1] = "ббб"
args[2] = мусор

как мне сделать?
...
Рейтинг: 0 / 0
12.10.2020, 16:11
    #40007773
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Так попробуй
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
    while (args[argc] != NULL)
    {
         
        args[++argc] = strtok (NULL, " ");

        if(argc == 2)
            break;
    }


Не запускал.
...
Рейтинг: 0 / 0
12.10.2020, 16:29
    #40007776
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Dima T
Так попробуй
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
    while (args[argc] != NULL)
    {
         
        args[++argc] = strtok (NULL, " ");

        if(argc == 2)
            break;
    }


Не запускал.

получается то же самое
args[0] = "ааа"
args[1] = "ббб"
args[2] = "ввв " - ггг обрезается

может свою ф-цию написать? strtok мне никогда не нравился :))
...
Рейтинг: 0 / 0
12.10.2020, 17:26
    #40007796
Агрох
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Попробуй так:
Код: plaintext
1.
2.
3.
4.
if(argc == 2){
args[++argc] = strtok (NULL, "");}
else{  
args[++argc] = strtok (NULL, " ");}
...
Рейтинг: 0 / 0
12.10.2020, 17:35
    #40007797
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Агрох
Попробуй так:
Код: plaintext
1.
2.
3.
4.
if(argc == 2){
args[++argc] = strtok (NULL, "");}
else{  
args[++argc] = strtok (NULL, " ");}


после strtok (NULL, "") указатель теряется - пишет unavailable.
...
Рейтинг: 0 / 0
12.10.2020, 18:54
    #40007817
Разбить строку
бьёшь на 4 и склеиваешь 2 последние
...
Рейтинг: 0 / 0
13.10.2020, 07:28
    #40007935
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
strok() заменяет пробел на ноль в конце той строки, которую возвращает. Поэтому надо обратно вернуть пробел
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
	while (args[argc] != NULL)
	{
		if (argc == 2) {
			*(args[argc] + strlen(args[argc])) = ' ';
			break;
		}

		args[++argc] = strtok(NULL, " ");
	}


Правда тут образуется потенциальный косяк в случае если в строке 2 пробела. В этом случае args[2] будет без нуля на конце.
...
Рейтинг: 0 / 0
13.10.2020, 11:18
    #40007987
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
strtok такая неприятная функция. Слишком разрушительная.
...
Рейтинг: 0 / 0
13.10.2020, 19:30
    #40008180
Aklin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
mayton
strtok такая неприятная функция. Слишком разрушительная.


strtok_r не слишком.
...
Рейтинг: 0 / 0
13.10.2020, 19:32
    #40008181
Aklin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
еще strtok_r есть версия "с хвостом"
достаточно взять два токена, а третий из хвоста.

То есть вопрос, откуда взялось число 2 и число 1?
Если это заранее известные числа, то почему бы не
...
Рейтинг: 0 / 0
13.10.2020, 19:47
    #40008190
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Мне непонятны следующие тестовые сценарии. Отмеченные вопросиком

InputOutput"ааа ббб ввв ггг" {"ааа", "ббб","ввв ггг"}"ббб ввв ггг" {"ббб","ввв ггг"}"ввв ггг" {"ввв ггг"} (?)"ггг" {"ггг"} (?)"" {""} (?)

Автор проясни как должно быть.
...
Рейтинг: 0 / 0
13.10.2020, 20:36
    #40008213
Aklin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
что вообще значит "но не до конца"?
Оставить последний пробел? А если там два и более подряд пробела?
...
Рейтинг: 0 / 0
14.10.2020, 08:38
    #40008321
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
mayton
Мне непонятны следующие тестовые сценарии. Отмеченные вопросиком

InputOutput"ааа ббб ввв ггг" {"ааа", "ббб","ввв ггг"}"ббб ввв ггг" {"ббб","ввв ггг"}"ввв ггг" {"ввв ггг"} (?)"ггг" {"ггг"} (?)"" {""} (?)


Автор проясни как должно быть.
скажем я хочу разбить на три части - тогда будет "ааа", "ббб","ввв ггг" - третяя часть остается целиком с пробелами.
...
Рейтинг: 0 / 0
14.10.2020, 08:45
    #40008323
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Dima T
strok() заменяет пробел на ноль в конце той строки, которую возвращает. Поэтому надо обратно вернуть пробел
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
	while (args[argc] != NULL)
	{
		if (argc == 2) {
			*(args[argc] + strlen(args[argc])) = ' ';
			break;
		}

		args[++argc] = strtok(NULL, " ");
	}


Правда тут образуется потенциальный косяк в случае если в строке 2 пробела. В этом случае args[2] будет без нуля на конце.

не. не работает.

а что если сделать что то свое, так например
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
uint32_t SplitString(char* str, char *args[], uint32_t args_lim)
{
    char ptr;
    uint32_t arg_idx;
    uint32_t chr_idx;
    
    while (*str)
    {
        ptr = *str++;
        if (ptr == ' ') //space found
        {
            //skip all spaces
            while (ptr == ' ') 
            {
                ptr = *str++;
            }
            
            //terminate the argument
            args[arg_idx][chr_idx] = '\0';
            //next argument
            arg_idx++;
            chr_idx = 0;
            
            if (arg_idx >= ARGS_MAX || arg_idx == args_lim)
              break;
        }
        else
        {
            args[arg_idx][chr_idx] = ptr;
            chr_idx++;
            if (chr_idx >= ARGS_LEN);
                break;
        }
    }
    
    return arg_idx;
}
...
Рейтинг: 0 / 0
14.10.2020, 08:51
    #40008327
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
jenya7
не. не работает.

У меня работает. Чтоб от проблемы двух пробелов избавиться лучше так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
static uint32_t PARSER_ParseInputString(char* str, char** args)
{
	uint32_t argc = 0;

	args[argc] = strtok(str, " ");

	while (args[argc] != NULL)
	{
		if (argc == 2) {
			if(strtok(NULL, " ") != NULL) *(args[argc] + strlen(args[argc])) = ' ';
			break;
		}

		args[++argc] = strtok(NULL, " ");
	}

	return argc;
}



Тест
Код: plaintext
1.
2.
3.
4.
	char* r[10];
	char buf[] = "aaa bbb ccc ddd";
	PARSER_ParseInputString(buf, r);
	for(int i = 0; i < 3; i++) printf("%d. '%s'\n", i, r[i]);


Результат
Код: plaintext
1.
2.
0. 'aaa'
1. 'bbb'
2. 'ccc ddd'
...
Рейтинг: 0 / 0
14.10.2020, 09:22
    #40008332
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Dima T
jenya7
не. не работает.

У меня работает. Чтоб от проблемы двух пробелов избавиться лучше так


не знаю. мой компайлер сходит сума. контроллер это все таки не комп :))

хочу проверить свою поделку но при передачи статического массива
Код: plaintext
1.
2.
3.
4.
5.
6.
#define ARGS_MAX 32
#define ARGS_LEN 128

char str_args[ARGS_MAX][ARGS_LEN];

SplitString(str, str_args, 2);


компайлер ругается
Error[Pe167]: argument of type "char (*)[128]" is incompatible with parameter of type "char **"
и так тоже
Код: plaintext
1.
SplitString(str, &str_args[0], 2);
...
Рейтинг: 0 / 0
14.10.2020, 11:01
    #40008369
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Дело не в компиляторе, это ты не понимашь разницы между массивом массивов и массивом указателей.
...
Рейтинг: 0 / 0
14.10.2020, 11:24
    #40008374
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Dima T
Дело не в компиляторе, это ты не понимашь разницы между массивом массивов и массивом указателей.


массив массивов я не могу передать
Код: plaintext
1.
uint32_t SplitString(char* str, char args[][], uint32_t args_lim)


Error[Pe098]: an array may not have elements of this type
...
Рейтинг: 0 / 0
14.10.2020, 11:25
    #40008375
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
jenya7
mayton
Мне непонятны следующие тестовые сценарии. Отмеченные вопросиком

InputOutput"ааа ббб ввв ггг" {"ааа", "ббб","ввв ггг"}"ббб ввв ггг" {"ббб","ввв ггг"}"ввв ггг" {"ввв ггг"} (?)"ггг" {"ггг"} (?)"" {""} (?)


Автор проясни как должно быть.
скажем я хочу разбить на три части - тогда будет "ааа", "ббб","ввв ггг" - третяя часть остается целиком с пробелами.
Ты будто не услышал моего вопроса.
Чтоб правильно написать твою функцию мы должны уяснить все кейсы. Ты привел 1 частный случай.

Я спрашиваю - что будет если на вход подать

"Ввв ггг"

Здесь твоя логика - неоднозначная. Можно как разбивать так и не разбивать.

Как правильно?
...
Рейтинг: 0 / 0
14.10.2020, 11:54
    #40008389
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
mayton
jenya7
пропущено...

скажем я хочу разбить на три части - тогда будет "ааа", "ббб","ввв ггг" - третяя часть остается целиком с пробелами.

Ты будто не услышал моего вопроса.
Чтоб правильно написать твою функцию мы должны уяснить все кейсы. Ты привел 1 частный случай.

Я спрашиваю - что будет если на вход подать

"Ввв ггг"

Здесь твоя логика - неоднозначная. Можно как разбивать так и не разбивать.

Как правильно?

на сколько частей разбивать я задам в качестве аргумента. понятно что если строка "Ввв ггг" а я хочу разбить на три части то не получится.
...
Рейтинг: 0 / 0
14.10.2020, 12:31
    #40008398
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
jenya7
Код: plaintext
1.
char str_args[ARGS_MAX][ARGS_LEN];


str_args это массив массивов.
Dima T
Код: plaintext
1.
	char* r[10];


r это массив указателей.

char** args или char* args[] - это указатель на указатель или массив указателей.

Ты бы для начала определился что тебе надо:
1. Разбить строку на подстроки (из отдельных слов) и получить массив указателей на эти подстроки.
2. Скопировать подстроки в массив массивов.

В первом посте у тебя не получается первое, а затем ты постишь 22213867 код где делается второе.

PS За такое надо руки отрывать. Имя ptr - сокращение от pointer, т.е. указатель, поэтому название обязано соответствовать типу
jenya7
Код: plaintext
1.
    char ptr;

...
Рейтинг: 0 / 0
14.10.2020, 12:42
    #40008403
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Dima T
jenya7
Код: plaintext
1.
char str_args[ARGS_MAX][ARGS_LEN];


str_args это массив массивов.
Dima T
Код: plaintext
1.
	char* r[10];


r это массив указателей.

char** args или char* args[] - это указатель на указатель или массив указателей.

Ты бы для начала определился что тебе надо:
1. Разбить строку на подстроки (из отдельных слов) и получить массив указателей на эти подстроки.
2. Скопировать подстроки в массив массивов.

В первом посте у тебя не получается первое, а затем ты постишь 22213867 код где делается второе.

PS За такое надо руки отрывать. Имя ptr - сокращение от pointer, т.е. указатель, поэтому название обязано соответствовать типу
jenya7
Код: plaintext
1.
    char ptr;



strtok делает динамическое выделение памяти. я в своей ф-ции хочу скопировать подстроки в статически выделенную память. поэтому у меня char str_args[32][128] - строки выделены статически.
да это черезмерное выделение памяти но динамическое выделение в эмбедед это зло.

и как тогда передать? такой аргумент функция не принимает uint32_t SplitString(char* str, char args[][], uint32_t args_lim)
...
Рейтинг: 0 / 0
14.10.2020, 12:56
    #40008407
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
jenya7
strtok делает динамическое выделение памяти

Наивный.

Запусти
Код: plaintext
1.
2.
3.
4.
5.
static uint32_t PARSER_ParseInputString(char* str, char* args[])
{
	uint32_t argc = 0;
	args[argc] = strtok(str, " ");
	printf("%p \n%p\n", str, args[argc]);


У меня так
Код: plaintext
1.
00000000001EFC20
00000000001EFC20

strtok() ничего не выделяет, ничего никуда не копирует, он просто портит исходную строку проставляя нолики (конец строки) взамен пробелов и возвращая указатели на подстроки.

В конце добавь вывод str
Код: plaintext
1.
	printf("%s\n", str);


там будет только первое слово, а не вся строка
...
Рейтинг: 0 / 0
14.10.2020, 13:04
    #40008416
Dima T
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
jenya7
поэтому у меня char str_args[32][128] - строки выделены статически.

и как тогда передать? такой аргумент функция не принимает uint32_t SplitString(char* str, char args[][], uint32_t args_lim)

Тебе компилятор говорит как
jenya7
Error[Pe167]: argument of type "char (*)[128]" is incompatible with parameter of type "char **"

Ты передаешь указатель на массив 128 байт, это важно, а ты размер нигде не указал.
Так попробуй
Код: plaintext
1.
 uint32_t SplitString(char* str, char* args[ARGS_LEN], uint32_t args_lim)


Проверять некогда, не заработает - напиши позже проверю.
...
Рейтинг: 0 / 0
14.10.2020, 13:21
    #40008425
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить строку
Dima T
jenya7
strtok делает динамическое выделение памяти


strtok() ничего не выделяет, ничего никуда не копирует, он просто портит исходную строку проставляя нолики (конец строки) взамен пробелов и возвращая указатели на подстроки.

спасибо. это меня натолкнуло на новую идею... :))
...
Рейтинг: 0 / 0
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Разбить строку / 25 сообщений из 25, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]