Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.98/196: Рейтинг темы: голосов - 196, средняя оценка - 4.98
3 / 3 / 0
Регистрация: 23.11.2011
Сообщений: 97
1

Чтение строки неизвестной длины

23.11.2011, 14:40. Показов 36998. Ответов 42
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
реализация на СИ

как прочитать строку неизвестной длины? Чтение должно быть не посимвольным. Строка вводиться вручную.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.11.2011, 14:40
Ответы с готовыми решениями:

Чтение из файла с пропуском комментария неизвестной длины
Всем привет. Подскажите, пожалуйста, можно ли как-то при чтении файла пропустить комментарий...

Чтение из файла строки неизвестной длинны
Здравствуйте. Стоит задача писать в файл строку неизвестной длинны, введенную с клавиатуры. А...

Массив символов неизвестной длины
Добрый утро/день/вечер. Дело такое: вводится строка состоящая из слов и чисел(целых), разделяют...

Ввод массива неизвестной длины
Добрый день! Уважаемые знатоки, вопрос скорее всего тривиальный, но тем не менее решения у меня...

42
Заблокирован
Автор FAQ
23.11.2011, 16:32 21
Author24 — интернет-сервис помощи студентам
Siend, что вы хотите реализовать - ввод с консоли или файловое чтение?
0
Заблокирован
23.11.2011, 16:34 22
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Siend, что вы хотите реализовать - ввод с консоли или файловое чтение?
Не запутывайте автора вопроса. Лучше сами разберитесь, как fgets работает с stdin
0
4043 / 2332 / 292
Регистрация: 03.02.2011
Сообщений: 5,066
Записей в блоге: 10
23.11.2011, 16:37 23
5 копеек:
fgets
function
<cstdio>
char * fgets ( char * str, int num, FILE * stream );
Get string from stream

Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or a the End-of-File is reached, whichever comes first.
A newline character makes fgets stop reading, but it is considered a valid character and therefore it is included in the string copied to str.
A null character is automatically appended in str after the characters read to signal the end of the C string.

Parameters
str
Pointer to an array of chars where the string read is stored.
num
Maximum number of characters to be read (including the final null-character). Usually, the length of the array passed as str is used.
stream
Pointer to a FILE object that identifies the stream where characters are read from.
To read from the standard input, stdin can be used for this parameter.
0
3 / 3 / 0
Регистрация: 23.11.2011
Сообщений: 97
23.11.2011, 16:45  [ТС] 24
-=ЮрА=-, с консоли, и Сыроежка прав, можно просто указать входной поток заместо файла, но меня ломает ради простого ввода строки так извращаться. не дорос я еще до высот программирования, поэтому вариант Юры мне очень приемлем)

Добавлено через 1 минуту
Пишу вообще под линукс, и помимо этого ввода еще нужно сделать обработчик сигналов и т.п. - там много всего) поэтому усложнять не хочется)
0
Заблокирован
Автор FAQ
23.11.2011, 16:53 25

Не по теме:

Сыроежка, я сейчас не способен вам достойно ответить ввиду 3-х кратного бана
я прекрасно знаю что такое fgets(str,256,stdin); оставьте свои догадки о моём знании/не знании при себе. Вы один раз уже пострадали, наверное уроков никаких не извлекли...



Добавлено через 1 минуту
Цитата Сообщение от Siend Посмотреть сообщение
-=ЮрА=-, с консоли,
- ввиду этого свою помощь в топике считаю оконченной, как и говорил Siend, успешной вам здачи!
0
Заблокирован
23.11.2011, 17:06 26
Цитата Сообщение от Siend Посмотреть сообщение
-=ЮрА=-, с консоли, и Сыроежка прав, можно просто указать входной поток заместо файла, но меня ломает ради простого ввода строки так извращаться. не дорос я еще до высот программирования, поэтому вариант Юры мне очень приемлем)

Добавлено через 1 минуту
Пишу вообще под линукс, и помимо этого ввода еще нужно сделать обработчик сигналов и т.п. - там много всего) поэтому усложнять не хочется)
Я вам приведу альтернативный вариант

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
#include   <stdio.h>
#include   <stdlib.h>
#include   <string.h>
#include   <conio.h>
 
int main( void )
{
   int size = BUFSIZ;
   int n = 0;
   char *s = malloc( size );
 
   while ( fgets( s, BUFSIZ, stdin ) != NULL )
   {
      char *p = strchr( s + n, '\n' );
      if ( p != NULL )
      {
         n = p - s;
         break;
      }
      size += BUFSIZ - 1;
      n     += BUFSIZ - 1;
      s = realloc( s, size );
   }
 
   s[n] = '\0';
 
   puts( s );
 
   getch();
}
Может быть я допустил опечатки при наборе текста. но тем не менее код правильный.

