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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 25, средняя оценка - 4.84
Gooman
10 / 10 / 0
Регистрация: 03.10.2010
Сообщений: 350
#1

Функция getline не считывает пробелы - C++

04.02.2012, 13:41. Просмотров 3385. Ответов 23
Метки нет (Все метки)

Написал код программы для вывода из файла строк, где есть двузначные цифры. Пользовался функцией getline. Но указанные в процессе работы программы строки выводятся "слипшиеся" - без пробелов.

Вот код программы:

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
#include "stdafx.h"
#include "iostream"
#include "fstream"
//#include "stdio.h"
using namespace std;
 
int _tmain(int argc, _TCHAR* argv[])
{
    // создание входного потока и открытие файла
    ifstream fin("c:\\projects\\text1.txt", ios::in);
    if (!fin)
    {
        cout << "Can't open input file" << endl;
        system("pause");
        return -1;
    } 
 
    char buf[255];
    char lim;
    int i = 0;
    while (!fin.eof())      // пока не конец файла
    {
        i = 0;
        cout<<endl;
        fin.getline(buf, 255, lim = '\n');  // считать одну строку
        while (buf[i])                      // рассмотреть каждый символ этой строки
        {
            if (buf[i] >= '1' && buf[i] < '100')    // если текущий символ - двузначная цифра
                cout << buf[i];                     // то начать выводить эту строку посимвольно
            i++;                                    // перепестить индекс массива buf вперед
        }
    }
    
    fin.close();
    fout.close();
    cout << endl;
    cout << endl;
    system("pause");
    return 0;
}
Можете подсказать, как с помощью этой функции считывать и пробелы. Или может другая функция существует?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.02.2012, 13:41
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Функция getline не считывает пробелы (C++):

Функция getline считывает несколько строк из файла, игнорируя символ новой строки - C++
Всем доброго дня! В С++ я новичок, сам себе придумываю задачки, просто для тренировки. Столкнулся с непонятным для меня поведением...

Getline не считывает строку целиком - C++
getline в string не хочет считывать полностью строку, а только до первого пробела. #include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include...

Почему stream.getline считывает до пробела? - C++
Задание: удалить все адреса изображений в html-файле (в теге img значение атрибута src заменить на пустое). void...

Некорректно считывает структуру с cin.getline - C++
вопрос про cin.getline когда ввожу спомощью cin.getline после 1ого ввода с нажатием &quot;в&quot; пропускается ввод 1 элемента структуры(имя) и...

Почему getline не считывает строку при первом проходе цикла? - C++
В данной функции: void ArrayStr::InputArr(void) { cout &lt;&lt; &quot;Введите строки длинной не более &quot; &lt;&lt; range &lt;&lt; &quot; символов: \n&quot;; for...

Программа не считывает пробелы - C++
Программа воспринимает текст только до пробела, если поставил пробел игнорирует. Думаю проблема в этой строчке. cin.get(); ...

23
Gooman
10 / 10 / 0
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 16:08  [ТС] #16
Цитата Сообщение от Kastaneda Посмотреть сообщение
Языков С/С++.
isdigit()

Добавлено через 3 минуты

Угу, тогда смотри еще предыдущий символ)
Хотя, в задании не сказано, что должны в строке быть только двузначные цифры. Написано, что "только те строки, где есть двузначные цифры". Значит, там могут быть и двухзначные, и трехзначные одновременно. Раз isdigit есть даже с C, то буду пользоваться ей.
0
Kastaneda
Форумчанин
Эксперт С++
4655 / 2863 / 228
Регистрация: 12.12.2009
Сообщений: 7,275
Записей в блоге: 2
Завершенные тесты: 1
04.02.2012, 17:38 #17
Цитата Сообщение от Gooman Посмотреть сообщение
Хотя, в задании не сказано, что должны в строке быть только двузначные цифры. Написано, что "только те строки, где есть двузначные цифры". Значит, там могут быть и двухзначные, и трехзначные одновременно.
Да. Я твое замечание понял по другому, а ты мое не понял.

Цитата Сообщение от Gooman Посмотреть сообщение
И если там break поставить, то строка дальше смотреться не будет. Т.е. если встретили где-то в первом месте число 25, прервали цикл. А в той же строке дальше может идти число 325. Получается, что выведется ненужная строка.
Смотри, в строке может быть число 325, тогда когда i будет указывать на 3, то good_str будет 0, а i увеличится на 1. При следующей итерации i будет указывать на 2, далее будет идти 5 а потом например пробел и good_str станет равным 1, как будто это двузначное число, хотя это не так. Поэтому нужно смотреть еще предыдущий символ, чтоб он не был цифрой.

Добавлено через 1 час 25 минут
Если компилятор с поддержкой С++11, то можно сделать так:
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 <iostream>
#include <fstream>
#include <string>
#include <regex>
 
int main()
{
    std::string file_name("main.cpp");
    std::ifstream in(file_name);
    if (!in) {
        std::cout << "Can't open file " << file_name << std::endl;
        return 1;
    }
 
    std::string str;
    std::regex pattern("(^|[^0-9])[0-9]{2}(?![0-9])");
 
    while (std::getline(in, str)) {
        if (std::regex_search(str.begin(), str.end(), pattern)) {
            std::cout << str << std::endl;
        }
    }
 
    return 0;
}
не часто пользуюсь регулярками, поэтому подозреваю, что шаблон можно сделать более красиво
0
Gooman
10 / 10 / 0
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 17:40  [ТС] #18
Kastaneda, я вообще пользовался только СИ, а это углубленный с++ какой-то. Мне ведь стандартными средствами с++ надо сделать.
0
Том Ардер
Модератор
Эксперт по математике/физике
3753 / 2366 / 296
Регистрация: 15.06.2009
Сообщений: 4,242
04.02.2012, 17:47 #19
Цитата Сообщение от Kastaneda Посмотреть сообщение
Смотри, в строке может быть число 325, тогда когда i будет указывать на 3, то good_str будет 0, а i увеличится на 1. При следующей итерации i будет указывать на 2, далее будет идти 5 а потом например пробел и good_str станет равным 1, как будто это двузначное число, хотя это не так. Поэтому нужно смотреть еще предыдущий символ, чтоб он не был цифрой.
Это тоже не спасает: для цифры 5 надо смотреть уже два предыдущих символа.
Выход в другом: считать количество цифр

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
char buf[256], *pbuf = buf;
bool good_str = false;
 
