Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Работа со строками


Автор: Ripper 7.10.2007, 20:21
Значит, пользователь вводит строку. Нужно сформировать новую строку из 80 символов, куда поместить первую, "центрировав" все слова. т.е.
1) "   f  d f    fgg    s d"
2)"      f d f fgg s d      "  - слова разделены 1 пробелом. 
Передвигатся с помощью указателей, соответсвенно массивы символов. 
Я не совсем понимаю как это вообще сделать. Думал взять первую привести к виду "f d f fgg s d" т.е. удалить побокам пробелы и внутри только один оставить, посчитать длину этой строки. а потом необходимое количество пробелов слева и справа для второй.  (библиотечные ф-ии незя использовать). Но и это толком не получается. Очень тяжко даются такие задачи :( Вот пробывал сначала к этому виду привести, хотя бы просто удалить все пробелы:
Код

#include <iostream>
using namespace std;

void output(char *str);
int obrabotka(char *from, char *to);
char* deletespaces(char*, char*);
int strlen(char*);
char* skip (char*);
int count (char *str);

const int SIZE=80;

int main () {
    char in[SIZE], buf [SIZE];
    while (cout << "Enter string:" << endl, cin.getline(in,80)) {
      deletespaces(in,buf);
      output(buf);
    }
    system("pause");
    return 0;
}

void output(char *str) {
     for (char* i=str; *i; i++) 
      cout << *i;
      cout << endl;
}

char* skip (char *str) {
      while ((*str==' ') || (*str == '\t')) 
       str++;
      return str;
}

int count(char* str) {
    int i=0; 
    for (char* tmp=str; *tmp&&*tmp!=' '&&*tmp!='\t'; tmp++, i++);
    return i;
}

char* deletespaces(char* from, char* to) {
      int n, i=0;
      for (; *from; i++) {
       from = skip(from);
       n=count(from);
       
       for (int j=0; j<n; j++) 
        *(to++)=*(from++);
      }
       return from;
}


Тут часть прототипных ф-ий не описаны. Но и тут, если вводить много строчек ерунда получается, видимо опять эти указатели :( Уже голова кипит, подскажите плз

Автор: zkv 7.10.2007, 20:30
Ripper, эта задача легко решается с помощью СИ-шных sscanf sprintf, либо С++сных std::strstream
если ими пользоваться нельзя, то возьми идею - читаешь посимвольно следующее слово из исходной строки, пропуская пробелы, дописываешь в конец новой строки, через один пробел.
Все это в цикле, пока исходная строка не кончится.

Автор: Walker 7.10.2007, 22:08
Доброго времени суток!
Судя по 
Цитата
#include <iostream>
, библиотечные функции всё же использовать можно. Тем не менее, вот прикинул пример на C. Программа принимает строку произвольной длины. Если после уплотнения строка в буфер из 80 символов не влезает, то оставшаяся её часть просто отсекается.

Код

#define MAXLINE 80
#define EOF -1

main()
{
    int c; /* Переменная для хранения считываемого символа */
    int k; /* Счётчик для циклов */
    int i = 0; /* Индекс массива */
    int line[MAXLINE]; /* Массив для хранения строки */
    
    /* Пропускаем пробелы в начале */
    while((c = getchar()) != EOF && c == ' ')
     ;
    line[i] = c;
    i++;
    
    /* Формируем массив. Страхуемся от переполнения буфера */
    while((c = getchar()) != EOF && i < 80)
    {
        if((line[i - 1] == c) && c == ' ')
            continue;
        line[i] = c;
        i++;
    }
    
    /* Центрируем путём отступа */
    for (k = 0; k < (80 - i) / 2; k++)
     putchar(' ');
     
    /* Выводим на печать заполненную часть массива */
    for(k = 0; k < i; k++)
     putchar(line[k]);
}

P.S. Не все указатели бывают одинаково полезны. smile 

Автор: Любитель 7.10.2007, 22:44
Цитата(Walker @  7.10.2007,  22:08 Найти цитируемый пост)
Судя по #include <iostream>

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

Автор: Ripper 8.10.2007, 05:08
использовать нельзя библиотечных ф-ий. Эту строку, мы так толком и не понимаем ещё, подключается какая то библиотека, а почему не .h в линуксе и с .h в виндусе, или верней при using namespace std; т.е. кароче нам сказали писать 2 строки, а что это значит мы толком незнаем ) putchar, getchar тоже незнаем таких smile  И там явно как то по другому, тех же указателей нет. Тот бред что я выше написал, это просто часть собранных с тетради ф-ий в каком то смысле. Вот нужно что-то в таком духе...

zkv, Ну я попробую, проверять что-то вроде, символ!=проблел -> записать. Но как потом слева и справа добавить пробелы нужное количество. Почему в конец именно дописывать? 

Автор: zkv 8.10.2007, 07:23
Ripper, сорри, невнимательно задание прочитал, еще центрировать нужно.
решение уже Walker привел, ну вот еще, через через массивы, видимо так по заданию нужно было?
что не нравится - доработаешь напильником smile
Код

#include <iostream>

int RemoveRepeatedSpaces( const char *pSrc, char *pDst );
void InsertAtCenter( const char *pSrc, int lenSrc, char *pDst, int lenDst );

int main() 
{
    const unsigned size = 80;
    char    src[size], buff[size], dst[size];

    std::cin.getline( src, size );

    int lenBuff = RemoveRepeatedSpaces( src, buff );

    InsertAtCenter( buff, lenBuff, dst, size );
    
    std::cout<<dst;
    std::cin.get();
}

bool IsSpace( char c )
{
    return c == ' ' || c == '\t';
}

bool SkipSpaces( const char *&pSrc )
{
    while( *pSrc && IsSpace( *pSrc ) )
        ++pSrc;
    return *pSrc != 0;
}

bool AddNextGroup( const char *&pSrc, char *&pDst )
{
    while( *pSrc && !IsSpace( *pSrc ) )
        *pDst++ = *pSrc++;
    return *pSrc != 0;
}

int RemoveRepeatedSpaces( const char *pSrc, char *pDst )
{
    const char * const pDstBegin = pDst;
    while( true )
    {
        if( !SkipSpaces( pSrc ) )
            break;

        if( pDst != pDstBegin)
            *pDst++ = ' ';

        if(    !AddNextGroup( pSrc, pDst ) )
            break;
    }
    *pDst = '\0';
    return pDst - pDstBegin;
}

void SetSpaces( char *&pDst, int count )
{
    for( int i = 0; i < count; ++i )
            *pDst++ = ' ';
}

void Copy( const char *pSrc, char *&pDst )
{
    while( *pSrc )
        *pDst++ = *pSrc++;
}

void InsertAtCenter( const char *pSrc, int lenSrc, char *pDst, int lenDst )
{
    int lenDelta = (lenDst - lenSrc)/2;
    
    SetSpaces( pDst, lenDelta );
    
    Copy( pSrc, pDst );

    SetSpaces( pDst, lenDst - lenSrc - lenDelta - 1 );

    *pDst = '\0';
}

Автор: 0lmer 9.10.2007, 14:00
Можно поробовать и так:


Код


#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
  char in [81];
  char out [81];
  char temp [81];
  cin.getline(in, 80, '\n');
  
  int j = 0;
  int i = 0;
  int tlen = 0;
  while (in[i] != 0) {
    if (in[i] != ' ') {
      temp[j] = in[i];
      ++i;
      ++j;
      ++tlen;
    } else {
      if (in[i] == ' ' && in[i + 1] != ' ') {
        temp[j] = ' ';
        ++j;
        ++i;
        ++tlen;
      } else {
        ++i;
      }    
    }  
  }
  temp[j + 3] = 0;
  
  int spcount = (80 - tlen) / 2;
  
  for (i = 0; i < spcount; ++i) {
    out[i] = ' ';
  }  
  j = 0;
  while (temp[j] != 0) {
    out[i] = temp[j];
    ++i;
    ++j;
  }
  for (; i < 80; ++i) {
    out[i] = ' ';
  }
  out[80] = 0;
  
  cout << out;    
     
  return 0;
}


Автор: Rickert 9.10.2007, 19:22
0) Считаем длинну строки.
1) Идём по всей строке, считаем длины слов и их кол-во, попутно занося их в дин. массив.
2) Ну а дальше всё ясно я думаю smile 

Автор: Ripper 9.10.2007, 20:58
Всем спасибо smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)