Преимущество этого кода по сравнению с тем, что вам предложили состоит в том, что если будет введена строка, состоящая, к примеру, из 127 символов, то вместо выделения памяти 127 раз, как это делается в первоначально предоженном вам варианте, здесь память будет выделяться только один раз. Как говорится, почувствуйте разницу.
0
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
23.11.2011, 17:41 27
Цитата Сообщение от Сыроежка Посмотреть сообщение
C++
1
2
3
4
5
6
7
//...
   while ( fgets( s, BUFSIZ, stdin ) != NULL )
   {
      //...
      s = realloc( s, size );
   }
//...
Может быть я допустил опечатки при наборе текста. но тем не менее код правильный.
Не придираясь к тому, что нужно проверять результат вызова realloc(), что-то мне подсказывает, что на втором и следующих проходах fgets будет s с начала перезаписывать, при этом каждый раз честно увеличивая размер выделенной памяти...
0
2304 / 1225 / 246
Регистрация: 16.03.2008
Сообщений: 5,840
Записей в блоге: 2
23.11.2011, 17:49 28
еще ТСу надо учесть, что этот код под винду (у ТС линукс) - немного надо отредактировать
0
Заблокирован
23.11.2011, 17:51 29
Цитата Сообщение от easybudda Посмотреть сообщение
Не придираясь к тому, что нужно проверять результат вызова realloc(), что-то мне подсказывает, что на втором и следующих проходах fgets будет s с начала перезаписывать, при этом каждый раз честно увеличивая размер выделенной памяти...
Ну, это опечатка. Я даже удивляюсь, как она появилась. Должно быть

C++
1
   while ( fgets( s + n, BUFSIZ, stdin ) != NULL )
Для этого переменная n и вводилась.
0
Заблокирован
Автор FAQ
23.11.2011, 18:16 30
Siend, чтобы Вам было меньше возни, вот вам код аналогичный функционалу
Цитата Сообщение от Сыроежка Посмотреть сообщение
while ( fgets( s, BUFSIZ, stdin ) != NULL )
* *{
даже лучше(т.к аллокаем через каждые 1024 символов)
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
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    long i = 0, sLen = 0;//Áóäåò ñîäåðæàòü â ñåáå äëèííó ñòðîêè
    //Íà÷àëüíîå âûäåëåíèå ïàìÿòè âñåãî ïîä 1 ñèìâîë
    char ch, * str = (char *)malloc(1024*sizeof(char));
    printf("Enter string :\n");
    while((ch = getchar()) != '\n')
    {
        str[sLen] = ch;
        if(i < 1024)
            sLen++;
        else
        {
            str = (char *)realloc(str,(1 + (sLen += 1024))*sizeof(char));
            i = 0;
        }
    }
    str[sLen] = '\0';
    printf("Your input : \n");
    printf("%s\n",str);
    system("pause");//Ñòîï-òî÷êà èíà÷å ïðèëîæåíèå îòðàáîòàâ ñðàçó çàêðîåòñÿ
    return 0;
}
0
2304 / 1225 / 246
Регистрация: 16.03.2008
Сообщений: 5,840
Записей в блоге: 2
23.11.2011, 18:23 31
кто то забыл
C
1
 ++i
сделать

Хотя можно и без i
C
1
if ((sLen / 1024)==0)...
Пожалуй этот вариант будет лучше варианта с fgets где приходится использовать поиск в строке
0
-=ЮрА=-
23.11.2011, 18:25
  #32

Не по теме:

voral, я лишь показал что можно спокойно обойтись без fgets - далее как говориться дело техники...

0
Заблокирован
23.11.2011, 18:31 33
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Siend, чтобы Вам было меньше возни, вот вам код аналогичный функционалу
даже лучше(т.к аллокаем через каждые 1024 символов)
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
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    long i = 0, sLen = 0;//Áóäåò ñîäåðæàòü â ñåáå äëèííó ñòðîêè
    //Íà÷àëüíîå âûäåëåíèå ïàìÿòè âñåãî ïîä 1 ñèìâîë
    char ch, * str = (char *)malloc(1024*sizeof(char));
    printf("Enter string :\n");
    while((ch = getchar()) != '\n')
    {
        str[sLen] = ch;
        if(i < 1024)
            sLen++;
        else
        {
            str = (char *)realloc(str,(1 + (sLen += 1024))*sizeof(char));
            i = 0;
        }
    }
    str[sLen] = '\0';
    printf("Your input : \n");
    printf("%s\n",str);
    system("pause");//Ñòîï-òî÷êà èíà÷å ïðèëîæåíèå îòðàáîòàâ ñðàçó çàêðîåòñÿ
    return 0;
}
Я думаю, что в этом коде имеется логическая ошибка

C++
1
2
3
                str[sLen] = ch;
                if(i < 1024)
                        sLen++;
То есть если sLen == 1023, то на следующей итерации делается попытка записать значение в str[1024] Это конечно при условии, если бы переменная i изменялась. Но я не вижу, где она изменяется, поэтому в любом случае будет переполнение строки, если естестенно входная строка достаточно большая.
0
2304 / 1225 / 246
Регистрация: 16.03.2008
Сообщений: 5,840
Записей в блоге: 2
23.11.2011, 18:39 34
Может так
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main()
{
        const int bufSize = 10;
        long sLen = 0;//Будет содержать в себе длинну строки
        //Начальное выделение памяти всего под 1 символ
        char ch, * str = (char *)malloc(bufSize*sizeof(char));
        printf("Enter string :\n");
        while((ch = getchar()) != '\n')
        {
                str[sLen] = ch;
                                ++sLen;
                if ((sLen / bufSize)==1)
                {
                        str = (char *)realloc(str,(sLen + bufSize)*sizeof(char));
                }
        }
        str[sLen] = '\0';
        printf("Your input : \n");
        printf("%s\n",str);
        system("pause");//Стоп-точка иначе приложение отработав сразу закроется
        return 0;
}
Добавлено через 2 минуты
Упс точно
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main()
{
        const int bufSize = 10;
        long sLen = -1;//Будет содержать в себе длинну строки
        //Начальное выделение памяти всего под 1 символ
        char ch, * str = (char *)malloc(bufSize*sizeof(char));
        printf("Enter string :\n");
        while((ch = getchar()) != '\n')
        {
                ++sLen;
                if ((sLen / bufSize)==1)
                {
                        str = (char *)realloc(str,(sLen + bufSize)*sizeof(char));
                }
                str[sLen] = ch;
        }
        str[sLen] = '\0';
        printf("Your input : \n");
        printf("%s\n",str);
        system("pause");//Стоп-точка иначе приложение отработав сразу закроется
        return 0;
}
Добавлено через 1 минуту
bufSize конечно же лучше поставить больше 10
0
-=ЮрА=-
23.11.2011, 18:39
  #35

Не по теме:

Сыроежка, ну что мне тут вам доказывать, я накидал чтобы был понятен принцип, мне есть чем заняться и расстрачивать своё время не имею ни малейшего желания. Технические огрехи устранимы - важен принцип - аллокнули 1024, пока не заполнили их не аллокаем, заполнили добавили 1024 и всё...
PS:Я вас не трогаю вы сами лезете со своим я и оскорблениями именно в мой адрес(утверждайтесь например в помощи ТС-ам а не разборках)...

0
2304 / 1225 / 246
Регистрация: 16.03.2008
Сообщений: 5,840
Записей в блоге: 2
23.11.2011, 18:42 36
черт - не углядел при аллоке надо учесть что будет еще '\0' ну и если сразу нажмут ентер предусмотреть чтоб не в str[-1] отправляался ноль
0
Заблокирован
23.11.2011, 18:43 37
Цитата Сообщение от voral Посмотреть сообщение
Может так
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main()
{
        const int bufSize = 10;
        long sLen = 0;//Будет содержать в себе длинну строки
        //Начальное выделение памяти всего под 1 символ
        char ch, * str = (char *)malloc(bufSize*sizeof(char));
        printf("Enter string :\n");
        while((ch = getchar()) != '\n')
        {
                str[sLen] = ch;
                                ++sLen;
                if ((sLen / bufSize)==1)
                {
                        str = (char *)realloc(str,(sLen + bufSize)*sizeof(char));
                }
        }
        str[sLen] = '\0';
        printf("Your input : \n");
        printf("%s\n",str);
        system("pause");//Стоп-точка иначе приложение отработав сразу закроется
        return 0;
}
Добавлено через 2 минуты
Упс точно
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main()
{
        const int bufSize = 10;
        long sLen = -1;//Будет содержать в себе длинну строки
        //Начальное выделение памяти всего под 1 символ
        char ch, * str = (char *)malloc(bufSize*sizeof(char));
        printf("Enter string :\n");
        while((ch = getchar()) != '\n')
        {
                ++sLen;
                if ((sLen / bufSize)==1)
                {
                        str = (char *)realloc(str,(sLen + bufSize)*sizeof(char));
                }
                str[sLen] = ch;
        }
        str[sLen] = '\0';
        printf("Your input : \n");
        printf("%s\n",str);
        system("pause");//Стоп-точка иначе приложение отработав сразу закроется
        return 0;
}
Добавлено через 1 минуту
bufSize конечно же лучше поставить больше 10
У вас как раз первый вариант был лучше, так как не нужно было присваивать -1 sLen.

Вам просто нужно было (как, впрочем, и в вашем втором варианте) исправить код

