Форум программистов, компьютерный форум CyberForum.ru

Разбиение произвольного текста на строки указанной длины - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.69
-=ЮрА=-
Заблокирован
Автор FAQ
12.04.2010, 20:15     Разбиение произвольного текста на строки указанной длины #1
Полное задание
Вариант В22.
Составить и отладить программу,
реализующую разбиение произвольного текста
на строки указанной длины без переноса (=разрыва)
слов в конце строки и в то же время без большого
коли-чества пробелов в конце строки (>3), путем
равномерного распределения их между словами данной строки.

Вот моя реализация на С
C++
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <windows.h>
#include <stdio.h>
 
//Выделяем память под наш текстовый блок
char * str = (char *)malloc(sizeof(char));
//Выделяем память под массив строк
char ** sMass = (char **)malloc(sizeof(char));
                //ФУНКЦИИ
//Функция ввода текста до тех пор пока не встретиться символ ch_end
char * enter_text(char * str, char ch_end);
//Выделение отдельной строки длиной sLen из текстового блока sBlock
//начиная с позиции iPos
char * get_string(char * sBlock, char * str, int iPos, int sLen);
//Проверка не состоит ли строка только лишь из пробелов
bool not_empty_str(char * str);
//Возвращает количество слов в строке
int get_num_words(char * str);
//Расвномерное распределение пробелов между словами строки
//при их количстве вконце строки > nSpaces
char * distr_spaces(char * str, int nSpaces);
 
void main()
{
    printf("\tEnter text block\r\n");
    str = enter_text(str, '\n');
    printf("\tEnter length of 1 string\r\n");
    int sLen = -1;scanf("%d",&sLen);
    int nStr = strlen(str) / sLen + 1;
    sMass = (char **)realloc(sMass,nStr*sizeof(char));
    printf("\tStrings after dividing input text\r\n");
    //Формируем массив строк sMass
    for(int i = 0,iAdd = 0; i < nStr; i++)
    {
        sMass[i] = (char *)malloc(sLen);
        sMass[i] = get_string(str, sMass[i], iAdd, sLen);
        iAdd += strlen(sMass[i]);
        printf("[%02d] : %s\r\n",i + 1,sMass[i]);
        if(strlen(str) <= iAdd)
            break;
    }
    printf("Num of strings : %d\r\n", (nStr = i + 1));
    printf("Press NUM1 to enter new text block\r\n");
    getchar();
    str = enter_text(str, '\n');
    if(str[0] == '1')
        main();
}
 
char * enter_text(char * str, char ch_end)
{
    int sLen = 0;
    if(str)
    {
        while((str[sLen++] = getchar()) != ch_end)
            str = (char *)realloc(str,(sLen + 1)*sizeof(char));
        str[sLen - 1] = '\0';
    }
    return str;
}
 
char * get_string(char * sBlock, char * str, int iPos, int sLen)
{
    if(sBlock != NULL && str != NULL)
    {
        for(int i = iPos; i < iPos + sLen; i++)
            str[i - iPos] = sBlock[i];
        //Если строка оканчивается посередине слова, 
        //то копируем оставшиеся символы, одновременно 
        //увеличивая длину строки
        while(sBlock[i] != ' ')
        {
            str = (char *)realloc(str,i - iPos + 1);
            str[i - iPos] = sBlock[i];
            i++;
        }
        str[i - iPos] = '\0';
    }
    return str;
}
ниже скриншот работы а также пример с последовательным разбиением на одного и того же текста на строки с разным числом слов, в архиве экзешник и скомпилированный экзешник...Писал просто без всяких вывертов с использованием динамического выделения памяти под текстовый блок и массив строк..
Миниатюры
Разбиение произвольного текста на строки указанной длины  
Вложения
Тип файла: txt PrntScrn.txt (1.8 Кб, 28 просмотров)
Тип файла: rar text_divide.rar (15.5 Кб, 37 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.04.2010, 20:15     Разбиение произвольного текста на строки указанной длины
Посмотрите здесь:

C++ Подмножества указанной длины в множестве
C++ Вводится строка произвольного текста.
C++ Дана строка символов,состоящая из произвольного текста
C++ Разделение произвольного текста на слова
Текстовый файл содержит строки – предложения разной длины. Записать их в выходной файл в порядке возрастания длины строки C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
-=ЮрА=-
Заблокирован
Автор FAQ
15.04.2010, 13:58  [ТС]     Разбиение произвольного текста на строки указанной длины #2
Я доработал исходный код так, чтобы лишние пробелы вконце строки
равномерно распределялись между словами.(Вобщем на 100% по заданию)
Думаю коментарии внутри функций исключат все вопросы.
функцию char * str_insert(char * str, int iPos, char * ins)
написал без излишеств, чтобы понятно было. Впринципе можно было обойтись и без
неё, а использовать стандартную функцию memmove(), но тогда была не совсем понятна
суть перестановки символов внутри подстроки...Что ж удачи на защите и не забываем
о волшебной кнопке СПАСИБО если код действительно пригодился!))
C++
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#include <windows.h>
#include <stdio.h>
 
//Выделяем память под наш текстовый блок
char * str = (char *)malloc(sizeof(char));
//Выделяем память под массив строк
char ** sMass = (char **)malloc(sizeof(char));
                //ФУНКЦИИ
//Функция ввода текста до тех пор пока не встретиться символ ch_end
char * enter_text(char * str, char ch_end);
//Выделение отдельной строки длиной sLen из текстового блока sBlock
//начиная с позиции iPos
char * get_string(char * sBlock, char * str, int iPos, int sLen);
//Равномерно распределяет пробелы между словами если
//их число вконце больше nSpaces
char * div_spaces(char * sBlock, int nSpaces);
//Возвращает строку без пробелов вначале
char * skip_spaces(char * str);
//Вставляет подстроку ins в строку str с позиции iPos
char * str_insert(char * str, int iPos, char * ins);
 
void main()
{
    printf("\tEnter text block\r\n");
    str = enter_text(str, '\n');
    printf("\tEnter length of 1 string\r\n");
    int sLen = -1;scanf("%d",&sLen);
    int nStr = strlen(str) / sLen + 1;
    sMass = (char **)realloc(sMass,nStr*sizeof(char));
    printf("\tStrings after dividing input text\r\n");
    //Формируем массив строк sMass
    for(int i = 0,iAdd = 0; i < nStr; i++)
    {
        sMass[i] = (char *)malloc(sLen);
        sMass[i] = get_string(str, sMass[i], iAdd, sLen);
        iAdd += strlen(sMass[i]);
        printf("\t[%02d] :\r\n",i + 1);
        printf("->%s<-\r\n",sMass[i]);
        //Строка с перераспределёнными пробелами
        printf("->%s<-\r\n",div_spaces(sMass[i], 3));
        //Примечание
        //Если исходные строки не нужны то можно
        //записать так sMass[i] = div_spaces(sMass[i], 3);
        if(strlen(str) <= iAdd)
            break;
    }
    printf("Num of strings : %d\r\n", (nStr = i + 1));
    printf("Press NUM1 to enter new text block\r\n");
    getchar();
    str = enter_text(str, '\n');
    if(str[0] == '1')
        main();
}
 
char * enter_text(char * str, char ch_end)
{
    int sLen = 0;
    if(str)
    {
        while((str[sLen++] = getchar()) != ch_end)
            str = (char *)realloc(str,(sLen + 1)*sizeof(char));
        str[sLen - 1] = '\0';
    }
    return str;
}
 
char * get_string(char * sBlock, char * str, int iPos, int sLen)
{
    if(sBlock != NULL && str != NULL)
    {
        for(int i = iPos; i < iPos + sLen; i++)
            str[i - iPos] = sBlock[i];
 
        //При динамическом выделении памяти
        //вконце строк идёт мусор, поэтому вконце
        //необходим терминатор '\0'!!!
        str[i - iPos] = '\0';
        //Проверяем содержит ли строка пробелы
        //При этом мы не должны учитывать пробелы
        //которые идут вначале строки перед словом
        //т.е необходимо выбросить начальные пробелы
        char * chBuf = strchr(str,' ');
        if(str[0] == ' ')
        while(*chBuf)
        {
            if(chBuf[0] != ' ')
                break;
            chBuf++;
        }
        bool IsSpaces = false;
        //Проверка данного условия необходима 
        //для случая попадания в середину слова, 
        //при этом если строка не содержит пробелов
        //т.е. состоит из 1-го слова
        //то необходимо докопировать слово в строку
        //иначе отбросить лишние символы
 
        //Зададимся строкой "строка символов"
        //Пример 1: - строка из 1 слова попали в его середину
        //пусть длина подстроки 4 символа тогда
        //
        //подстрока = "стро" - в этом случае надо докопировать
        //оставшуюсячасть слова, т.е. подстрока = "строка"!!!
        //
        //Пример 2: - строка из 2 слов попали в символы 2-го
        //пусть длина подстроки 8 символов тогда
        //
        //подстрока = "строка с" - в этом случае надо отступить
        //назад до пробела, т.е. подстрока = "строка"!!!
        if(*chBuf)
        if(strchr(chBuf,' '))
            IsSpaces = true;
        
        //Если строка оканчивается посередине слова, 
        //то отбрасываем слово, путём сдвига обратно
        //одновременно уменьшая длину строки
        while(*(sBlock + i))
        {
            str = (char *)realloc(str,i - iPos + 1);
            str[i - iPos] = sBlock[i];
            if(sBlock[i] == ' ')
                break;
            if(IsSpaces)
                i--;
            else
                i++;
        }
        str[i - iPos] = '\0';
    }
    return str;
}
 
char * div_spaces(char * sBlock, int nSpaces)
{
    if(sBlock != NULL)
    {
        int nCount = 0;
        char * chBuf = strrchr(sBlock,' ');
        //Вычисляем число пробелов вконце
        //для этого находим последний пробел в строке
        //и последовательно отступаем на символ назад
        //до того как предыдущий символ станет не пробелом
        if(chBuf)
        {
            //Также необходимо учесть что последний пробел должен
            //также являться последним символом строки!!!
            //В противном случае мы будем подсчитывать количество
            //пробелов в каком нибудь промежутке в середине слова
            if(strlen(chBuf) == 1)
            while((chBuf - nCount) != NULL)
            {
                if(*(chBuf - nCount) != ' ')
                    break;
                nCount++;
            }
        }
        if(nSpaces < nCount)
        {
            int nBlocks = 0;
            int *sPos = (int *)malloc(sizeof(int));
            chBuf = skip_spaces(sBlock);
            while(chBuf != NULL)
            {
                //Записываем в массив позиции промежутков между словами
                sPos[nBlocks] = strlen(sBlock) - strlen(chBuf);
                if(chBuf = skip_spaces(chBuf + sPos[nBlocks]))
                    chBuf = strchr(chBuf,' ');
                if(chBuf == NULL)
                    break;
                nBlocks++;
                sPos = (int *)realloc
                (
                    (void *)sPos,
                    (nBlocks + 1)*sizeof(int)
                );
            }
            int nAdd = (nCount - nSpaces)/nBlocks;
            //Если пробелов вконце строки не хватает для добавления
            //во все промежутки между слвами, например слов 5 а
            //лишних пробелов от 1-го до 5-ти
            if(nAdd < 1)
            {
                while(nAdd < 1)
                {
                    nBlocks--;
                    //Это случай нескольких слов в строке и всего
                    //1-го лишнего пробела вконце
                    if(nBlocks == 0)
                    {
                        nAdd = (nCount - nSpaces);
                        break;
                    }
                    nAdd = (nCount - nSpaces)/nBlocks;
                }
                nBlocks = nAdd/(nCount - nSpaces);
            }
            while(0 < nBlocks)
            {
                nBlocks--;
                sBlock = str_insert
                (
                    sBlock,
                    sPos[nBlocks],
                    &sBlock[strlen(sBlock) - nAdd]
                );
            }
        }
    }
    return sBlock;
}
 
char * skip_spaces(char * str)
{
    int i = 0;
    if(str != NULL)
    {
        while((str + i) != NULL)
        {
            if(str[i] != ' ')
                break;
            i++;
        }
    }
    return (str + i);
}
 
char * str_insert(char * str, int iPos, char * ins)
{
    if(*str && * ins)
    {
        int sLen = strlen(str);
        int nAdd = strlen(ins);
        if(iPos < sLen)
        {
            str = (char *)realloc(str,sLen + nAdd);
            for(int i = sLen + nAdd - 1; iPos + nAdd <= i; i--)
                str[i] = str[i - nAdd];
            for(i = iPos; i < iPos + nAdd;i++)
                str[i] = ins[i - iPos];
            str[sLen] = '\0';
        }
    }
    return str;
}
Миниатюры
Разбиение произвольного текста на строки указанной длины  
-=ЮрА=-
Заблокирован
Автор FAQ
18.04.2010, 18:23  [ТС]     Разбиение произвольного текста на строки указанной длины #3
Всё таки пришлось выловить ещё пару багов, и добавить ещё одну функцию
C++
1
bool is_null_str(char * str);
В программе всё прокоменчено...Приношу извинения за 3-ю редакцию - сразу всего и не упомнишь)))
Ниже подправленный код, в файле text.txt текстовый блок который использовал для тестирования
C++
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#include <windows.h>
#include <stdio.h>
 
//Выделяем память под наш текстовый блок
char * str = (char *)malloc(sizeof(char));
//Выделяем память под массив строк
char ** sMass = (char **)malloc(sizeof(char));
                //ФУНКЦИИ
//Функция ввода текста до тех пор пока не встретиться символ ch_end
char * enter_text(char * str, char ch_end);
//Выделение отдельной строки длиной sLen из текстового блока sBlock
//начиная с позиции iPos
char * get_string(char * sBlock, char * str, int iPos, int sLen);
//Равномерно распределяет пробелы между словами если
//их число вконце больше nSpaces
char * div_spaces(char * sBlock, int nSpaces);
//Возвращает строку без пробелов вначале
char * skip_spaces(char * str);
//Вставляет подстроку ins в строку str с позиции iPos
char * str_insert(char * str, int iPos, char * ins);
//Проверка того что строка состоит полностью из пробелов
bool is_null_str(char * str);
 
void main()
{
    printf("\tEnter text block\r\n");
    str = enter_text(str, '\n');
    printf("\tEnter length of 1 string\r\n");
    int sLen = -1;scanf("%d",&sLen);
    int nStr = strlen(str) / sLen + 1;
    sMass = (char **)realloc(sMass,nStr*sizeof(char));
    printf("\tStrings after dividing input text\r\n");
    //Формируем массив строк sMass
    for(int i = 0,iAdd = 0; i < nStr; i++)
    {
        sMass[i] = (char *)malloc(sLen);
        sMass[i] = get_string(str, sMass[i], iAdd, sLen);
        iAdd += strlen(sMass[i]);
        printf("\t[%02d] :\r\n",i + 1);
        printf("->%s<-\r\n",sMass[i]);
        //Строка с перераспределёнными пробелами
        //Если строка полностью состоит из пробелов
        //её преобразование не производим
        printf("->%s<-\r\n",is_null_str(sMass[i]) ? sMass[i] : div_spaces(sMass[i], 3));
        //Примечание
        //Если исходные строки не нужны то можно
        //записать так sMass[i] = div_spaces(sMass[i], 3);
        if(strlen(str) <= iAdd)
            break;
    }
    printf("Num of strings : %d\r\n", (nStr = i + 1));
    printf("Press NUM1 to enter new text block\r\n");
    getchar();
    str = enter_text(str, '\n');
    if(str[0] == '1')
        main();
}
 
char * enter_text(char * str, char ch_end)
{
    int sLen = 0;
    if(str)
    {
        while((str[sLen++] = getchar()) != ch_end)
            str = (char *)realloc(str,(sLen + 1)*sizeof(char));
        str[sLen - 1] = '\0';
    }
    return str;
}
 
char * get_string(char * sBlock, char * str, int iPos, int sLen)
{
    if(sBlock != NULL && str != NULL)
    {
        for(int i = iPos; i < iPos + sLen; i++)
            str[i - iPos] = sBlock[i];
 
        //При динамическом выделении памяти
        //вконце строк идёт мусор, поэтому вконце
        //необходим терминатор '\0'!!!
        str[i - iPos] = '\0';
        //Проверяем содержит ли строка пробелы
        //При этом мы не должны учитывать пробелы
        //которые идут вначале строки перед словом
        //т.е необходимо выбросить начальные пробелы
        char * chBuf = strchr(str,' ');
        if(str[0] == ' ')
        while(*chBuf)
        {
            if(chBuf[0] != ' ')
                break;
            chBuf++;
        }
        bool IsSpaces = false;
        //Проверка данного условия необходима 
        //для случая попадания в середину слова, 
        //при этом если строка не содержит пробелов
        //т.е. состоит из 1-го слова
        //то необходимо докопировать слово в строку
        //иначе отбросить лишние символы
 
        //Зададимся строкой "строка символов"
        //Пример 1: - строка из 1 слова попали в его середину
        //пусть длина подстроки 4 символа тогда
        //
        //подстрока = "стро" - в этом случае надо докопировать
        //оставшуюсячасть слова, т.е. подстрока = "строка"!!!
        //
        //Пример 2: - строка из 2 слов попали в символы 2-го
        //пусть длина подстроки 8 символов тогда
        //
        //подстрока = "строка с" - в этом случае надо отступить
        //назад до пробела, т.е. подстрока = "строка"!!!
        if(*chBuf)
        if(strchr(chBuf,' '))
            IsSpaces = true;
        
        //Если строка оканчивается посередине слова, 
        //то отбрасываем слово, путём сдвига обратно
        //одновременно уменьшая длину строки
        while(*(sBlock + i))
        {
            str = (char *)realloc(str,i - iPos + 1);
            str[i - iPos] = sBlock[i];
            if(sBlock[i] == ' ')
                break;
            if(IsSpaces)
                i--;
            else
                i++;
        }
        str[i - iPos] = '\0';
    }
    return str;
}
 
char * div_spaces(char * sBlock, int nSpaces)
{
    if(sBlock != NULL)
    {
        int nCount = 0,sLen = strlen(sBlock);
        char * chBuf = strrchr(sBlock,' ');
        //Вычисляем число пробелов вконце
        //для этого находим последний пробел в строке
        //и последовательно отступаем на символ назад
        //до того как предыдущий символ станет не пробелом
        if(chBuf)
        {
            //Также необходимо учесть что последний пробел должен
            //также являться последним символом строки!!!
            //В противном случае мы будем подсчитывать количество
            //пробелов в каком нибудь промежутке в середине слова
            if(strlen(chBuf) == 1)
            while((chBuf - nCount) != NULL)
            {
                nCount++;
                if(*(chBuf - nCount) != ' ')
                    break;
            }
        }
        if(nSpaces < nCount)
        {
            int nBlocks = 0;
            int *sPos = (int *)malloc(sizeof(int));
            chBuf = skip_spaces(sBlock);
            while(chBuf != NULL)
            {
                //Записываем в массив позиции промежутков между словами
                sPos[nBlocks] = strlen(sBlock) - strlen(chBuf);
                if(chBuf = skip_spaces(chBuf + sPos[nBlocks]))
                    chBuf = strchr(chBuf,' ');
                //Переставил nBlocks++; т.к. в случае досрочного выхода
                //из цикла операция инкремента не выполнялась nBlocks++
                //в результате возникали ситуации когда nBlocks = 0
                //и при выходе из цикла в выражении nAdd = (nCount - nSpaces)/nBlocks
                //было деление на нуль, что вызывало ошибку
                nBlocks++;
                if(chBuf == NULL)
                    break;
                sPos = (int *)realloc
                (
                    (void *)sPos,
                    (nBlocks + 1)*sizeof(int)
                );
            }
            int nAdd = (nCount - nSpaces)/nBlocks;
            //Если пробелов вконце строки не хватает для добавления
            //во все промежутки между слвами, например слов 5 а
            //лишних пробелов от 1-го до 5-ти
            if(nAdd < 1)
            {
                while(nAdd < 1)
                {
                    nBlocks--;
                    //Это случай нескольких слов в строке и всего
                    //1-го лишнего пробела вконце
                    if(nBlocks == 0)
                    {
                        nAdd = (nCount - nSpaces);
                        break;
                    }
                    nAdd = (nCount - nSpaces)/nBlocks;
                }
                nBlocks = nAdd/(nCount - nSpaces);
            }
            //Случай всего 1-го слова в строке, в этом случае удваиваем
            //nAdd и данные проблеы добавляем с позиции sPos[0], т.е перед словом
            if(nBlocks == 2 && is_null_str(sBlock + sPos[nBlocks - 1] + 1))
            {
                nAdd    *= 2;
                nBlocks--;
            }
            while(0 < nBlocks)
            {
                nBlocks--;
                sBlock = str_insert
                (
                    sBlock,
                    sPos[nBlocks],
                    &sBlock[strlen(sBlock) - nAdd]
                );
                //Обрезаем строку, т.к. нам необходима лишь 
                //перестановка внутри sBlock, т.е
                //Например :
                //sBlock = "строка12", необходимо переставить подстроку "12"
                //на позицию 0
                //после str_insert получаем вставку "12" в, т.е sBlock = "12строка12", 
                //для перестановки необходимо убрать символы "12" вконце строки
                sBlock[sLen] = '\0';
            }
            free((void *)sPos);
        }
    }
    return sBlock;
}
 
char * skip_spaces(char * str)
{
    int i = 0;
    if(str != NULL)
    {
        while((str + i) != NULL)
        {
            if(str[i] != ' ')
                break;
            i++;
        }
    }
    return (str + i);
}
 
char * str_insert(char * str, int iPos, char * ins)
{
    if(*str && *ins)
    {
        int sLen = strlen(str);
        int nAdd = strlen(ins);
        //В случае перекрывания элементов строк str и ins
        //при перестановке символов внутри str возможно
        //изменение символов ins!!!
        //Например :
        //строка12, необходимо переставить подстроку "12"
        //на позицию 0, тогда после цикла 
        //  for(i = sLen + nAdd - 1; iPos + nAdd <= i; i--)
        //произойдёт следующее :
        //str = "стстрока"
        //ins = "ка" 
        //для избежания этого вводим дополнительную строку sIns
        /////////////////////////////////////////////////////////
        char * sIns = (char *)malloc(nAdd);
        for(int i = 0;i < nAdd; i++)
            sIns[i] = ins[i];
        /////////////////////////////////////////////////////////
        if(iPos < sLen)
        {
            str = (char *)realloc(str,sLen + nAdd);
            for(i = sLen + nAdd - 1; iPos + nAdd <= i; i--)
                str[i] = str[i - nAdd];
            for(i = iPos; i < iPos + nAdd;i++)
                str[i] = sIns[i - iPos];
        }
        //////////////////////////////////////////////////////////
        free(sIns);
        //////////////////////////////////////////////////////////
    }
    return str;
}
 
bool is_null_str(char * str)
{
    bool RetVal = true;
    if(str != NULL)
    {
        int sLen = strlen(str);
        for(int i = 0; i < sLen; i++)
            if(str[i] != ' ')
                RetVal = false;
    }
    return RetVal;
}
Миниатюры
Разбиение произвольного текста на строки указанной длины  
Вложения
Тип файла: txt text.txt (1.1 Кб, 19 просмотров)
-=ЮрА=-
Заблокирован
Автор FAQ
20.04.2010, 21:23  [ТС]     Разбиение произвольного текста на строки указанной длины #4
Устал я уже переделывать, в этом случае без динамического выделения памяти написал, думаю борланд справиться)
C++
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#include <string.h>
#include <stdio.h>
 
//Выделяем память под наш текстовый блок
char str[64*1024];//длина вводимого текста не более 64*1024 символов
 
//Выделяем память под массив строк
char sMass[1024][64];//Работаем с двухмерным массивом
//максимальное число срок 1024, длина строки не более 64 символов
 
                //ФУНКЦИИ
//Функция ввода текста до тех пор пока не встретиться символ ch_end
char * enter_text(char * str, char ch_end);
//Выделение отдельной строки длиной sLen из текстового блока sBlock
//начиная с позиции iPos
char * get_string(char * sBlock, char * str, int iPos, int sLen);
//Равномерно распределяет пробелы между словами если
//их число вконце больше nSpaces
char * div_spaces(char * sBlock, int nSpaces);
//Возвращает строку без пробелов вначале
char * skip_spaces(char * str);
//Вставляет подстроку ins в строку str с позиции iPos
char * str_insert(char * str, int iPos, char * ins);
//Проверка того что строка состоит полностью из пробелов
bool is_null_str(char * str);
 
void main()
{
    printf("\tEnter text block\r\n");
    strcpy(str,enter_text(str, '\n'));
    printf("\tEnter length of 1 string\r\n");
    int sLen = -1;scanf("%d",&sLen);
    int nStr = strlen(str) / sLen + 1;
    printf("\tStrings after dividing input text\r\n");
    //Формируем массив строк sMass
    for(int i = 0,iAdd = 0; i < nStr; i++)
    {
        strcpy(sMass[i],get_string(str, sMass[i], iAdd, sLen));
        iAdd += strlen(sMass[i]);
        printf("\t[%02d] :\r\n",i + 1);
        printf("->%s<-\r\n",sMass[i]);
        //Строка с перераспределёнными пробелами
        //Если строка полностью состоит из пробелов
        //её преобразование не производим
        printf("->%s<-\r\n",is_null_str(sMass[i]) ? sMass[i] : div_spaces(sMass[i], 3));
        //Примечание
        //Если исходные строки не нужны то можно
        //записать так sMass[i] = div_spaces(sMass[i], 3);
        if(strlen(str) <= iAdd)
            break;
    }
    printf("Num of strings : %d\r\n", (nStr = i + 1));
    printf("Press NUM1 to enter new text block\r\n");
    scanf("%d",&sLen);getchar();str[0] = '\0';
    if(sLen == 1)
        main();
}
 
char * enter_text(char * str, char ch_end)
{
    int sLen = 0;
    if(str)
    {
        while((str[sLen] = getchar()) != ch_end)
            sLen++;
        str[sLen - 1] = '\0';
    }
    return str;
}
 
char * get_string(char * sBlock, char * str, int iPos, int sLen)
{
    if(sBlock != NULL && str != NULL)
    {
        for(int i = iPos; i < iPos + sLen; i++)
            str[i - iPos] = sBlock[i];
        //Проверяем содержит ли строка пробелы
        //При этом мы не должны учитывать пробелы
        //которые идут вначале строки перед словом
        //т.е необходимо выбросить начальные пробелы
        char * chBuf = strchr(str,' ');
        if(str[0] == ' ')
        while(*chBuf)
        {
            if(chBuf[0] != ' ')
                break;
            chBuf++;
        }
        bool IsSpaces = false;
        //Проверка данного условия необходима 
        //для случая попадания в середину слова, 
        //при этом если строка не содержит пробелов
        //т.е. состоит из 1-го слова
        //то необходимо докопировать слово в строку
        //иначе отбросить лишние символы
 
        //Зададимся строкой "строка символов"
        //Пример 1: - строка из 1 слова попали в его середину
        //пусть длина подстроки 4 символа тогда
        //
        //подстрока = "стро" - в этом случае надо докопировать
        //оставшуюсячасть слова, т.е. подстрока = "строка"!!!
        //
        //Пример 2: - строка из 2 слов попали в символы 2-го
        //пусть длина подстроки 8 символов тогда
        //
        //подстрока = "строка с" - в этом случае надо отступить
        //назад до пробела, т.е. подстрока = "строка"!!!
        if(*chBuf)
        if(strchr(chBuf,' '))
            IsSpaces = true;
        
        //Если строка оканчивается посередине слова, 
        //то отбрасываем слово, путём сдвига обратно
        //одновременно уменьшая длину строки
        while(*(sBlock + i))
        {
            str[i - iPos] = sBlock[i];
            if(sBlock[i] == ' ')
                break;
            if(IsSpaces)
                i--;
            else
                i++;
        }
        str[i - iPos] = '\0';
    }
    return str;
}
 