while( *pbuf && !good_str )
{
    int ndigits = 0;
    char pdig = pbuf;
 
    while( isdigit(*pdig) )
    {
        pdig++;
    }
 
    ndigits = pdig - pbuf;  // pdig или =pbuf, или указывает на символ после последней цифры
 
    good_str = ndigits == 2;
 
    pbuf += ndigits + 1;  // пропустить число или перейти к следующему символу
}
0
Kastaneda
Форумчанин
Эксперт С++
4655 / 2863 / 228
Регистрация: 12.12.2009
Сообщений: 7,275
Записей в блоге: 2
Завершенные тесты: 1
04.02.2012, 17:55 #20
Цитата Сообщение от Том Ардер Посмотреть сообщение
Это тоже не спасает: для цифры 5 надо смотреть уже два предыдущих символа.
Одного предыдущего символа и двух следующих будет достаточно, т.к. если число из 3х и более цифр, то строка уже не подходит.
0
Gooman
10 / 10 / 0
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 17:56  [ТС] #21
Цитата Сообщение от Kastaneda Посмотреть сообщение
Одного предыдущего символа и двух следующих будет достаточно, т.к. если число из 3х и более цифр, то строка уже не подходит.
Нет. Если в строке есть хоть одно двухзначное число, то она подходит.
0
Kastaneda
Форумчанин
Эксперт С++
4655 / 2863 / 228
Регистрация: 12.12.2009
Сообщений: 7,275
Записей в блоге: 2
Завершенные тесты: 1
04.02.2012, 17:56 #22
если писать в стиле "С", то я бы сделал через конечный автомат.
0
Gooman
10 / 10 / 0
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 17:57  [ТС] #23
В общем, я вот так написал:

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
while (!fin.eof())      // пока не конец файла
    {
        good_str = 0;
        i = 0;
        cout<<endl;
        fin.getline(buf, 255, lim = '\n');  // считать одну строку
        while (buf[i])  // рассмотреть каждый символ этой строки 
        { 
            if (isdigit(buf[i]))        // если текущее число - цифра
                //if (isdigit(buf[i+1]) && (i+1) <= 255)    // если последующий символ тоже цифра
                if (isdigit(buf[i+1]))
                    //if (!isdigit(buf[i+2]) && (i+2) <= 255)
                    if (!isdigit(buf[i+2]))
                    {
                        good_str = 1;
                        break;
                    }
                    else 
                    {
                        good_str = 0;
                    }
            i++;
        } 
        if (good_str)
        {
           cout << buf << endl;
           //fout << buf << endl;
        }
    }
Но оно выводит и строки, где есть только трехзначные и более числа.
0
Kastaneda
Форумчанин
Эксперт С++
4655 / 2863 / 228
Регистрация: 12.12.2009
Сообщений: 7,275
Записей в блоге: 2
Завершенные тесты: 1
04.02.2012, 18:37 #24
Цитата Сообщение от Gooman Посмотреть сообщение
Нет. Если в строке есть хоть одно двухзначное число, то она подходит.
Да, я не правильно выразился. Но если мы смотрим в настоящий момент 3х и более значное число, то нет необходимости смотреть 2 предыдущих символа, одного достаточно.

Конечный автомат в стиле "С"
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
    char str[BUFSIZ];
    enum states {find_first, find_second, check_third};
    bool is_valid_str = false;
 
    while (in.getline(str, BUFSIZ)) {
        states state = find_first;
        int i = 0;
 
        while (str[i]) {
            switch(state) {
            case find_first:
                if (isdigit(str[i]) && (i > 0 ? !isdigit(str[i - 1]) : true)) {
                    state = find_second;
                }
                break;
            case find_second:
                if (isdigit(str[i])) {
                    if (str[i+1]) {
                        state = check_third;
                    } else {
                        is_valid_str = true;
                    }
                } else {
                    state = find_first;
                }
                break;
            case check_third:
                if (isdigit(str[i])) {
                    state = find_first;
                } else {
                    is_valid_str = true;
                }
                break;
            }
        
            if (is_valid_str) {
                std::cout << str << std::endl;
                is_valid_str = false;
                break;
            }
            ++i;
        }
    }
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.02.2012, 18:37
Привет! Вот еще темы с ответами:

Функция getline - C++
Добрый вечер. Очень долго пытался найти в чём проблема в работе программы-она выдавала немного не то значение,которые было необходимо.Ни...

Функция С++ getline() - C++
Здравствуйте! Скажите пожалуйста, каков смысл функции cin.getline(). Если не сложно,приведите пожалуйста пример.

Функция getline - C++
Делаю упражнение по С++ (консольное приложение). Необходимо считать строку, включая пробелы. Вот описание класса: class employee { ...

Не работает функция getline(); - C++
Помогите, после ввода в переменную int c не выполняется функция getline, программа ее просто пропускает. #include &lt;iostream&gt; using...


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

Или воспользуйтесь поиском по форуму:
24
Yandex
Объявления
04.02.2012, 18:37
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru