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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [C] Выравнивание текста, по правому краю 
V
    Опции темы
ivashkanet
Дата 30.11.2006, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Значится так:
Предпосылки такие:
  •  Знаем ширину любой буквы шрифта.
  •  Пробелы имеют фиксированную длину.

Метод упорядочивания текста:
[*]Расставление доп. пробелов между словами
Алгоритм:
1) Находим первое слово, которое не помещается в строку.
Для этого нам нужно знать ширину каждой буквы и минимальную ширину пробела.
Складываем последовательно ширину всех букв, включая пробелы и проверяем вышли ли мы за пределы строки.
2) Слово на котором вышли отбрасываем и вычисляем длину всех букв в неоткинутых словах (пробелы не считаются).
3) Вычисляем разность между длинной строки и числом из п. 2. 
4) Определяем сколько пробелов нужно для выравнивания текста.
5) Вычисляем сколько пробелов будет между конкретными словами (распределяем так, чтобы всем было поровну +-1 пробел)
5) Выводим строку с количеством пробелов вычисленном в пред. пункте.

P.S. Если не разберетесь --- спрашивайте. Я сделаю это не раньше понедельника (работы очень много). Максимум на C#
PM MAIL WWW ICQ   Вверх
anad
Дата 30.11.2006, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Да, ну и задачка...
PM MAIL   Вверх
anad
Дата 30.11.2006, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Буду ждать.
PM MAIL   Вверх
Kuvaldis
Дата 30.11.2006, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


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

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



anad
Надо хотеть что-либо сделать и приложить хоть какие-то усилия. Вот я за 10 минут упростил свой вариант, который привел во втором посте этой темы
Код

//-------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
//-------------------------------------------------------------------
#define LEN 60  // max string length
//-------------------------------------------------------------------
int get_width(char* str, int count);
int get_words_count(char* str);
//-------------------------------------------------------------------
int main(void) 
{    
    char str[LEN] = {0};
    int  n;

    puts("Input str len");
    scanf("%d", &n);
    fflush(stdin);
    puts("Input str");
    fgets(str, LEN, stdin);
    str [ strlen(str) - 1 ] = '\0';

    if (get_width(str, n))
    {
        puts("After chiki-puki");
        for (int i = 1; i <= LEN; i++)
        {
            printf("%d", i % 10);
        }
        puts("");
        puts(str);
    }
    system("pause");
    return 0;    
}
//-------------------------------------------------------------------
// insert extra gaps to get width-str
// size - string max size

int get_width(char* str, int len)

{
    int    gapkol = 0;  // gaps count
    int    i, j, k;     // cycle variables
    int    n;           // real str length
    int    step;        // gaps count to add to each gap_group
    int    tail = 0;    // step += tail
    int    ost;         // gapskol % count    
    char*  res = NULL;  // result str
    int    count;        // words count in string
    
    count = get_words_count(str);
    n = strlen(str);
    if ((count == 1) && (str[0] != ' '))  // if only one word and no leading gaps
    {
      for(i = n; i < len; i++)           // fill following spaces with gaps
         str[i] = ' ';
      return 1;
    }

    if(!(res = (char*) calloc(len + 1, sizeof(char))))
    {
       puts("Error: not enough memory");
       return 0;
    }
    gapkol = len - n;   // following gaps count
    count--;            // count of gaps groups
   

    for (k = 0; k <= n; k++)                   // calculate all gaps in str
    {
      if(str[k] == ' ')
         gapkol++;
    }


    if (gapkol == 0)  // if no gaps (all string is letters)
    {
       free(res);                          // exit function
       return 1;
    }

    i = j = 0;

    if (count == 0)                       // if only one word
    {
       while ((i < n) && (str[i] != ' '))  // copy word in res
          res[j++] = str[i++];
       for (i = 0; i < gapkol; i++)        //add gaps into str end
          res[j++] = ' ';
       strcpy(str, res);                  // restore str
       str[len - 1] = '\0';
       free(res);
       return 1;
    }

    while (str[i] == ' ')              // get first word start
           i++;

    step = gapkol / count;                // gaps count to add to each gap_group
    ost = gapkol % count;                 // divide ostatok

    if (ost)
      tail = 1;
    for (count; count > 0; count--)        // for each gap_group
    {
       while (str[i] != ' ')              // copy word
          res[j++] = str[i++];
     
       while (str[i] == ' ')              // miss following gaps
           i++;
       
       for (int i = 0; i < step + tail; i++) // add new gaps after word
          res[j++] = ' ';
       ost--;
       if(!ost)                           // if all ostatok is written
         tail = 0;
    }

    while (str[i] && (str[i] != ' '))     // copy last word
       res[j++] = str[i++];

    res[j] = '\0';
    strcpy(str, res);                     // restore str
    free(res);
    
    return 1;
}
//-------------------------------------------------------------------
int get_words_count(char* str)
{
    int n;
    int found = 0;
    int count = 0;

    n = strlen(str);
    for (int i = 0; str[i]; i++)
    {
        if (!isspace(str[i])) 
        {
            if (!found)
            {
               found = 1;// вошли в слово, до этого были пробелы
               count++;
            }
        }
        else 
            found = 0;        
    }    

    return count;
}
//-------------------------------------------------------------------





--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
anad
Дата 1.12.2006, 00:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Я знаю, что здесь работают умные люди, спасибо!

Эта программа выравнивает текст по правому краю? А можно пояснения на русском языке?
А указатели не надо использовать?
PM MAIL   Вверх
Kuvaldis
Дата 1.12.2006, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


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

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



anad
Цитата

Эта программа выравнивает текст по правому краю?

Нужно запустить и убедиться.. (выравнивает)

Цитата

А указатели не надо использовать?

Строка - это уже указатель. ТУт в одном месте используется динамическая память.
Цитата

А можно пояснения на русском языке?

ИМХО, в данной программе комменты и на английском очень информативны (лень мне переписывать).

Суммируя вышесказанное, хочу сказать: сначала посмотри, что тебе предложили. И попытайся разобраться. И задавай вопросы по существу.  Приятней общаться с человеком (даже если это и девушка), которого интересует не только результат. smile 


--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
anad
Дата 1.12.2006, 01:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Что означает?
Код

int    tail = 0;

Эти строки не понятны:
Код

if(!(res = (char*) calloc(len + 1, sizeof(char))))


Код

if(str[k] == ' ')


Что такое i и j и почему равны нулю в 84 строке.
И еще не понятна строка 140.


PM MAIL   Вверх
Kuvaldis
Дата 1.12.2006, 02:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


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

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



anad
Идея алгоритма:
1. Получаем на вход строку
2. Считаем количество слов count в этой строке.
3. считаем количество необходимых пробелов в строке. Оно равно gapkol = максимальная длина строки - длина входной строки - количество проблелов во введенной строке.
Данные пробелы нужно равномерно (!) распределить между словами. Если слов К шт., то количество групп пробелов между словами = К - 1.
Между словами должно быть по возможности одинаковое кол-во пробелов. Разделим
step = gapkol / count;               
ost = gapkol % count;     

strep - это количетство пробелов, которое всегда будет записываться.
ost - будет меняться, это остаток от деления gapcol на количество слов.

Например, у нас 4 слов и 14 пробелов.
Тогда 
step = 14 / 4 = 3
ost = 2
Значит,  у нас будет 2 группы пробелов по (2 + 1) = 4  символа, и 2 группы по 3 символа (мы "лишние" проблелы из ost распределяем по одному в каждую группу путем прибавления "хвоста" tail к основному количеству, пока их количество не станет нулем) 
В алгоритме еще отстлеживаются ситуации, когда количество слов равно 1, т.е. делать ничего не надо (или нужно просто убрать ведущие пробелы).
  
  
Цитата

if(!(res = (char*) calloc(len + 1, sizeof(char))))

это динамическое выделение памяти под временную строку. Сначала мы получаем правильную временную строку, а потом уже в конце копируем ее в старую.

Цитата

Что такое i и j и почему равны нулю в 84 строке.

i - это указатель на текущий символ во входной строке
j - указатель на текущий символ в выходной строке 
Индексы не совпадают, так как в выходную строку мы после каждого найденного слова дописываем необходимое количество пробелов.

Цитата

if (!isspace(str[i])) 

Если текущий символ не является символом-разделителем (по умолчанию пробелы и некоторые другие).


--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
anad
Дата 1.12.2006, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



А что такое k, count и почему res=0 изначально?
 str[i]='  ';  ?
n=strlen(str);  ?
Я так понимаю в задачи две функции?

Добавлено @ 13:51 
Забыла еще спросить, зачем нужны библиотеки: 
#include <stdlib.h> и
#include <ctype.h> ?
PM MAIL   Вверх
anad
Дата 1.12.2006, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Не понятна разница между:
Код

count = get_words_count(str);
    n = strlen(str);
    if ((count == 1) && (str[0] != ' '))  // if only one word and no leading gaps
    {
      for(i = n; i < len; i++)           // fill following spaces with gaps
         str[i] = ' ';
      return 1;
    }

и
Код

if (count == 0)             // if only one word  //ПОЧЕМУ только 1 слово?ведь приравнивается к 0.          
{
       while ((i < n) && (str[i] != ' '))  // copy word in res
          res[j++] = str[i++];
       for (i = 0; i < gapkol; i++)        //add gaps into str end
          res[j++] = ' ';
       strcpy(str, res);                  // restore str
       str[len - 1] = '\0';
       free(res);
       return 1;
    }



А это зачем?
Код

gapkol = len - n;   // following gaps count
    count--;            // count of gaps groups

и
Код

if(str[k] == ' ')
gapkol++;


И последний вопрос, как выводятся числа?


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


Шустрый
*


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

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



Может проще как-нибудь можно решить?
PM MAIL   Вверх
ivashkanet
Дата 1.12.2006, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

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



Блин, а сами будем что-нибудь делать?
По полочкам им разложили, код дали.
Что еще сделать? 
Разжевать и в рот положить?

Давайте-ка сами подумайте.
Никто а вас всю работу делать не будет.
А если хотите чтобы сделали, то вам сюда.

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


механик-вредитель
***


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

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



anad
идею проще, чем я тебе описал, не придумать...
Если хочешь, можешь сама сделать...
ты мне напомнила анекдот
Тетя звонит в online поддержку и говорит:
-Я устанавливаю Вашу программу с комплекта дискет. Мне поступают сообщения "Вставьте следующую дискету" Я уже 5 с трудом вставила а 6-я не влезает. И что мне прикажете делать?

Есть очень хороший способ узнать, зачем нужно то или иное описание - удали строку и посмотри, какие ошибки будут...
Зачем нужны те или иные переменные?
запусти программу по шагам и посмотри в явном виде, как она работает и куда что пишется..


--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
anad
Дата 1.12.2006, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Ок!Спасибо! Намучились наверное со мной.
PM MAIL   Вверх
Rockie
Дата 2.12.2006, 00:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(anad @  29.11.2006,  21:39 Найти цитируемый пост)
Программа, выравнивающая текст по правому краю, т.е. равномерно размещающая по строке пробелы между словами так, чтобы длина каждой строки стала=n.

В свое время делал но на С++, со string. На красоту в данном случае не претендую, но все равно выложу, раз тему такую подняли. =)

Код
#include<iostream>

using namespace std;

int main()
{  string str = "here is a simple string";
   int num_spaces = 0;                 // кол-во пробелов в нашей строке
   int first = 0;

  // ПОДСЧИТЫВАЕМ КОЛ-ВО СУЩЕСТВУЮЩИХ ПРОБЕЛОВ
   first = str.find(" ");              // находим позицию первого пробела
   if(first!=-1) num_spaces++;

   // на случай, если пробелов в строке вообще нет
   else { cout<<"error, there is no spaces"; return 1;}

   while(1)                            // подсчитываем сумму пробелов
     { first = str.find(" ",first+1);
       if(first==-1) break;
       num_spaces++;
     }

  // ПОДСЧИТЫВАЕМ, СКОЛЬКО ПРОБЕЛОВ НАДО ДОБАВИТЬ,
  // если считать что длина строки 80 символов
   int space_to_add = ( (80 - str.length()) / num_spaces );

  // ДОБАВЛЯЕМ ПРОБЕЛЫ
   first = str.find(" ");             // сначала к первому
   str.insert(first, space_to_add, ' ');

   while(1)                           // а затем ко всем последующим
     { first = str.find(" ",first+space_to_add+1);
       if(first==-1) break;
       str.insert(first, space_to_add, ' ');
     }

  cout<<str;

  cin.get();
  return 0;
}


Это сообщение отредактировал(а) Rockie - 2.12.2006, 00:13


--------------------
Чтобы иметь большой гардероб - надо иметь большой гардероб.
PM   Вверх
Страницы: (4) Все 1 2 [3] 4 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

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

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


 




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


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

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