PDA

Просмотр полной версии : Разбиение буфера на переменные ( строки )


fire64
17.12.2008, 00:50
У меня опять проблема с буферами.

у меня есть буфер такого вида

string1 x00 string2 x00 string2 x00 и так далее

тоесть буфер состоит из нескольких строк разделенных нулями

я побывал создавать структуру
и с помощью нее разделять строки, но проблема в том что длина отдельных строк в буфере мне не известна

и длина строк может меняться

тоесть если я подогнал структуры под определенное количество байт, то не факт что и в следующий раз строки совпадут

izlesa
17.12.2008, 01:55
да проблема с буфЕрами это пять ^______^
используй динамический двумерный массив + в конце исходного буфера ставь дополнительный символ '\0' для обозначения конца. Сначала определяешь количество строк в буфере и выделяешь место под указатели на строки. Потом проходишь и считывая строки во временный буфер, определяешь размеры строк - выделяешь место под строку в массиве двумерном и копируешь туда строку из временного буфера. Если хочешь, завтра наверно напишу пример на plain C , а то сейчас спааааать надо ^______^

впрочем держи ^____^ написано через задницу, но работает.



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

int main(void)
{
char str[] = {'s','s','\0','a','\0','g','g','g','\0','\0'};
char **buffer;
char temp[100];
int flagstr = 0;
int counter = 0;
int count = 0;
int i, j;


for(i = 0;; i++)
{
if((str[i] != '\0') && (flagstr == 0))
{
counter++;
flagstr = 1;
}
else if(str[i] == '\0')
{
if(str[i + 1] == '\0') break;
flagstr = 0;
}

}
printf("%d\n", counter);

buffer = (char **)malloc(counter * sizeof(char **));
flagstr = 0;
count = counter;
counter = 0;

for(i = 0, j = 0;counter < count; i++, j++)
{
if(str[i] != '\0')
{
temp[j] = str[i];
flagstr = 1;
}
else
{
temp[j] = '\0';
buffer[counter] = (char *)malloc((strlen(temp)+1)*sizeof(char *));
memcpy(buffer[counter], temp, strlen(temp)+1);
buffer[counter][j]='\0';
counter++;
flagstr = 0;
j = -1;
}

}

for(i = 0; i < counter; i++)
{
printf("%s\n", buffer[i]);
free(buffer[i]);
}

free(buffer);
getch();


return 0;
}

St0nX
17.12.2008, 10:29
если я все правильно понял то достаточно фунукции strtok(). Получаеш количество вхождений в строку разделителей и в цикле с помощью этой функции делиш.

slesh
17.12.2008, 10:47
Так вешь еще проще - динамический массив pchar'ов
затем циклом проходишь от начала строки до конца и при встрече нуля ставишь умеличиваешь позицию в массиве и ставишь номер следующего элемента+адрес начала строки. При этом \0 сам будет сведетельствовать о конце строки.
Другими словами не выдирать сами строки из буфера, а лишь ставить указатели на них.

izlesa
17.12.2008, 10:52
2St0nX
а разве strtok() умеет работать с '\0' в качестве раздилителей корректно?

fire64
17.12.2008, 16:04
izlesa, спасибо за код, так же спасибо всем остальным за советы

fire64
17.12.2008, 16:59
izlesa, с кодом что то не так
иногда ( видимо зависит от содержимого буфера ), программа крешится

отладчик показал на строку


for(i = 0, j = 0;counter < count; i++, j++)
{
if(ClBuf[i] != '\0')



если точно, то if(ClBuf[i] != '\0')

значения были такие

count 13
counter 12
i 52430
j 678

Поток 'Поток Win32' (0xb2c) завершился с кодом 0 (0x0).
Необработанное исключение в "0x0040162a" в "server.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00137c6a".
Первый этап обработки исключения в "0x0040162a" в "server.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00137c6a".
Необработанное исключение в "0x0040162a" в "server.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00137c6a".

Feonor
17.12.2008, 17:05
...
если точно, то if(ClBuf[i] != '\0')

значения были такие

count 13
counter 12
i 52430
j 678

а размер ClBuf[i] какой? скорее всего произошол выход за границы массива

__________________
http://forum.korol-i-shut.ru/info/ub/119.gif

fire64
17.12.2008, 17:11
размер самого ClBuf 10024


хм увеличил temp до 1024, толку никакого

если надо могу выложить весь код проги

xismyname
17.12.2008, 17:25
да проблема с буфЕрами это пять ^______^
используй динамический двумерный массив + в конце исходного буфера ставь дополнительный символ '\0' для обозначения конца. Сначала определяешь количество строк в буфере и выделяешь место под указатели на строки. Потом проходишь и считывая строки во временный буфер, определяешь размеры строк - выделяешь место под строку в массиве двумерном и копируешь туда строку из временного буфера. Если хочешь, завтра наверно напишу пример на plain C , а то сейчас спааааать надо ^______^

впрочем держи ^____^ написано через задницу, но работает.



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

int main(void)
{
char str[] = {'s','s','\0','a','\0','g','g','g','\0','\0'};
char **buffer;
char temp[100];
int flagstr = 0;
int counter = 0;
int count = 0;
int i, j;


for(i = 0;; i++)
{
if((str[i] != '\0') && (flagstr == 0))
{
counter++;
flagstr = 1;
}
else if(str[i] == '\0')
{
if(str[i + 1] == '\0') break;
flagstr = 0;
}

}
printf("%d\n", counter);

buffer = (char **)malloc(counter * sizeof(char **));
flagstr = 0;
count = counter;
counter = 0;

for(i = 0, j = 0;counter < count; i++, j++)
{
if(str[i] != '\0')
{
temp[j] = str[i];
flagstr = 1;
}
else
{
temp[j] = '\0';
buffer[counter] = (char *)malloc((strlen(temp)+1)*sizeof(char *));
memcpy(buffer[counter], temp, strlen(temp)+1);
buffer[counter][j]='\0';
counter++;
flagstr = 0;
j = -1;
}

}

for(i = 0; i < counter; i++)
{
printf("%s\n", buffer[i]);
free(buffer[i]);
}

free(buffer);
getch();


return 0;
}




Вы допустили ошибку :
buffer = (char **)malloc(counter * sizeof(char **));

указатель на указатель создаеться так :
buffer = (char **)malloc(counter * sizeof(char *));

тоже самое вы сделали в цикле :
buffer[counter] = (char *)malloc((strlen(temp)+1)*sizeof(char *));

а должно быть так :
buffer[counter] = (char *)malloc((strlen(temp)+1)*sizeof(char));


Надеюсь,что разницу видите.

fire64
17.12.2008, 17:32
xismyname, всеравно падает

fire64
17.12.2008, 17:51
мне только что на винграде дали более простой код

const char str[] = {'s','s','\0','a','\0','g','g','g','\0','\0'};
// Код последовательно выводит все разделенные слова
for (const char* p = str ; *p ; p += strlen(p) + 1)
{
puts(p);
}

надеюсь что теперь падать не будет

izlesa
18.12.2008, 00:52
Что я вчера за кусок гу*на накодил? Ппц. ^_____^

2xismyname
согласен, хотя первый косяк не такой страшный ) хотя признаюсь, это ппц )

2fire64
Этот код с винграда восхитителен, великолепен. Он завораживает своим остроумием и профессионализмом. Если я когда-нибудь приближусь хоть на немного к такому же ясному изложению мысли на Си я буду счастлив. Пользуйся им ^____^ и забей на мой. Там выход за пределы массива имеет место быть при некоторых вводных, т.к. условием завершения является количество посчитанных слов и счётчик тупо выбежал за пределы массива, а слова не были посчитаны. Если бы ты дал пример строки с которой вылетае, то было бы проще найти багу, а желание такое есть, ибо опыт.

fire64
18.12.2008, 13:13
izlesa, окей сегодня скину строку