C++
1
2
3
4
                if ((sLen / bufSize)==1)
                {
                        str = (char *)realloc(str,(sLen + bufSize)*sizeof(char));
                }
На

C++
1
2
3
4
                if ((sLen % bufSize) == 0 )
                {
                        str = (char *)realloc(str,(sLen + bufSize)*sizeof(char));
                }
1
Заблокирован
Автор FAQ
23.11.2011, 18:48 38
Думаю всё же лучше так
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
long i = 0, sLen = 0;//Áóäåò ñîäåðæàòü â ñåáå äëèííó ñòðîêè
    //Íà÷àëüíîå âûäåëåíèå ïàìÿòè âñåãî ïîä 1 ñèìâîë
    char ch, * str = (char *)malloc(1024*sizeof(char));
    printf("Enter string :\n");
    while((ch = getchar()) != '\n')
    {
        str[sLen + i] = ch;
        if(i < 1024)
            i++;
        else
        {
            str = (char *)realloc(str,(1024 + (sLen += 1024))*sizeof(char));
            i = 0;
        }
    }
    if(i < 1024)
        sLen += i;
    str[sLen] = '\0';
0
2304 / 1225 / 246
Регистрация: 16.03.2008
Сообщений: 5,840
Записей в блоге: 2
23.11.2011, 18:52 39
Цитата Сообщение от Сыроежка Посмотреть сообщение
Вам просто нужно было (как, впрочем, и в вашем втором варианте) исправить код
стоп. а какая разница? не не не. Имх код первый нормальный только не учтен последний \0.
надо все ж проверить. думаю достаточно при аллоке и реалоке еще +1 сделать.

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
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
        const int bufSize = 1024;
        long sLen = 0;//Будет содержать в себе длинну строки
        //Начальное выделение памяти всего под 1 символ
        char ch, * str = (char *)malloc((bufSize+1)*sizeof(char));
        printf("Enter string :\n");
        while((ch = getchar()) != '\n')
        {
                str[sLen] = ch;
                                ++sLen;
                if ((sLen / bufSize)==1)
                {
                        str = (char *)realloc(str,(sLen + bufSize+1)*sizeof(char));
                }
        }
        str[sLen] = '\0';
        printf("Your input : \n");
        printf("%s\n",str);
        system("pause");//Стоп-точка иначе приложение отработав сразу закроется
        return 0;
}



Т.е. заносим сивол в массив, потом увиличиваем длинну (он же индекс). Если индекс вышел на границу (т.е. уже не допустим) добавляем памяти. +1 в функциях с памятью дает резерв для \0
0
Заблокирован
Автор FAQ
23.11.2011, 18:57 40
voral, зачем
Цитата Сообщение от voral Посмотреть сообщение
if ((sLen / bufSize)==1)
?
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
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    long i = 0, sLen = 0;//Áóäåò ñîäåðæàòü â ñåáå äëèííó ñòðîêè
    //Íà÷àëüíîå âûäåëåíèå ïàìÿòè âñåãî ïîä 1 ñèìâîë
    char ch, * str = (char *)malloc(1024*sizeof(char));
    printf("Enter string :\n");
    while((ch = getchar()) != '\n')
    {
        str[sLen + i] = ch;
        if(i < 1024)
            i++;
        else
        {
            str = (char *)realloc(str,(1024 + (sLen += 1024))*sizeof(char));
            i = 0;
        }
    }
    if(i < 1024)
        sLen += i;
    str[sLen] = '\0';
    printf("Your input : \n");
    printf("%s\n",str);
    system("pause");//Ñòîï-òî÷êà èíà÷å ïðèëîæåíèå îòðàáîòàâ ñðàçó çàêðîåòñÿ
    return 0;
}
Enter string :
dsgfdg
Your input :
dsgfdg
Для продолжения нажмите любую клавишу . . .

Добавлено через 1 минуту
Если i < 1024 добавим это значение к sLen здесь
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
if(i < 1024)
* * * * * * * * sLen += i;
а так аллокаем
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
str = (char *)realloc(str,(1024 + (sLen += 1024))*sizeof(char));
предлагаю оттестировать, т.к мне уже нужно выходить...
0
23.11.2011, 18:57
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.11.2011, 18:57
Помогаю со студенческими работами здесь

Считывание массива неизвестной длины
Имеется набор чисел. Про их количество ничего заранее неизвестно, кроме того, что оно кратно 10....

Чтение строки неограниченной длины и её параллельная обработка
Здравствуйте. В ходе реализации алгоритма для поиска возникла проблема в том, что в условии...

Создание массива чисел неизвестной длины
Нужно сделать программу, которая считывает неизвестное наперёд количество чисел в массив. То есть...

Ввод массива заранее неизвестной длины
#include &lt;iostream&gt; #include &lt;math.h&gt; using namespace std; int main() { int arr, a = 0;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru