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

Оставить после знаков препинания только один пробел - C++

Восстановить пароль Регистрация
 
Glebordan
0 / 0 / 0
Регистрация: 07.04.2014
Сообщений: 36
06.07.2014, 23:03     Оставить после знаков препинания только один пробел #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
31
32
33
34
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdio.h>
#include <Windows.h>
#include <string>
using namespace std;
int _tmain (int argc, _TCHAR* argv[])
{   setlocale (LC_ALL, "RUS");
    FILE *fp = fopen("Текст.txt","r");
    if ( NULL == fp )
    {
    printf("Не удалось открыть файл.");
    return 0;
    }
    char s[1024]="";
    char pchars[] = ".,?!:";
    while (!feof(fp))
    {   fgets(s,1024,fp);
      for (int i = 0; s[i] != '\0'; i++)
      if (strchr(pchars,s[i]) != NULL)
      {
         for (int t = strlen(s); t>=i; t--)
         s[t+1] = s[t];
         s[i+1] = ' ';
      }
     
       
    }
    printf("%s",s);
    system("pause");
    fclose(fp);
    }
Хочу чтобы после знаков препинания оставался только один пробел, не понимаю почему, но их остаётся два. И не знаю как убирать лишние пробелы(Не только после разделителей).
Буду очень благодарен за помощь))
И ещё, чтобы новую тему не создавать, так же я хочу чтобы в тексте два повторяющихся слова(они идут друг за другом) заменялись на одно, как это реализовать(не обязательно придумывать код, просто подкиньте идейку )
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.07.2014, 23:03     Оставить после знаков препинания только один пробел
Посмотрите здесь:

C++ Вставить после каждого символа «.» один символ « » (пробел), если после точки нет пробела.
Удалить из файла все цифры, если они следуют после знаков препинания. C++
В строке, состоящей из слов и знаков препинания(пробел.:,!?-;),найти слово максимальной длины, не содержащее заданную букву C++
Оставить в строке только те символы, которые встречаются один раз C++
C++ Чтение из файла только букв и знаков препинания
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
SatanaXIII
Супер-модератор
Эксперт С++
 Аватар для SatanaXIII
5549 / 2563 / 233
Регистрация: 01.11.2011
Сообщений: 6,334
Завершенные тесты: 1
07.07.2014, 09:39     Оставить после знаков препинания только один пробел #2
Цитата Сообщение от Glebordan Посмотреть сообщение
И ещё, чтобы новую тему не создавать, так же я хочу чтобы в тексте два повторяющихся слова(они идут друг за другом) заменялись на одно
Лучше уж создать.

Цитата Сообщение от Glebordan Посмотреть сообщение
как это реализовать(не обязательно придумывать код, просто подкиньте идейку )
Создать какой-либо буфер. В него записать слово от разделителя до разделителя. При нахождении следующего слова сравнивать текущее слово и предыдущее. Если равны, то удалять текущее, если нет, то перезаписывать буфер.
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
07.07.2014, 10:53     Оставить после знаков препинания только один пробел #3
Хочу чтобы после знаков препинания оставался только один пробел, не понимаю почему, но их остаётся два. И не знаю как убирать лишние пробелы(Не только после разделителей).
Регулярными выражениями (std::regex/boost::regex). Искать что-то вроде R"(([\.,])\s{2,})" (искать точку/запятую+два и более пробела. Точку/запятую хомячить в $1), менять на "$1 " (найденное заменить на захомяченный знак препинания+пробел). Вообще, универсальный ответ на вопрос "как мне найти то-то и заменить на сё-то" - регулярные выражения.
Glebordan
0 / 0 / 0
Регистрация: 07.04.2014
Сообщений: 36
07.07.2014, 16:27  [ТС]     Оставить после знаков препинания только один пробел #4
А можете пример простенький дать для регулярных выражений, не совсем ясно как использовать...
nmcf
4303 / 3724 / 1255
Регистрация: 14.04.2014
Сообщений: 14,589
07.07.2014, 16:33     Оставить после знаков препинания только один пробел #5
Тебе нужно отказаться от преобразований внутри строки со всеми этими сдвигами. Сложно и не оптимально. Используй вторую строку, в которую переноси нужные символы, вставляя в процессе, если что-то требуется.
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
07.07.2014, 16:50     Оставить после знаков препинания только один пробел #6
А можете пример простенький дать для регулярных выражений, не совсем ясно как использовать...
Чего там может быть неясного?
C++
1
2
3
4
5
6
7
8
9
10
#include<iostream>
#include<boost/regex.hpp>
int main()
{
    boost::regex my_regex(R"(([\.,])\s{2,})");
    //boost::regex my_regex("([\\.,])\\s{2,}"); если компилятор не понимает C++11
    std::string some_text("A,      B.   C");
    std::cout<<boost::regex_replace(some_text,my_regex,"$1 ")<<std::endl;
    return 0;
}
Glebordan
0 / 0 / 0
Регистрация: 07.04.2014
Сообщений: 36
07.07.2014, 17:33  [ТС]     Оставить после знаков препинания только один пробел #7
Можете посоветовать какой-нибудь сайт где боле менее хорошо написано про регулярные выражения?=)

Добавлено через 15 минут
Попробовал перенести в другой массив символы, на выходе получаю исходный текст без изменений
что тут не так?
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
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdio.h>
#include <Windows.h>
#include <string>
 
using namespace std;
int _tmain (int argc, _TCHAR* argv[])
{   setlocale (LC_ALL, "RUS");
    FILE *fp = fopen("Текст.txt","r");
    if ( NULL == fp )
    {
    printf("Не удалось открыть файл.");
    return 0;
    }
    char s[1024]="";
    char b[1024]="";
    while (!feof(fp))
    {   fgets(s,1024,fp);}
    for(int i=0;s[i]!='\0';i++)
    {int t=0;
    if (s[i]==','||s[i]=='.'||s[i]=='!'||s[i]=='?')
    {b[t]=s[i];
     b[t+1]=' ';}
    else{b[t]=s[i]; }
        t++;
    }
    printf("%s",b);
    system("pause");
    fclose(fp);
    }
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
07.07.2014, 17:38     Оставить после знаков препинания только один пробел #8
Сам синтаксис описан на каждом углу начиная с Википедии. На http://www.pcre.ru/ есть форма через которую можно поиграться с выражениями ничего дополнительно не устанавливая. Хотя, я бы посоветовал освоить Перл в объеме "Hello, world!" и играться уже в Перле. Потому как регулярные выражения пошли именно оттуда и реализованы там удобнее всего.

Добавлено через 4 минуты
что я делаю не так?(((
int t=0; постоянно сбрасывает t в ноль.
Glebordan
0 / 0 / 0
Регистрация: 07.04.2014
Сообщений: 36
08.07.2014, 11:08  [ТС]     Оставить после знаков препинания только один пробел #9
Не получается всё равно, выдаёт исходный текст, почему-то он никак не реагирует на if

Добавлено через 40 минут
Как лучше всего разбить текст на слова? Я использовал strtok(), но что-то я сообразить потом не могу что с этими словами делать, как их занести в массив и уж тем более как сравнить со следующим словом?(
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
08.07.2014, 11:40     Оставить после знаков препинания только один пробел #10
Не получается всё равно, выдаёт исходный текст, почему-то он никак не реагирует на if
Реагирует. Просто обе ветки if выполняют один и тот же b[t]=s[i];. Вам нужно либо использовать регулярные выражения, либо реализовать ровно тот же алгоритм ручками.
1) Сравнить текст на позиции s[i] с шаблоном "любой знак препинания, два и более пробела". "Два и более пробела" через if не проверяется, нужно еще один вложенный цикл прикручивать и в нем пробелы считать.
2) Совпало с шаблоном - в b[t] кидаются знак препинания И пробел. i сдвигается в конец совпадения (в позицию после "два и более пробела"). t увеличивается на два.
3) Не совпало - сдвинуть i на один символ.
4) Вернуться к пункту 1.
Короче, чем это кодить, быстрее и нагляднее воткнуть рекексп.
Как лучше всего разбить текст на слова?
Найти все совпадения строки с регулярным выражением \w+. Если проблемы с русским, то [a-zA-Zа-яА-Я]+. Ну или смотри выше - "реализовать ровно тот же алгоритм ручками".
Glebordan
0 / 0 / 0
Регистрация: 07.04.2014
Сообщений: 36
08.07.2014, 11:53  [ТС]     Оставить после знаков препинания только один пробел #11
Попробую сделать вручную...

Добавлено через 1 минуту
Проблема в том, что мой компилятор не принимает регулярные выражения...
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
08.07.2014, 12:06     Оставить после знаков препинания только один пробел #12
Попробуй вместо boost #include<regex> с заменой boost:: на std::. Проблема в том что в зависимости от свежести компилятора, реализация штатного regex может оказаться кастрированной. Поэтому дополнительно установленный boost как-то надежнее.
Glebordan
0 / 0 / 0
Регистрация: 07.04.2014
Сообщений: 36
08.07.2014, 12:41  [ТС]     Оставить после знаков препинания только один пробел #13
Попробовал как вы сказали, принимать стал, начал компилировать появилась ошибка:
"отсутствуют экземпляры перегруженная функция "std::regex_replace", соответствующие списку аргументов"
Почитал, что возможно она из-за того что напутал со скобками, проверил, ошибок вроде нет...
Вот часть кода:
C++
1
2
3
 regex Poisk("([\\.,])\\s{1, }");
     string s;
     cout<<std::regex_replace(s,Poisk,"$1 ")<<endl;
Renji
1535 / 983 / 240
Регистрация: 05.06.2014
Сообщений: 2,963
08.07.2014, 13:00     Оставить после знаков препинания только один пробел #14
Замените "$1 " на std::string("$1 "), должно помочь.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.07.2014, 14:48     Оставить после знаков препинания только один пробел
Еще ссылки по теме:

C++ В строке, состоящей из слов и знаков препинания (пробел . : , ! ?-;), найти слово максимальной длины
Добавить в строку пробелы после знаков препинания, если они там отсутствуют C++
C++ Из каждой группы равных между собой элементов массива нужно оставить только один

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

Или воспользуйтесь поиском по форуму:
Glebordan
0 / 0 / 0
Регистрация: 07.04.2014
Сообщений: 36
08.07.2014, 14:48  [ТС]     Оставить после знаков препинания только один пробел #15
К моему величайшему сожалению, не помогло(
Yandex
Объявления
08.07.2014, 14:48     Оставить после знаков препинания только один пробел
Ответ Создать тему
Опции темы

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