Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Замена пробелов String.h 
V
    Опции темы
Winterlord
Дата 15.3.2009, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Добрый вечер, уважаемые программисты! Борланд С++ изучаю сравнительно не долго, соответственно и опыта пока что маловато;) Обращаюсь к вам за помощью, хотелось бы, чтоб вы подкинули идейку, надоумили на решение.

Задача такая: Преобразовать заданную строку следующим образом: заменить все внутренние группы пробелов одним пробелом.

Всё это делается при помощи функций библиотеки string.h. С файла в массив фиксированной длины считывается строка с символами, все действия с элементами массива проводятся через указатели.

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

Код

#include <iostream.h>
#include <fstream.h>
#include <string.h>

fstream F,P;

//char strchr(char*p, char Q);

void main ()
{
int v;
int i=0;
int N=5;
char M[50];
char *p;
char S,Q;
p=&M[0];

F.open("input2.txt", ios::in);
P.open("output2.txt", ios::out);
 F.unsetf(ios::skipws);
 while (!F.eof())
  {
  F>>S;
  *(p+i)=S;
  P<<*(p+i);
  cout<<*(p+i);
  i++;
  }
 }

Ещё непонятно почему последний символ повторяется 2 раза.
Заранее премного благодарен!

Это сообщение отредактировал(а) Winterlord - 16.3.2009, 02:43
PM MAIL ICQ   Вверх
Anikmar
Дата 16.3.2009, 03:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



ПОЛЬЗУЙТЕСЬ ПОИСКОМ.
Тема 100 раз обсуждалась.
Вариант:
Я не смотрел ваш код - только изменил имена файлов в древнем своем коде
Код

void DeleteSpaces(void)
{
    FILE *InputFile, *OutputFile;
    char Symbol;
    int Ret;
    bool FlagSpace = false;

    InputFile = fopen("input2.txt","r");
    OutputFile = fopen("output2.txt","w+");

    while(true)
    {
        Ret = fgetc(InputFile);
        if (Ret == EOF) break;
        Symbol = (char)Ret;
        if (Symbol == ' ')
            if (FlagSpace) continue;
            else FlagSpace = true;
        else FlagSpace = false;
        fputc(Symbol,OutputFile);
    }

    fclose(InputFile);
    fclose(OutputFile);
}



Кажется работает.

Это сообщение отредактировал(а) Anikmar - 16.3.2009, 03:11
PM MAIL ICQ   Вверх
afanp
Дата 16.3.2009, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 147
Регистрация: 25.11.2008

Репутация: нет
Всего: нет



посчитать число пробелов, потом их удалить, и добавить один большой пробел в конец?
и эта, считывай в строку из файла с помощью getline в стринг. 
Код

#include<iostream>
#include<fstream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
ifstream infile;
    infile.open("test123.txt");
    if(!infile){
        cout << "file doesnt exist or cannot be opened\n";}
    else{
        string workstring;
    while(!infile.eof()){
        getline(infile,workstring);
        int k=0;
        for(int i=0;i<workstring.length();i++){
            if(workstring[i]==' ') k++;
        }
        cout << k << endl;
        workstring.erase(workstring.end(),remove(workstring.begin(),workstring.end(),' '));
        cout << workstring << endl;}
    }
    system("pause");
    return 0;
}

ну и там добавляешь потом куда надо  пробелы или еще че, если надо вставить все пробелы на место первого, то удаляешь все кроме первого 
а можно просто запомнить место первого пробела и потом туда еще инсертом все засунуть )

Добавлено через 14 минут
Anikmar, я в твоем коде ни шиша не понял  smile  могешь пояснить ? ты там просто пробелы считаешь ? 

Это сообщение отредактировал(а) afanp - 16.3.2009, 21:47
PM MAIL   Вверх
Anikmar
Дата 16.3.2009, 22:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Цитата(afanp @  16.3.2009,  21:36 Найти цитируемый пост)
Anikmar, я в твоем коде ни шиша не понял    могешь пояснить ? ты там просто пробелы считаешь ? 

Зачем их считать? Задача была оставить максимум по 1 пробелу - вот я и оставляю. Про количество ничего не было сказано:
Цитата(Winterlord @  15.3.2009,  23:56 Найти цитируемый пост)
Задача такая: Преобразовать заданную строку следующим образом: заменить все внутренние группы пробелов одним пробелом.


Просто такую задачу я уже кому-то помогал делать - вот и остался исходник.

А что, он не работает? Вроде как работал.

PM MAIL ICQ   Вверх
goody
Дата 16.3.2009, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 31
Регистрация: 23.4.2008

Репутация: нет
Всего: нет



Вот еще вариант :

Код

#include <iostream>
#include <cstring>

using namespace std;

int fyn (char *s) 
{
    char s2[250]="0";
    int i,j;
    int c=0;
    
    for (i=0; i < strlen(s); i++)
    {
        if(s[i]!=' ' || s[i-1]!=' ')
        {
            s2[c]=s[i];
            c++;
            
        }            
    }
    s2[strlen(s2)]='\0';
    strcpy(s,s2);
    return 0;
}



int main()
{
    char str[250];
    printf("before: ");
    gets(str);
    fyn(str);
    printf("after: ");
    puts(str);
    return 0;
} 



PM MAIL   Вверх
Anikmar
Дата 16.3.2009, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Цитата(goody @  16.3.2009,  22:19 Найти цитируемый пост)
s2[strlen(s2)]='\0';

Можно узнать назначение этой строчки?
PM MAIL ICQ   Вверх
mes
Дата 16.3.2009, 22:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(goody @  16.3.2009,  21:19 Найти цитируемый пост)
Вот еще вариант :

но не происходит отсечения начальных и конечных пробелов, хотя имхо должны..
вот вариант с таким отсечением и без использования дополнительного буффера.

Код

 void fyn (char *s)
{
    bool flag = false;
    char *p=s;

    for (;*s && *s==' '; ++s); // пропуск начальных пробелов

    for (;*s; ++s)
      if (*s!=' ')
      {
         if (flag) *p++= ' ';  // перенос пробела

          *p++=*s;           // перенос символа
          flag=false;
       }
       else flag=true;

      *p='\0';


P.S. А также без конца не гонятся функция strlen() - которая не просто возвращает размер, а при каждом вызове его считает перебором всех символов.  smile



Это сообщение отредактировал(а) mes - 16.3.2009, 22:56


--------------------
PM MAIL WWW   Вверх
Winterlord
Дата 16.3.2009, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Немного поясню задание: 

На входе: "      The    project     of     the         International     Phonematic      Alphabet         "

На выходе: "      The project of the International Phonematic Alphabet         "
тоесть должны заменяться  только внутренние пробелы на один, а те пробелы, которые находятся перед текстом и за текстом, должны оставаться неизменными. И всё это должно быть реализовано с использованием функций из библиотеки string.h. Обращаться к элементам массива можно только через указатели. Вот и не знаю как сделать=\ 

Предполагаю, что нужно завести дополнительный массив, искать в  первом массиве первый пробел (кроме тех, что перед текстом <-- тоже не совсем понятно как пропустить), далее копировать с исправлениями кусок во второй массив и так далее. В итоге во втором массиве образуется исправленный текст. 

P.S. Большое спасибо всем откликнувшимся

Это сообщение отредактировал(а) Winterlord - 16.3.2009, 23:10
PM MAIL ICQ   Вверх
Anikmar
Дата 16.3.2009, 23:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Если брать конкретно мой пример - модифицируйте его - считывайте сразу строку, а затем формируйте результирующую строку и сохраняйте в другой файл.

Добавлено через 14 минут и 40 секунд
Вот с использованием string
Код

void DeleteSpaces(void)
{
    const int SizeOfBuff = 255;
    string str_in, str_out;
    FILE *InputFile, *OutputFile;
    char Symbol;
    int Ret;
    bool FlagSpace = false;
    char Buff[SizeOfBuff+1] = {0};

    InputFile = fopen("input2.txt","r");
    OutputFile = fopen("output2.txt","w+");

    while(!feof(InputFile))
    {
        fgets(Buff,SizeOfBuff,InputFile);
        str_in = Buff;
        str_out.clear();
        for(int j=0;j<str_in.length();j++)
        {
            Symbol = (char)str_in[j];
            if (Symbol == ' ')
                if (FlagSpace) continue;
                else FlagSpace = true;
            else FlagSpace = false;
            str_out.push_back(Symbol);
        }
        fputs(str_out.c_str(),OutputFile);
    }

    fclose(InputFile);
    fclose(OutputFile);
}


PM MAIL ICQ   Вверх
mes
Дата 16.3.2009, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Winterlord @  16.3.2009,  22:04 Найти цитируемый пост)
И всё это должно быть реализовано с использованием функций из библиотеки string.h. Обращаться к элементам массива можно только через указатели.

имеется ввиду эта библиотека http://cplusplus.com/reference/string/string/ ?
Если да, то функции find...of() и substr() Вам в помощь.
Только вот не пойму к чему тут указатели. Не спутали ли воедино два разных задания ?!


--------------------
PM MAIL WWW   Вверх
Winterlord
Дата 17.3.2009, 00:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Цитата(mes @  16.3.2009,  23:52 Найти цитируемый пост)
имеется ввиду эта библиотека http://cplusplus.com/reference/string/string/ ?
Если да, то функции find...of() и substr() Вам в помощь.
Только вот не пойму к чему тут указатели. Не спутали ли воедино два разных задания ?! 

Нет, скорее функции вот этой библиотеки: (хотя работаю я в Борланде С++е)
http://forum.vingrad.ru/forum/topic-165963...1%82%D0%BC.html
И использовать, например, для поиска я хотел strchr()
А указатели, думаю, чтоб работать не напрямую со считанным из файла массивом и чтобы к строке через них обращаться, а не посимвольно.

Это сообщение отредактировал(а) Winterlord - 17.3.2009, 00:07
PM MAIL ICQ   Вверх
Anikmar
Дата 17.3.2009, 00:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Цитата(Winterlord @  17.3.2009,  00:03 Найти цитируемый пост)
И использовать, например, для поиска я хотел strchr()

Что вы там собрались искать? Пробелы что-ли?  smile 

Цитата(Winterlord @  17.3.2009,  00:03 Найти цитируемый пост)
А указатели, думаю, чтоб работать не напрямую со считанным из файла массивом. Может быть, чтобы к строке не посимвольно обращаться, а через указатели.

Строка - это массив символов. Какие еще дополнительные указатели нужны? Использовать их вместо операции индексирования []? Так это ради Бога.
PM MAIL ICQ   Вверх
Winterlord
Дата 17.3.2009, 00:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Цитата(Anikmar @  17.3.2009,  00:09 Найти цитируемый пост)
Что вы там собрались искать? Пробелы что-ли?  

Ну да) я ж писал
Цитата(Winterlord @  16.3.2009,  23:04 Найти цитируемый пост)
Предполагаю, что нужно завести дополнительный массив, искать в  первом массиве первый пробел (кроме тех, что перед текстом <-- тоже не совсем понятно как пропустить), далее копировать с исправлениями кусок во второй массив и так далее. В итоге во втором массиве образуется исправленный текст. 



Цитата(Anikmar @  17.3.2009,  00:09 Найти цитируемый пост)
Строка - это массив символов. Какие еще дополнительные указатели нужны? Использовать их вместо операции индексирования []? Так это ради Бога. 

Да, наверно так)
PM MAIL ICQ   Вверх
Anikmar
Дата 17.3.2009, 00:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Мой алгоритм такой:
Идем посимвольно по строчке. Встретили пробел - проверяем флаг. Если флаг установлен - значит пробел не первый, пропускаем. Если флаг не установлен - пробел первый - записываем в результирующую строку. Если символ вообще не пробел - флаг сбрасываем, символ записываем.

Никаких поисков в этой задаче не нужно. Каждый поиск - это пробег с начала строки. Зачем?
PM MAIL ICQ   Вверх
Winterlord
Дата 17.3.2009, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Цитата(Anikmar @  17.3.2009,  00:22 Найти цитируемый пост)
Мой алгоритм такой:
Идем посимвольно по строчке. Встретили пробел - проверяем флаг. Если флаг установлен - значит пробел не первый, пропускаем. Если флаг не установлен - пробел первый - записываем в результирующую строку. Если символ вообще не пробел - флаг сбрасываем, символ записываем.

А ваш алгоритм игнорирует пробелы перед текстом и после?

PM MAIL ICQ   Вверх
Anikmar
Дата 17.3.2009, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Цитата(Winterlord @  17.3.2009,  00:47 Найти цитируемый пост)
А ваш алгоритм игнорирует пробелы перед текстом и после?

Мой алгоритм делает из нескольких пробелов подряд один. А нужно было игнорировать? Тогда дополнительный флаг появится - признак начала строки. И дополнительная переменная - счетчик пропущенных пробелов.

PM MAIL ICQ   Вверх
Winterlord
Дата 17.3.2009, 01:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Цитата(Anikmar @  17.3.2009,  00:53 Найти цитируемый пост)
А нужно было игнорировать?


Я ж тут писал:
Цитата(Winterlord @  16.3.2009,  23:04 Найти цитируемый пост)
Немного поясню задание: 

На входе: "      The    project     of     the         International     Phonematic      Alphabet         "

На выходе: "      The project of the International Phonematic Alphabet         "
тоесть должны заменяться  только внутренние пробелы на один, а те пробелы, которые находятся перед текстом и за текстом, должны оставаться неизменными. И всё это должно быть реализовано с использованием функций из библиотеки string.h. Обращаться к элементам массива можно только через указатели. Вот и не знаю как сделать=\ 

Предполагаю, что нужно завести дополнительный массив, искать в  первом массиве первый пробел (кроме тех, что перед текстом <-- тоже не совсем понятно как пропустить), далее копировать с исправлениями кусок во второй массив и так далее. В итоге во втором массиве образуется исправленный текст. 

Совсем запутался)

PM MAIL ICQ   Вверх
Dmi3ev
Дата 17.3.2009, 01:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1698
Регистрация: 28.11.2007

Репутация: 13
Всего: 41



вот накидал... указаетелей - туча...
Код

#include "stdafx.h"
#include <iostream>
#include <fstream>

using namespace std;

int _tmain()
{
    char buf[256];
    
    ofstream fo("D:\\1.txt");
    ifstream fi("D:\\2.txt");

    while (!fi.eof())
    {
        fi.getline(buf,256);
        char *p;
        char *d=" ";
        char *bt=buf;
        
        while (*bt==' ')
            fo<<*(bt++);
        char *et=buf;
        
        et+=strlen(buf)-1;
        
        while (*et==' ' && et!=bt)
            et--;
        p=strtok(buf, d);
        while (p=strtok(NULL, d))
                fo<<p<<" ";
        while (*et==' ')
            fo<<*(et--);
        fo<<endl;
    }
    fo.close();
    fi.close();
    return 0;
}

есть две недоработки:
1) не рассматривал случай, если одни пробелы в строке.
2) в строке с комментарием всегда прибавляется пробел к слову, но при добавлении последнего куска текста этого делать не надо,
это остается тебе для размышления, а так вроде нормуль... хотя хз, я не тестил)))

Добавлено @ 01:25
Цитата

2) в строке с комментарием всегда прибавляется пробел к слову, но при добавлении последнего куска текста этого делать не надо,

те к тексту прибавляется один лишний пробел, думаю сможешь поправить, мне лень...

Это сообщение отредактировал(а) Dmi3ev - 17.3.2009, 01:25


--------------------

PM MAIL   Вверх
Winterlord
Дата 17.3.2009, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Цитата(Dmi3ev @  17.3.2009,  01:23 Найти цитируемый пост)
#include "stdafx.h"

Спасибо
а что вот это такое?


Это сообщение отредактировал(а) Winterlord - 17.3.2009, 01:28
PM MAIL ICQ   Вверх
Dmi3ev
Дата 17.3.2009, 01:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1698
Регистрация: 28.11.2007

Репутация: 13
Всего: 41



Цитата

а что вот это такое?

не важно, просто я компилил в MS VS, тебе надо это убрать и переименовать _tmain() в main

Добавлено через 2 минуты
вместо 
Код

#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
int _tmain()
{
//...
}

тебе надо
Код

#include <iostream.h>
#include <fstream.h>
#include <string.h>
int main()
{
//...
}


Добавлено через 3 минуты и 11 секунд
Цитата

те к тексту прибавляется один лишний пробел, думаю сможешь поправить, мне лень...

а можешь и не править, потому как сзади незаметно))) впереди бы было заметно, а сзади +1 пробел, ничего страшного)))


--------------------

PM MAIL   Вверх
Winterlord
Дата 17.3.2009, 01:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Dmi3ev, Большое спасибо, уж завтра попробую, отпишусь;)
PM MAIL ICQ   Вверх
Anikmar
Дата 17.3.2009, 01:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Гы. И мой вариант.
Вроде работает.
Варианты - когда конец файла вместо конца строки и одни пробелы в строке вроде как отрабатывает.
Недостаток:Если конец файла в строке вместо конца строки - то в результирующем файле добавится конец строки перед концом файла
Код

void DeleteSpaces(void)
{
    const int SizeOfBuff = 255;
    string str_in, str_out,str_temp;
    FILE *InputFile, *OutputFile;
    char Symbol;
    int Ret;
    bool FlagSpace = false;
    bool FlagStartLine;
    char Buff[SizeOfBuff+1] = {0};
    int Count;

    InputFile = fopen("input2.txt","r");
    OutputFile = fopen("output2.txt","w+");

    while(!feof(InputFile))
    {
        fgets(Buff,SizeOfBuff,InputFile);
        str_in = Buff;
        str_out.clear();
        FlagStartLine = true;
        Count = 0;
        for(unsigned int j=0;j<str_in.length();j++)
        {
            Symbol = (char)str_in[j];
            if (Symbol == ' ')
            {
                Count++;
                if ((FlagSpace)&&(!FlagStartLine)) continue;
                else FlagSpace = true;
            }
            else
            {
                if (Symbol == '\n') continue;
                Count = 0;
                FlagSpace = false;
                FlagStartLine = false;
            }
            str_out.push_back(Symbol);
        }
        if ((Count > 1)&&(!FlagStartLine)) str_out.append(Count-1,' ');
        str_out.push_back('\n');
        fputs(str_out.c_str(),OutputFile);
    }

    fclose(InputFile);
    fclose(OutputFile);
}

PM MAIL ICQ   Вверх
Dmi3ev
Дата 17.3.2009, 01:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1698
Регистрация: 28.11.2007

Репутация: 13
Всего: 41



Цитата

Dmi3ev, Большое спасибо, уж завтра попробую, отпишусь;) 

вот тебе:
Код

#include <iostream.h>
#include <fstream.h>
#include <string.h>

int main()
{
    char buf[256];
    
    ofstream fo("D:\\1.txt");
    ifstream fi("D:\\2.txt");

    while (!fi.eof())
    {
        fi.getline(buf,256);
        char s[256];
        int i=0;
        char *p;
        char *d=" ";
        char *bt=buf;
        
        while (*bt==' ')
            s[i++]=*(bt++);
        char *et=buf;
        
        et+=strlen(buf)-1;
        
        while (*et==' ' && et!=bt)
            et--;
        p=strtok(buf, d);
        while (p=strtok(NULL, d))
        {
            while (*p)
                s[i++]=*(p++);
            s[i++]=' ';
        }
        if (i>0)
            i--;
        while ((*et==' ') && (et!=bt))
            s[i++]=*(et--);
        s[i]='\0';
        fo<<s;
        cout<<s<<endl;
        fo<<endl;
    }
    fo.close();
    fi.close();
    system("pause");
    return 0;
}

дурацкие действия не предусмотрены, но если все будет нормально, то это прога работает...


--------------------

PM MAIL   Вверх
mes
Дата 17.3.2009, 03:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



не смотря на обилие кода в этой теме, вношу свою лепту:
Код

void fn(char* s)
{
    for (;*s && *s==' '; ++s);           // пропускаем начальные пробелы

    for (char *p=s; *p;)
    {
        for(;*p && *p!=' ';++p) *s++=*p; // копируем не_пробелы

        char *p1=p;                      // запоминаем позицию
        for(;*p && *p==' ';++p);         // пропускаем все пробелы

        if (*p) *s++=' ';                // если не дошли до конца_строки то ставим только один пробел
        else for (;p1<p;++p1) *s++=' ';  // иначе ставим все
    }
    *s='\0';  //ставим новый конец строки.
}


Код


int main ()
{
  char s[] = "      The    project     of     the         International     Phonematic      Alphabet         ";

  std::cout<<"-"<<s<<"-"<<std::endl;

  fn(s);
  std::cout<<"-"<<s<<"-"<<std::endl;

  system("pause");
  return(0);
}


Это сообщение отредактировал(а) mes - 17.3.2009, 03:23


--------------------
PM MAIL WWW   Вверх
mes
Дата 17.3.2009, 03:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



вот еще подправил
Код

void fn(char* s)
{
    for (;*s && *s==' '; ++s);               // оставляем начальные пробелы

    char *last =s;

    for (char *p=s; *p; ++p) if (*p!=' ') last=p; // ищем последний не_пробел.

    for (char *p=s; p<=last;)
    {
        for(;p<=last && *p!=' ';++p) *s++=*p; // копируем слово (пока не_пробел)

        if (p<last)                   // если еще не дошли до последнего_символа,
        {
           *s++=' ';                  // то ставим один пробел
           for(; *p==' ';++p);        // и игнорируем остальные
        }
    }

    for (++last; *last; ++last) *s++=*last;    // переносим финальные пробелы

    *s='\0';  //ставим новый конец строки.
}



теперь логика обработки как  начальных так  и конечных пробелов отделена от центральных. smile

Это сообщение отредактировал(а) mes - 17.3.2009, 10:06


--------------------
PM MAIL WWW   Вверх
Anikmar
Дата 17.3.2009, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Ну, препода просто завалить можно вариантами  smile 
PM MAIL ICQ   Вверх
mes
Дата 17.3.2009, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Anikmar @  17.3.2009,  11:09 Найти цитируемый пост)
Ну, препода просто завалить можно вариантами  smile  

 smile 
теперь главное, чтоб тс сам не "завалился" в этом изобилии  smile 


--------------------
PM MAIL WWW   Вверх
Winterlord
Дата 18.3.2009, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Цитата(Dmi3ev @  17.3.2009,  01:53 Найти цитируемый пост)
вот тебе:


Dmi3ev,  Ваша программа работает, но съедает любое первое слово. Например на входе "       The project     of     the         International     Phonematic      Alphabet    ", а на выходе: "       project of the International Phonematic Alphabet"
И что то это никак не исправить=\


mes, Ваша программа работает, но, если я прально понял, вообще не использует библиотеку string.h


Это сообщение отредактировал(а) Winterlord - 18.3.2009, 11:55
PM MAIL ICQ   Вверх
mes
Дата 18.3.2009, 14:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Winterlord @  18.3.2009,  10:29 Найти цитируемый пост)
 но, если я прально понял, вообще не использует библиотеку string.h

ага, ей не нашлось места в коде  smile забыл  .. точнее сказать, не вспомнил, когда писал код , что ее использование обязательно  smile 




--------------------
PM MAIL WWW   Вверх
Anikmar
Дата 18.3.2009, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Ну а хоть мой код работает?
PM MAIL ICQ   Вверх
Dmi3ev
Дата 18.3.2009, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1698
Регистрация: 28.11.2007

Репутация: 13
Всего: 41



Цитата

Dmi3ev,  Ваша программа работает, но съедает любое первое слово. Например на входе "       The project     of     the         International     Phonematic      Alphabet    ", а на выходе: "       project of the International Phonematic Alphabet"

да надо после первого вызова strtok добавить
Код

        while ((*p))
            s[i++]=*(p++);

+ еще добавить условие конца файла, строки, но даже при таких раскладах должна работать, хоть и будет выдавать ошибку, но файл правильно заполнит... точнее, должна выдать ошибку, я не проверял...


--------------------

PM MAIL   Вверх
mes
Дата 18.3.2009, 19:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Winterlord @  18.3.2009,  10:29 Найти цитируемый пост)
не использует библиотеку string.h

вот с библиотекой..
Код

void fn(const char* s, char *dst)
{
     const char *begin =s; // указатель на начало строки
     const char *end   = s+strlen(s); // расчитывает указатель на конец строки

// 1
     if (*s==' ') // если первый пробел
     {
       for (const char *p=s; p && !(p-s); p=strchr(s,' '))  ++s; // то ищем где заканчиваются начальные пробелы

       strncat (dst, begin, s-begin); // и прибавляем их к результативной строке
     }  
// в результате s указывает на 1й не_пробел

// 2
      for (const char *p=s; p && p<end;) //  пока не дойдем до конца строки 
      {
           p=strchr(s,' '); // ищем где заканчиается слово
           if (p) // если найдено
           {
               strncat (dst, s, p-s); // копируме его в результативную строку
               s=p;                         // запоминаем указатель 
               for (const char *p1=p; p<end && p1 && !(p1-p); p1=strchr(p,' ')) ++p; // пропускаем все пробелы
               if (end-p) // если не вышли за конец
               {
                   s=p; //запоминаем позицию (это будет начало другого слова)
                   strcat (dst, " "); // вставляем проблел в результативную строку
               };
             };
        }
// 3
        strncat (dst, s, end-s); // копируем в результативную строку финальный (не обработанный)  кусок строки.
}

P.S. s - используется фактически как счетчик отработанных символов, p и p1 для поиска вперед. 

добавил комменты smile



Это сообщение отредактировал(а) mes - 19.3.2009, 01:18


--------------------
PM MAIL WWW   Вверх
Winterlord
Дата 19.3.2009, 01:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Anikmar, Для меня без комментариев очень сложно понять ваш код. Если там используются флаги, то их нельзя использовать=\

mes, напишите пожалуйста хотя б поверхностные комментарии. И куда в функции мейн воткнуть dst?

Dmi3ev , теперь первое слово выводится прально, но съедаются пробелы после него, тоесть между первым и вторым и последние пробелы из исходного текста не переносятся в изменённый.

P.S. Большое спасибо, что помогаете



Это сообщение отредактировал(а) Winterlord - 19.3.2009, 01:22
PM MAIL ICQ   Вверх
mes
Дата 19.3.2009, 01:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Winterlord @  19.3.2009,  00:07 Найти цитируемый пост)
mes, напишите пожалуйста хотя б поверхностные комментарии. 

написал smile


Цитата(Winterlord @  19.3.2009,  00:07 Найти цитируемый пост)
И куда в функции мейн воткнуть dst?


вот пример вызова :

Код

int main ()
{
  char s[] =  "      The    project     of     the         International     Phonematic      Alphabet      ";
  char s1[100] = { 0 };


  fn (s, s1);
    std::cout<<"="<<s1<<"="<<std::endl;

  system("pause");
  return(0);
}



--------------------
PM MAIL WWW   Вверх
Dmi3ev
Дата 19.3.2009, 01:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1698
Регистрация: 28.11.2007

Репутация: 13
Всего: 41



Цитата

Dmi3ev , теперь первое слово выводится прально, но съедаются пробелы после него, тоесть между первым и вторым и последние пробелы из исходного текста не переносятся в изменённый.

не пробелы, а один пробел! надо еще дописать после цикла:
Код

s[i++]=' ';

Проявите фантазию


--------------------

PM MAIL   Вверх
Winterlord
Дата 19.3.2009, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



mes, Большое спасибо, вроде работает, входные\выходные файлы надеюсь, что сам смогу прикрутить)

Dmi3ev, И вам большое спасибо. Да, постараюсь доделать) если не сложно, напишите пожалуйста комментарии к вашему коду, хотя б поверхностные
PM MAIL ICQ   Вверх
xvr
Дата 19.3.2009, 12:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Еще вариант, правда без string.h, но зато с родными для Borland'а строками (AnsiString) - так, на закуску  smile
Код

AnsiString my_trim(AnsiString inp)
{
 int l=inp.Length();  inp=inp.TrimLeft();
 int left_spaces=l-inp.Length();
 l=inp.Length();  inp=inp.TrimRight();
 int righ_spaces=l-inp.Length();

 for(;;)
  {
   AnsiString s=StringReplace(inp,"  "," ",TReplaceFlags()<<rfReplaceAll);
   if (s==inp) break;
   inp=s;
  }
 return AnsiString::StringOfChar(' ',left_spaces)+inp+AnsiString::StringOfChar(' ',right_spaces);
}



Это сообщение отредактировал(а) xvr - 19.3.2009, 12:52
PM MAIL   Вверх
Anikmar
Дата 19.3.2009, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Цитата(Winterlord @  19.3.2009,  01:07 Найти цитируемый пост)
Anikmar, Для меня без комментариев очень сложно понять ваш код. Если там используются флаги, то их нельзя использовать=\

А флаги почему нельзя?  smile 


На самом деле мой код от остальных отличается принципиально только тем, что он однопроходный - т.е. все идет в одном цикле. Если флаги нельзя- тогда мой код можете выкинуть.
PM MAIL ICQ   Вверх
Winterlord
Дата 21.3.2009, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Цитата(Anikmar @  19.3.2009,  17:36 Найти цитируемый пост)
А флаги почему нельзя?

Препод сказал, по идее флаги можно использовать только в следующей работе. Другая тема)


mes, Вот ваша функция мейн, только с добавленным чтением с файла:
Код

int main ()
{
  char s[100];
  int i=0;
  F.open("input2.txt", ios::in);
  P.open("output2.txt", ios::out);
  F.unsetf(ios::skipws);
   while (!F.eof())
    {
    F>>s[i];
    i++;
    } 
   cout<<endl;
      if (i==1) 
       {
       cout<<"No input information"<<endl; 
       P<<"No input information"<<endl; 
       system("pause"); 
       F.close(); P.close(); 
       return (0);
       }               
  //char s[] =  "      The    project     of     the         International     Phonematic      Alphabet      ";
  char s1[100] = { 0 };
  fn (s, s1);
    cout<<"="<<s1<<"="<<endl;
    P<<"="<<s1<<"="<<endl;
  system("pause");
  F.close(); P.close();
  return(0);
}


Как исправить такую проблему, что если ввести строку, где последние символы пробелы (хотя бы один) - то всё нормально, если же ввести строку, где последние символы не пробелы - при выводе добавляется произвольный лишний символ.
И если ввести только пробелы - выводятся пробелы - нормально, а если ввести меньше 8-ми пробелов или просто много пробелов - выводится крокозябра) Заранее благодарен.

P.S. Если компилировать на Борланде С++ 3.1, то при выводе в конце строки прибавляется крокозябра. Если компилировать в Dev C++, то только когда меньше восьми пробелов и когда их очень много.
PM MAIL ICQ   Вверх
mes
Дата 21.3.2009, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



вы считывайте из файла буфер. Чтоб этот буффер можно было считать строкой в конце должен стоять '\0'
если Вы работаете с одной строкой, которая меньше по длине, чем размер буффера, то достаточно обнулить этот буфер изначально.
стр 3:
Код

char s[100]  = { 0 };



--------------------
PM MAIL WWW   Вверх
Winterlord
Дата 21.3.2009, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



mes, Большое спасибо, пока работает) воспользовался обнулением
PM MAIL ICQ   Вверх
mes
Дата 21.3.2009, 23:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Winterlord @  21.3.2009,  20:15 Найти цитируемый пост)

  F.open("input2.txt", ios::in);
  P.open("output2.txt", ios::out);
..
  cout<<"No input information"<<endl; 
  P<<"No input information"<<endl; 

переменные F и P очень портят вид кода, Гулливер и то, имхо, смотрелся лучше.
Учитывая, что пользуетесь stl, гораздо симпатичнее смотрелись бы fin и fout.

Добавлено @ 23:27
не вытерпел, подправил код.. Вам для примера, ну а мне чтоб глаза не резал smile. В дальнейшем сами старайтесь..уважайте тех кому придется его читать smile
Код

#define BUFF_SIZE 100

int main ()
{ 
  cout<<endl;

  char s [BUFF_SIZE] = { 0 };
  char s1[BUFF_SIZE] = { 0 };

  fin.open("input2.txt", ios::in);
  fin.unsetf(ios::skipws);

  fout.open("output2.txt", ios::out);

  int readed =0;
  for (;!fin.eof() && readed<BUFF_SIZE; ++readed)    
   fin>>s[i];
  
  if (readed<=1) 
  {
      cout<<"No input information"<<endl; 
      fout<<"No input information"<<endl; 
  }               
  else 
  {
       fn (s, s1);
       cout<<"="<<s1<<"="<<endl;
       fout<<"="<<s1<<"="<<endl;
  }

  fout.close();
  fin.close();

  system("pause"); 
  return (0);
}



Это сообщение отредактировал(а) mes - 21.3.2009, 23:31


--------------------
PM MAIL WWW   Вверх
Winterlord
Дата 21.3.2009, 23:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



mes, Огромное спасибо) Я не волшебник, а только учусь ^_^
PM MAIL ICQ   Вверх
Winterlord
Дата 23.3.2009, 19:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Anikmar, 
Dmi3ev, 
mes, Большое вам спасибо, помогли. Сегодня сдал прогу) ^_^
PM MAIL ICQ   Вверх
Winterlord
Дата 23.3.2009, 21:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 58
Регистрация: 5.10.2008

Репутация: нет
Всего: нет



Вопрос решён
PM MAIL ICQ   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0993 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.