char * div_spaces(char * sBlock, int nSpaces)
{
    if(sBlock != NULL)
    {
        int nCount = 0,sLen = strlen(sBlock);
        char * chBuf = strrchr(sBlock,' ');
        //Вычисляем число пробелов вконце
        //для этого находим последний пробел в строке
        //и последовательно отступаем на символ назад
        //до того как предыдущий символ станет не пробелом
        if(chBuf)
        {
            //Также необходимо учесть что последний пробел должен
            //также являться последним символом строки!!!
            //В противном случае мы будем подсчитывать количество
            //пробелов в каком нибудь промежутке в середине слова
            if(strlen(chBuf) == 1)
            while((chBuf - nCount) != NULL)
            {
                nCount++;
                if(*(chBuf - nCount) != ' ')
                    break;
            }
        }
        if(nSpaces < nCount)
        {
            int nBlocks = 0;
            int sPos[64];
            chBuf = skip_spaces(sBlock);
            while(chBuf != NULL)
            {
                //Записываем в массив позиции промежутков между словами
                sPos[nBlocks] = strlen(sBlock) - strlen(chBuf);
                if(chBuf = skip_spaces(chBuf + sPos[nBlocks]))
                    chBuf = strchr(chBuf,' ');
                //Переставил nBlocks++; т.к. в случае досрочного выхода
                //из цикла операция инкремента не выполнялась nBlocks++
                //в результате возникали ситуации когда nBlocks = 0
                //и при выходе из цикла в выражении nAdd = (nCount - nSpaces)/nBlocks
                //было деление на нуль, что вызывало ошибку
                nBlocks++;
                if(chBuf == NULL)
                    break;
            }
            int nAdd = (nCount - nSpaces)/nBlocks;
            //Если пробелов вконце строки не хватает для добавления
            //во все промежутки между слвами, например слов 5 а
            //лишних пробелов от 1-го до 5-ти
            if(nAdd < 1)
            {
                while(nAdd < 1)
                {
                    nBlocks--;
                    //Это случай нескольких слов в строке и всего
                    //1-го лишнего пробела вконце
                    if(nBlocks == 0)
                    {
                        nAdd = (nCount - nSpaces);
                        break;
                    }
                    nAdd = (nCount - nSpaces)/nBlocks;
                }
                nBlocks = nAdd/(nCount - nSpaces);
            }
            //Случай всего 1-го слова в строке, в этом случае удваиваем
            //nAdd и данные проблеы добавляем с позиции sPos[0], т.е перед словом
            if(nBlocks == 2 && is_null_str(sBlock + sPos[nBlocks - 1] + 1))
            {
                nAdd    *= 2;
                nBlocks--;
            }
            while(0 < nBlocks)
            {
                nBlocks--;
                sBlock = str_insert
                (
                    sBlock,
                    sPos[nBlocks],
                    &sBlock[strlen(sBlock) - nAdd]
                );
                //Обрезаем строку, т.к. нам необходима лишь 
                //перестановка внутри sBlock, т.е
                //Например :
                //sBlock = "строка12", необходимо переставить подстроку "12"
                //на позицию 0
                //после str_insert получаем вставку "12" в, т.е sBlock = "12строка12", 
                //для перестановки необходимо убрать символы "12" вконце строки
                sBlock[sLen] = '\0';
            }
        }
    }
    return sBlock;
}
 
char * skip_spaces(char * str)
{
    int i = 0;
    if(str != NULL)
    {
        while((str + i) != NULL)
        {
            if(str[i] != ' ')
                break;
            i++;
        }
    }
    return (str + i);
}
 
char * str_insert(char * str, int iPos, char * ins)
{
    if(*str && *ins)
    {
        int sLen = strlen(str);
        int nAdd = strlen(ins);
        //В случае перекрывания элементов строк str и ins
        //при перестановке символов внутри str возможно
        //изменение символов ins!!!
        //Например :
        //строка12, необходимо переставить подстроку "12"
        //на позицию 0, тогда после цикла 
        //  for(i = sLen + nAdd - 1; iPos + nAdd <= i; i--)
        //произойдёт следующее :
        //str = "стстрока"
        //ins = "ка" 
        //для избежания этого вводим дополнительную строку sIns
        /////////////////////////////////////////////////////////
        char sIns[64];
        for(int i = 0;i < nAdd; i++)
            sIns[i] = ins[i];
        /////////////////////////////////////////////////////////
        if(iPos < sLen)
        {
            for(i = sLen + nAdd - 1; iPos + nAdd <= i; i--)
                str[i] = str[i - nAdd];
            for(i = iPos; i < iPos + nAdd;i++)
                str[i] = sIns[i - iPos];
        }
    }
    return str;
}
 
bool is_null_str(char * str)
{
    bool RetVal = true;
    if(str != NULL)
    {
        int sLen = strlen(str);
        for(int i = 0; i < sLen; i++)
            if(str[i] != ' ')
                RetVal = false;
    }
    return RetVal;
}
Миниатюры
Разбиение произвольного текста на строки указанной длины  
Вложения
Тип файла: txt text_block.txt (82 байт, 19 просмотров)
StereoMuse
0 / 0 / 0
Регистрация: 18.11.2011
Сообщений: 9
06.05.2013, 18:36     Разбиение произвольного текста на строки указанной длины #5
-=ЮрА=-, Большое спасибо за готовый код, нет ли у Вас его на языке C++ ?
Yandex
Объявления
06.05.2013, 18:36     Разбиение произвольного текста на строки указанной длины
Ответ Создать тему
Опции темы

Текущее время: 14:59. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru