powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Разбить строку
25 сообщений из 25, страница 1 из 1
Разбить строку
    #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
Разбить строку
    #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
Разбить строку
    #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
Разбить строку
    #40007796
Агрох
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробуй так:
Код: plaintext
1.
2.
3.
4.
if(argc == 2){
args[++argc] = strtok (NULL, "");}
else{  
args[++argc] = strtok (NULL, " ");}
...
Рейтинг: 0 / 0
Разбить строку
    #40007797
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Агрох
Попробуй так:
Код: plaintext
1.
2.
3.
4.
if(argc == 2){
args[++argc] = strtok (NULL, "");}
else{  
args[++argc] = strtok (NULL, " ");}


после strtok (NULL, "") указатель теряется - пишет unavailable.
...
Рейтинг: 0 / 0
Разбить строку
    #40007817
бьёшь на 4 и склеиваешь 2 последние
...
Рейтинг: 0 / 0
Разбить строку
    #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
Разбить строку
    #40007987
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
strtok такая неприятная функция. Слишком разрушительная.
...
Рейтинг: 0 / 0
Разбить строку
    #40008180
Фотография Aklin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
strtok такая неприятная функция. Слишком разрушительная.


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

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

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

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

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


Автор проясни как должно быть.
скажем я хочу разбить на три части - тогда будет "ааа", "ббб","ввв ггг" - третяя часть остается целиком с пробелами.
...
Рейтинг: 0 / 0
Разбить строку
    #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
Разбить строку
    #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
Разбить строку
    #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
Разбить строку
    #40008369
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дело не в компиляторе, это ты не понимашь разницы между массивом массивов и массивом указателей.
...
Рейтинг: 0 / 0
Разбить строку
    #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
Разбить строку
    #40008375
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jenya7
mayton
Мне непонятны следующие тестовые сценарии. Отмеченные вопросиком

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


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

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

"Ввв ггг"

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

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

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

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

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

"Ввв ггг"

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

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

на сколько частей разбивать я задам в качестве аргумента. понятно что если строка "Ввв ггг" а я хочу разбить на три части то не получится.
...
Рейтинг: 0 / 0
Разбить строку
    #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
Разбить строку
    #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
Разбить строку
    #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
Разбить строку
    #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
Разбить строку
    #40008425
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima T
jenya7
strtok делает динамическое выделение памяти


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

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


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