10 / 10 / 4
Регистрация: 03.10.2010
Сообщений: 350
1

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

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

Author24 — интернет-сервис помощи студентам
Написал код программы для вывода из файла строк, где есть двузначные цифры. Пользовался функцией 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.02.2012, 13:41
Ответы с готовыми решениями:

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

Getline() не считывает
void Anket::Add() //Функция добавления элементов в список { profile *temp = new profile; cout...

Getline не считывает строку целиком
getline в string не хочет считывать полностью строку, а только до первого пробела. #include...

Не считывает одну строку из файла с getline()
string s; char l; ifstream file1; file1.open(&quot;in_1.dat&quot;, ios::in); cout &lt;&lt; &quot;ФАЙЛ...

23
Псевдослучайный
1946 / 1145 / 98
Регистрация: 13.09.2011
Сообщений: 3,215
04.02.2012, 13:49 2
Цитата Сообщение от Gooman Посмотреть сообщение
buf[i] < '100'
Здесь ты неправ.
0
10 / 10 / 4
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 13:50  [ТС] 3
Цитата Сообщение от NoMasters Посмотреть сообщение
Здесь ты неправ.
Я знаю. Исправить нет проблем. Но как же считывать пробелы?!
0
Псевдослучайный
1946 / 1145 / 98
Регистрация: 13.09.2011
Сообщений: 3,215
04.02.2012, 14:00 4
Всё должно считываться, но в соответствии с if пробелы не выводятся.
0
10 / 10 / 4
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 14:01  [ТС] 5
Цитата Сообщение от NoMasters Посмотреть сообщение
Всё должно считываться, но в соответствии с if пробелы не выводятся.
Спасибо, теперь понятно. Буду исправлять.
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,112
Записей в блоге: 2
04.02.2012, 14:03 6
Gooman, это же не компилируемый код! Покажи в том виде, в котором компилируешь. А проблема не с считываением, а с выводом.

Добавлено через 36 секунд
опоздал
0
10 / 10 / 4
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 14:03  [ТС] 7
Цитата Сообщение от Kastaneda Посмотреть сообщение
Gooman, это же не компилируемый код! Покажи в том виде, в котором компилируешь. А проблема не с считываением, а с выводом.
У меня это компилируемый код. В этом самом виде и компилирую.
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,112
Записей в блоге: 2
04.02.2012, 14:06 8
Цитата Сообщение от Gooman Посмотреть сообщение
У меня это компилируемый код. В этом самом виде и компилирую.
fout в stdafx.h чтоли объявлен?
0
10 / 10 / 4
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 15:09  [ТС] 9
Цитата Сообщение от Kastaneda Посмотреть сообщение
fout в stdafx.h чтоли объявлен?
Нужно убрать строчку с закрытием файла fout.

Добавлено через 1 час 0 минут
Кто-нибудь может помочь? Уже по-разному пробовал и остановился на таком вот варианте. Но ничего не выводится.
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
#include "stdafx.h"
#include "iostream"
#include "fstream"
//#include "stdio.h"
using namespace std;
 
void readfile (char *buf, ifstream fin); // считывает содержимое файла в массив литер buf
 
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;
    } 
 
    // создание выходного потока и открытие файла
    ofstream fout("c:\\projects\\text2.txt", ios::out);
    if(!fout)
    {
        cout << "Can't create output file" << endl;
        system("pause");
        return -1;
    }
 
    char buf[255];
    char lim;
    int i = 0;
    int good_str = 0; // 1, если строка содержит только двузначные цифры
    while (!fin.eof())      // пока не конец файла
    {
        good_str = 0;
        i = 0;
        cout<<endl;
        fin.getline(buf, 255, lim = '\n');  // считать одну строку
        while (buf[i])                      // рассмотреть каждый символ этой строки
        {
            if (buf[i] == '\n')
                continue;
 
            if (buf[i] >= '1' && buf[i] <= '9')             // если текущий символ - цифра
                if (buf[i+1] >= '0' && buf[i+1] <= '9')     // если следующий символ тоже цифра
                    if (buf[i+2] >= '0' && buf[i+2] <= '9') // если и  третий символ - цифра
                        good_str = 0;    // то строка нам не подходит
                    else 
                        good_str = 1;    // иначе число имеет 2 знака, строка подходит.
 
            else
                good_str = 0;
 
            i++;                                    // переместить индекс массива buf вперед
        }
        if (good_str)
            cout << buf;            
    }
    
 
    fin.close();
    fout.close();
    cout << endl;
    cout << endl;
    system("pause");
    return 0;
}
А если убрать строки 51 и 52, то начинает хоть что-то выводиться. Однако выводятся и строки, где есть трехзначные цифры. Что нужно исправить, помогите, пожалуйста
Напомню задание: мне надо было записать в другой файл (вывести на экран) строки, где есть только двухзначные цифры. Ну в строках, естественно, не только цифры, а просто предложения любые.
0
Эксперт по математике/физике
4217 / 3412 / 396
Регистрация: 15.06.2009
Сообщений: 5,818
04.02.2012, 15:39 10
Цитата Сообщение от Gooman Посмотреть сообщение
двузначные цифры
Цифры и Числа - суть разные вещи
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool good_str = false;
while (buf[i] && !good_str)  // рассмотреть каждый символ этой строки 
{ 
  if ( buf[i] == '\n')
     continue; 
  good_str = isdigit(buf[i]) && isdigit(buf[i+1]) && !isdigit(buf[i+2]);  // именно двузначное число
  i++;
} 
 
if (good_str)
{
   cout << buf << endl;
   fout << buf<< endl;
}
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,112
Записей в блоге: 2
04.02.2012, 15:53 11
Цитата Сообщение от Gooman Посмотреть сообщение
А если убрать строки 51 и 52, то начинает хоть что-то выводиться. Однако выводятся и строки, где есть трехзначные цифры. Что нужно исправить, помогите, пожалуйста
Когда находишь нужную строку, добавь выход из цикла while(), т.е.
C++
1
2
3
4
 else {
   good_str = 1;    // иначе число имеет 2 знака, строка подходит.
   break;
}
иначе строка смотриться дальше и значение good_str скорее всего меняется.
Еще перед просмотром очередного символа проверь, является ли i валидным, т.е. ну будет ли выхода за пределы массива. Если i будет равно strlen(buf)-1, то в условии if(buf[i + 2] ...) будет выход за пределы массива.

Еще нет смысла проверять является ли текущий символ символом '\n', т.к. getline() не записывает его в строку.

Так же советую использовать фигурные скобки во всех if'ах (а так же в for'ах и while'ях). Это придает бОльшую читабельность и позволяет легко редактировать код.
Например в 51 строке создается впечатление, что else относится к if'у из 44 строки, а в действительности из 45ой (хотя это скорее вопрос правильного форматирования кода)
0
10 / 10 / 4
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 15:58  [ТС] 12
Том Ардер, ну вы очень легко поступили, пользуясь встроенной нестандартной функцией. А как без нее сделать?
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,112
Записей в блоге: 2
04.02.2012, 16:00 13
Цитата Сообщение от Gooman Посмотреть сообщение
пользуясь встроенной нестандартной функцией
Это стандартная функция. Кстати в коде Том Ардер занчение i тоже не проверяется.
0
10 / 10 / 4
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 16:00  [ТС] 14
Цитата Сообщение от Kastaneda Посмотреть сообщение
Это стандартная функция. Кстати в коде Том Ардер занчение i тоже не проверяется.
Стандартная функция чего? Visual studio?
И если там break поставить, то строка дальше смотреться не будет. Т.е. если встретили где-то в первом месте число 25, прервали цикл. А в той же строке дальше может идти число 325. Получается, что выведется ненужная строка.
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,112
Записей в блоге: 2
04.02.2012, 16:07 15
Цитата Сообщение от Gooman Посмотреть сообщение
Стандартная функция чего? Visual studio?
Языков С/С++.
isdigit()

Добавлено через 3 минуты
Цитата Сообщение от Gooman Посмотреть сообщение
И если там break поставить, то строка дальше смотреться не будет. Т.е. если встретили где-то в первом месте число 25, прервали цикл. А в той же строке дальше может идти число 325. Получается, что выведется ненужная строка.
Угу, тогда смотри еще предыдущий символ)
0
10 / 10 / 4
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 16:08  [ТС] 16
Цитата Сообщение от Kastaneda Посмотреть сообщение
Языков С/С++.
isdigit()

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

Угу, тогда смотри еще предыдущий символ)
Хотя, в задании не сказано, что должны в строке быть только двузначные цифры. Написано, что "только те строки, где есть двузначные цифры". Значит, там могут быть и двухзначные, и трехзначные одновременно. Раз isdigit есть даже с C, то буду пользоваться ей.
0
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,112
Записей в блоге: 2
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
10 / 10 / 4
Регистрация: 03.10.2010
Сообщений: 350
04.02.2012, 17:40  [ТС] 18
Kastaneda, я вообще пользовался только СИ, а это углубленный с++ какой-то. Мне ведь стандартными средствами с++ надо сделать.
0
Эксперт по математике/физике
4217 / 3412 / 396
Регистрация: 15.06.2009
Сообщений: 5,818
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
5231 / 3204 / 362
Регистрация: 12.12.2009
Сообщений: 8,112
Записей в блоге: 2
04.02.2012, 17:55 20
Цитата Сообщение от Том Ардер Посмотреть сообщение
Это тоже не спасает: для цифры 5 надо смотреть уже два предыдущих символа.
Одного предыдущего символа и двух следующих будет достаточно, т.к. если число из 3х и более цифр, то строка уже не подходит.
0
04.02.2012, 17:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.02.2012, 17:55
Помогаю со студенческими работами здесь

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

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

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

Программа не считывает пробелы
Программа воспринимает текст только до пробела, если поставил пробел игнорирует. Думаю проблема в...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

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