Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

FAQ - часто задаваемые вопросы

242
22 ноября 2006 года
Оlga
2.2K / / 04.02.2006
Здесь постим решения, ссылки на темы, где есть решения на часто задаваемые вопросы.

[COLOR=purple]Ищем исходники[/COLOR] здесь.

Если в приведенных здесь решениях есть ошибки, просьба сообщить мне об этом. Спасибо.
Страницы:
242
22 ноября 2006 года
Оlga
2.2K / / 04.02.2006
Написать программу, которая переводит числа из СС(система счисления) P в СС Q.
P, Q - произвольные СС.

Language C
242
22 ноября 2006 года
Оlga
2.2K / / 04.02.2006
[COLOR=darkorchid]1 - программа, которая проверяет, является ли строка полиндромом:[/COLOR]

Код:
#include <stdio.h>
#include <string>
bool isPolindrome(char *str)
{
 int n = strlen(str);
 int i, j;
 for(i = 0, j = n - 1; i < j; i++, j--)
  if(str != str[j])
   return false;
 return true;
}
void main(void)
{
 printf("%s\n\n", isPolindrome("ABA") ? "true" : "false");
}


[COLOR=darkorchid]2 - программа, которая проверяет, является ли введенное пользователем число полиндромом:[/COLOR]

Language C
Код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int isPolindrome(int num)
{
    char str[11];
    int i, j;
 
    itoa(num, str, 10); //переводим число в строку
 
    for(i = 0, j = strlen(str)-1; i < j; i++, j--)
        if(str != str[j]) return 0; // num isn't polindrome
 
    return 1; // num is polindrome
 
 
}
 
int main(void)
{
    int n;
    printf("Enter a number: ");
    scanf("%d", &n);
    if( isPolindrome(n) )
        printf("Number %d is polindrome\n\n", n);
    else
        printf("Number %d isn't polindrome\n\n", n);
    return 0;
}
242
22 ноября 2006 года
Оlga
2.2K / / 04.02.2006
[quote=Question]"Напишите задачу обработки кольцевого списка, решающего задачу Джозефуса.
Задача представляет собой своего рода считалку:элементы становяться в "круг", вводиться
некоторое число.Необходимо, начиная с первого элемента, отсчитать к-ый элемент списка и удалить его.Далее отсчет начинается с (к+1)-го элемента и опять удаляется к-ый элемент.Так продолжается
то тех пор,пока в списке не останеться один элемент.Выдать содержимое последнего оставшегося элемента"[/quote]

Language C/C++
Код:
#include <stdio.h>
#include <stdlib.h>
 
typedef struct node{
    char c;
    struct node *next;
    struct node *prev;
}List;
/*функция которая получает указатель на первый элемент двунаправленного списка(head), и возвращает указатель на последний элемент в списке(который не удалили).*/
List *func(List *head, int k)
{
    List *move = head, *temp = NULL;
    int counter = 0;
 
    while(move != move->next)
    {
        for(counter = k-1; counter; counter--, move = move->next);
        move->prev->next = move->next;
        move->next->prev = move->prev;
        temp = move;
        move = move->next;
        free(temp);
    }
 
 
    return move;
 
}
242
03 декабря 2006 года
Оlga
2.2K / / 04.02.2006
[COLOR=green][COLOR=green]/* одномерный массив */[/COLOR][/COLOR]
Код:
[COLOR=black]int *arr;  [/COLOR][COLOR=#008080]/* объявление указателя на массив */[/COLOR]
[COLOR=black]int  n;  [/COLOR][COLOR=seagreen] /* объявление переменной под кол-во элементов в массиве */[/COLOR]
int i;     [COLOR=#008080]/* объявление индексa для работы с массивом */[/COLOR]
 
[COLOR=black]printf("Enter size of array: ");[/COLOR]
[COLOR=black]scanf("%d", &n);[/COLOR]
 
[COLOR=#008080]/* выделение памяти под массив */[/COLOR]
[COLOR=black]arr = (int*)malloc(n*sizeof(int));[/COLOR]
 
[COLOR=teal]/* заполняем массив и сразу расспечатываем */[/COLOR]
[COLOR=green][COLOR=black]for(i = 0; i < n; i++)[/COLOR]
[COLOR=green]{[/COLOR]
[COLOR=black]arr = i+1;[/COLOR]
[COLOR=black]printf("%4d", arr);[/COLOR]
[COLOR=green]}[/COLOR]
/*освобождаем память когда массив уже не нужен(как минимум в конце программы)*/[/COLOR]
free(arr);


[COLOR=black]============================================================[/COLOR]

[COLOR=green]/* двумерный массив */[/COLOR]

Код:
float **matrix; [COLOR=teal]/* объявление указателя на массив */[/COLOR]
int row, col; [COLOR=teal]/* объявление переменных под кол-во строк и столбцов*/[/COLOR]
int i, j;  [COLOR=teal]/* объявление индексов для работы с массивом */[/COLOR]
 
printf("Enter the amount of rows & columns: ");
scanf("%d%d", &row, &col);
 
[COLOR=teal]/* выделение памяти под строки */[/COLOR]
matrix = (float**)malloc(row * sizeof(float*));  
 
[COLOR=teal]/* выделение памяти под столбцы */[/COLOR]
for ( i =0; i<row; i++ )  
  matrix = (float*)malloc(col * sizeof(float));
 
[COLOR=teal]/* заполняем массив и сразу расспечатываем */[/COLOR]
for(i = 0; i < row; i++)
{
  for(j = 0; j < col; j++)
  {
     matrix[j] = (i+j)*1.1f;
     printf("%4.1f    ", matrix[j]);
  }
  putchar('\n');
}
/*освобождаем память когда массив уже не нужен(как минимум в конце программы)*/
242
03 декабря 2006 года
Оlga
2.2K / / 04.02.2006
[quote=Question]
9 10 11 12 13
8 21 22 23 14
7 20 25 24 15
6 19 18 17 16
5 4 3 2 1
[/quote]

функция которая заполняет массив по спирали C++

Цитата:

1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9


решение нa Delphi/Pascal

242
03 декабря 2006 года
Оlga
2.2K / / 04.02.2006
Библиотека для работы с матрицами. Delphi
http://sources.codenet.ru/download/814/MatrixAPI.html

Автор: 3A3-968M
242
13 декабря 2006 года
Оlga
2.2K / / 04.02.2006
Данная функция получает 1 параметр - число N, и возвращает сумму цифр этого числа. Например: N == 9372, функция возвращает 21 <=> 9+3+7+2.
Код:
int digitsSumOfNum(int n)
{
   int sum = 0;
   while(n)
   {
        sum += (n % 10);
        n /= 10;
   }
 
   return sum;
}
242
27 декабря 2006 года
Оlga
2.2K / / 04.02.2006
функция mulmatr получает как параметры 3 матрицы: А, B, С, умножает матрицу А на матрицу B, а результат сохраняет в матрице С.

Код:
#include <stdio.h>
#include <stdlib.h>
#define ROW 4
#define COL 3
#define N 3
 
void mulmatr(int A[ROW][N], int B[N][COL], int C[ROW][COL])
{
    for(int i = 0; i < ROW; i++)
        for(int j = 0; j < COL; j++)
        {
            C[j] = 0;
            for(int k = 0; k < N; k++)
                C[j] += (A[k] * B[k][j]);
        }
}
242
27 декабря 2006 года
Оlga
2.2K / / 04.02.2006
Код:
#include <stdio.h>
#define N 5
void printmatrix(int [][N]);
int main(void)
{
 
    int arr[N][N] = { {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}  };
    int i, j;
    printmatrix(arr);
 
    for(i = 0; i < N-1; i++)
    {
        j = i+1;
        do{
            int temp = arr[j];
            arr[j] = arr[j];
            arr[j] = temp;
        }while(++j < N);
    }
 
    printmatrix(arr);
    putchar('\n');
    return 0;
 
}
void printmatrix(int m[][N])
{
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < N; j++)
            printf("%4d", m[j]);
        putchar('\n');
    }
    putchar('\n');
}
63
06 января 2007 года
Zorkus
2.6K / / 04.11.2006
В какой-то теме, вроде паскаль, мне попадались вопросы по псевдослучайным числам, и про якобы сложность их генерации.
Если нужно генерировать ПСЧ в криптографических функциях, то это действительно бывает непросто. Но для "бытовых" генераторов используются следующие алгоритмы генерации - примеры того как эти функции были реализованы в некоторых прошлых версиях популярных компиляторов.
Итак -
Код:
static unsigned int seed;
 
// gcc
unsigned int rand()
{
   unsigned int seed = seed * 69069 + 5;
   return (seed >> 0x10) & 0x7FFF;  
}
 
// Borland C++ for OS/2
unsigned int rand()
{
   unsigned int seed = seed * 0x15A4E35u + 1;
   return (seed >> 0x10) & 0x7FFF;
}
 
// Microsoft Visual C++
unsigned int rand()
{
   unsigned int seed = 0x343FD * seed + 0x269EC3;
   return (seed >> 0x10) & 0x7FFF;
}

P.S. Не ручаюсь за точность констант в конкретных версиях, это лишь примеры:)
242
29 января 2007 года
Оlga
2.2K / / 04.02.2006
[quote=Question]
Даны действительные числа a1, ..., an. Получить квадратную матрицу порядка n:

a1 a2 a3 ... an-2 an-1 an
a2 a3 a4 ... an-1 an a1
a3 a4 a4 ... an a1 a2
............................................
an a1 a2 ... an-3 an-2 an-1[/quote]
http://forum.codenet.ru/showthread.php?t=34356
http://forum.codenet.ru/showpost.php?p=163192&postcount=7
242
05 февраля 2007 года
Оlga
2.2K / / 04.02.2006
функция strpack принимает 2 параметра: первый параметр - обязательный, указатель на строку, второй - опциональный(можно и не передовать), передаем, если надо удалить последовательные дубликаты какого-то конкретного символа. т.е. можно использовать данную функцию в 2 случаях:
1)для удаления дубликатов(повторов) всех символов, если они рассположены последовательно(подряд)
например: "aaabbf ttr...."
результат: "abf tr."
2)для удаления последовательных повторов указанного символа (например символ точка)
например: "aabbf ttr...."
результат: "aabbf ttr."
функцию написал Lerkin

Код:
void strpack( char* str, char tok = '\0' )
{
    char *src = str, *ptr = str;
    while( *ptr++ )
         if( *ptr != *src || (tok && *ptr != tok) )
                 *(++src) = *ptr;
}
void main(void)
{
 char str1[] = "aaaaaaaaaabcb fjjgj..... hjk. kltt...";
 char str2[] = "asssdds fghh..... rty jkl........";
 puts(str1);
 strpack(str1);
 puts(str1);
 puts("\n\n");
 puts(str2);
 strpack(str2, '.');
 puts(str2);
 puts("\n\n");
 
}
242
06 февраля 2007 года
Оlga
2.2K / / 04.02.2006
производные функции от функции strpack:

1 - delch - удаляет последовательно рассположенные дубликаты символа ch
 
Код:
void delch(char *src, char ch)
{
 char *ptr = src;
  while( *ptr++ )
       if( *ptr != *src || *ptr != ch)
            *(++src) = *ptr;
}

2 - deldup - удаляет все последовательно рассположенные дубликаты символов
 
Код:
void deldup(char *src)
{
 char *ptr = src;
  while( *ptr++ )
      if( *ptr != *src)
           *(++src) = *ptr;
}
257
13 февраля 2007 года
kosfiz
1.6K / / 18.09.2005
Dev-C++
удобная среда разработки приложений на С++ и С: присутствует автодополнение кода, подсветка синтаксиса, поставляется вместе с компилятором mingw(порт gcc под Windows), в пакете также имеется отладчик gdb, примеры, файл справки, и плюс ко всему простой и удобный интерфейс - для студентов вещица просто необходимая. размер всего 9 Мб.

Если есть вопросы, то задаём их здесь.
[URL="http://forum.codenet.ru/showthread.php?t=34580"]Dev-C++, кто работал? [/url]
242
20 февраля 2007 года
Оlga
2.2K / / 04.02.2006
Возведение в степень на C/С++
320
20 марта 2007 года
m_Valery
1.0K / / 08.01.2007
Вариант 1-ий . C/C++
#include "windows.h". Создаем функцию
 
Код:
void RussianMessage(char *str){
   char message[100];
   CharToOem(str,message);
   cout<<message; [COLOR="Green"]// или для С: puts(message); или printf("%s", message);[/COLOR]
}

в main вызываем ее так
 
Код:
...
  RussianMessage("русский текст в консоли");
  ...

Unicode должен быть отключен в Project -> Properties -> Character Set ->
Use Multi-Byte Character Set(а не Use Unicode Character Set).
Вариант 2-ой. C++
Код:
#include "stdafx.h"
#include <locale>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    std::wcout.imbue(std::locale("Russian_russia.OCP"));
    std::wcout << L"русский текст в консоли";
    cout<<endl;
    return 0;
}
242
25 марта 2007 года
Оlga
2.2K / / 04.02.2006
[COLOR=purple]------------------------------------------------------------------------------------[/COLOR]
  • [COLOR=purple]Написать программу, подсчитывающую количество символов ASCII в строке.[/COLOR]
[COLOR=purple]------------------------------------------------------------------------------------[/COLOR]
Код:
#include <stdio.h>
#include <string.h>
 
int main(void)
{
 char str[255];
[COLOR=seagreen]/* размер вспомагательного массива-счётчика равен кол-ву символов ASCII */[/COLOR]
 const int size_counter = 256;
[COLOR=#2e8b57]/* вспомогательный массив-счётчик counter, для подсчёта кол-ва символов */[/COLOR]
 int counter[size_counter] = {0};
 int i;
 
[COLOR=#2e8b57]/* ввод строки с клавиатуры */[/COLOR]
 puts("Enter a string:");
 gets(str);
 
[COLOR=#2e8b57]/* подсчет различных символов в строке */[/COLOR]
 for(i = 0; str; i++)
  counter[str]++;
 
[COLOR=#2e8b57]/* вывод результата на экран */[/COLOR]
 for(i = 0; i < size_counter; i++)
  if(counter)
   printf("%3c - %d\n", i, counter);
 
 return 0;
 
}

[COLOR=purple]------------------------------------------------------------------------------------[/COLOR]
  • [COLOR=purple]Написать программу, подсчитывающую количество букв англ. алфавита в строке (кодировка ASCCI). В строке могут быть символы как вернего так и нижнего регистра. Программа считает общеe кол-во для каждой буквы, т.е. не делает различия между большими и маленькими буквами.[/COLOR]
[COLOR=purple]------------------------------------------------------------------------------------[/COLOR]
Код:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
 
int main(void)
{
  char str[] = "aaAAbsdfgrtyPPPOP";
  const int size_counter = 26;
  int counter[size_counter] = {0};
  int i;
 
[COLOR=#2e8b57]/* подсчет различных букв в строке */[/COLOR]
  for(i = 0; str; i++)
    if(islower(str))
      counter[str-'a']++;
    else
      counter[str-'A']++;
 
[COLOR=#2e8b57]/* вывод результата на экран */[/COLOR]
  for(i = 0; i < size_counter; i++)
    if(counter)
      printf("%3c/%c - %d\n", i+'A', i+'a', counter);
 
  return 0;
 
}

[COLOR=purple]--------------------------------------------------------------------------------------[/COLOR]
  • [COLOR=purple]Расспечатать таблицу кодов ASCII и символов, который данный код обозначает.[/COLOR]
[COLOR=purple]------------------------------------------------------------------------------------[/COLOR]
Код:
#include <stdio.h>
 
int main(void)
{
  for(int i = 0; i <= 255; i = i+1)
  {
    printf("%d - ", i);  [COLOR=seagreen]/* расспечатываем i как integer */[/COLOR]
    printf("%c \n", i);  [COLOR=seagreen]/* расспечатываем i как char */[/COLOR]
  }
  return 0;
}
320
27 августа 2007 года
m_Valery
1.0K / / 08.01.2007
В своей книге "The C++ Programming Language",3-е издание Бьярн Страуструп описывает интерфейсный класс для обычных массивов.Этот класс гораздо надежнее обычных массивов и не уступает им по быстродействию.Страуструп пишет:
Цитата:
"Возможно иногда полезнее представить обычный массив в таком виде который обеспечил бы удобства стандартного контейнера без изменения его природы на низком уровне"


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

Код:
#include <cstddef>
template<class T,std::size_t thesize>
class carray{
private:
    T v[thesize];//массив фиксированного размера
public:
//Определения типов
    typedef T value_type;
    typedef T* iterator;
    typedef const T* const_iterator;
    typedef T& reference;
    typedef const T& const_reference;
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;
//Поддержка итераторов
    iterator begin(){ return v; }
    const_iterator begin() const { return v; }
    iterator end(){ return v + thesize; }
    const_iterator end() const { return v + thesize; }
//Прямой доступ к элементам
    reference operator[](std::size_t i) { return v; }
    const_reference operator[](std::size_t i) const { return v; }
//Фиксированный размер
    size_type size() const { return thesize; }
    size_type max_size() const { return thesize; }
//Преобразование к обычному массиву
    T* as_array(){ return v; }
};

Контейнер carray можно использовать со стандартными алгоритмами, применяя begin(),end()...
Пример использования:
Код:
#include <iostream>
#include <algorithm>
#include <functional>
#include "c_array.cpp"
#include <ctime>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    srand(time(0));
    carray<int,10> a;
    for(unsigned i = 0;i < a.size();++i)
        a = i + 1;
    copy(a.begin(),a.end(),
        ostream_iterator<int>(cout," "));
    cout<<endl;
    reverse(a.begin(),a.end());
    copy(a.begin(),a.end(),
        ostream_iterator<int>(cout," "));
    cout<<endl;
    transform(a.begin(),a.end(),
        a.begin(),
        negate<int>());
    copy(a.begin(),a.end(),
        ostream_iterator<int>(cout," "));
    cout<<endl;
    carray<float,5> b;
    for(unsigned i = 0;i < b.size();++i)
        b = rand() / (float)32767 * 20 - 10;
    copy(b.begin(),b.end(),
        ostream_iterator<float>(cout," "));
    cout<<endl;
    return 0;
}

Создаем контейнер целых чисел,заполняем его числами от 1 до 10.Для показа контейнера используем алгоритм copy.Далее меняем при помощи алгоритма reverse порядок элементов на обратный, распечатываем, используем алгоритм transform для того чтобы поменять знак каждого элемента на обратный,распечатываем.Далее создаем контейнер типа float...
Более подробно смотри Бьерн Страуструп "Язык программирования С++.Специальное издание", Москва,Бином-Пресс,2007 год.глава 17.5.4,стр.555.Николай Джосюттис "Стандарнтная библиотека С++.Для профессионалов" Питер,2004 год,стр.224.
320
27 августа 2007 года
m_Valery
1.0K / / 08.01.2007
Герб Саттер пишет:
Цитата:
Большинство программистов слышали о стандартном интеллектуальном указателе auto_ptr,но далеко не все постоянно его применяют.Это досадно,так как auto_ptr в состоянии решить многие из распространенных проблем С++ и его разумное использование приводит к повышению качества кода.


auto_ptr - всего лишь один из множества существующих интеллектуальных указателей.Многие коммерческие библиотеки предоставляют свои более интеллектуальные реализации.
auto_ptr - cтандартный и "простой" интеллектуальный указатель общего назначения,способный к качественному решению обычных повседневно встречающихся задач.Б.Страуструп говорит о том,что auto_ptr реализует технику "выделение ресурса есть инициализация", более подробно рассмотренную во 2-м изданиие "The C++ Programming Language".
Вот простой пример кода,который небезопасен,если не использовать auto_ptr

 
Код:
...
void f()
{
    ClassA* ptr = new ClassA;// создание обьекта
    ... // выполнение операций
   delete ptr;//уничтожение обьекта
}

При использовании подобного кода нередко возникаютпроблемы.Первая -можно забыть об удалении обьекта ,особенно если внутри ф-ии есть команды return,расположенные до delete.Вторая - во время выполнения может произойти исключение,что приведет к немедленному выходу из ф-ии без выполнения delete.Мы получим классическую утечку памяти.
Перехватим:
Код:
...
void f()
{
     ClassA* ptr = new ClassA;// создание обьекта
     try{
      ...// работа с обьектом
     }
     catch(...){
       delete ptr;
       throw;
    }
   delete ptr;
}

Освобождение обьекта при исключении приводит к появлению лишнего кода.Если по такой схеме обрабатывается не один а несколько обьектов или имеется несколько секций catch,программа становится еще более запутанной.Это пример плохого стиля программирования.
Теперь смотрим как выглядит код с использованием auto_ptr
 
Код:
...
#include <memory>

void f()
{
    std::auto_ptr<ClassA> ptr(new ClassA);
   ...// работа с указателем
}

Что мы сделали ? Мы завернули указатель в интеллектуальный указателеподобный обьект, который владеет указателем,а при уничтожении автоматически удаляет обьект,на который тот ссылается. Т.о.auto_ptr - автоматический обьект,автоматически уничтожающийся при выходе из области видимости и поэтому его вполне обоснованно назвали "aвтоматический" указатель.
Такой код полностью безопасен,никаких утечек памяти не будет независимо от того осуществляется ли выход из ф-ии нормально или посредством исключения,поскольку деструктор будет вызван в любом случае.Освобождение ресурсов выполняется автоматически.Интерфейс указателя auto_ptr почти ничем не отличается от интерфейса обычного указателя:оператор * производит разыменование обьекта,на который ссылается указатель,а оператор -> предоставляет доступ. Математические операции (такие как ++ ) для auto_ptr не определены.auto_ptr не позволяет инициализировать обьект обычным указателем в конструкторе,инициализация должна производится напрямую по значению.
 
Код:
...
std::auto_ptr<ClassA> ptr(new ClassA); // Ok !!!
std::auto_ptr<ClassA> ptr = new ClassA;//ERROR!!!
320
27 августа 2007 года
m_Valery
1.0K / / 08.01.2007
Пример демонстрирует передачу права владения при работе с auto_ptr:
Код:
#include <iostream>
#include <memory>
#include <ctime>
using namespace std;
template<class T>
ostream &operator<<(ostream &strm,const auto_ptr<T>& p){
    if(p.get() == NULL){
       strm<<"NULL"<<endl;
    }
   else{
       strm<<*p<<endl;
   }
   return strm;
}
int _tmain(int argc, _TCHAR* argv[])
{
    srand(time(0));
    wcout.imbue(locale(".866"));
    auto_ptr<int> a(new int(rand() % 100));
    auto_ptr<int> g;
    wcout<<L"\tпосле инициализации"<<endl;
    cout<<"a = "<<a;
    cout<<"g = "<<g;
    g = a;
    wcout<<L"после присваивания g = a"<<endl;
    cout<<"a = "<<a;
    cout<<"g = "<<g;
    *g += 13;
    a = g;
    wcout<<L"после модификации + 13"<<endl;
    cout<<"a = "<<a;
    cout<<"g = "<<g;
    auto_ptr<int> ps(new int(12));
    cout<<"ps = "<<ps;
    *ps = 124;
    cout<<"ps = "<<ps<<endl;
    return 0;
}

Всем изучающим С++ рекомендуется изучение и использование auto_ptr.Увы,не представляется возможным рассмотреть тут более сложные примеры.За более подробной информацией смотреть
Бьярн Страуструп "Язык программирования С++.Специальное издание." стр.420
Герб Саттер "Решение сложных задач на С++"стр.257 - 275
Андрей Александреску "Современное проектирование на С++"стр.179-216(создание своего класса интеллектуального указателя SmartPtr, на основе стратегий).
320
31 августа 2007 года
m_Valery
1.0K / / 08.01.2007
Динамический двумерный массив на С++,вводим желаемое количество строк и столбцов,создаем,простое меню,фунции печати,добавления строки и столбца,удаление строки или столбца,освобождение памяти.Все реализовано через указатели,операторы new и delete.
Преподы часто дают такой пример для сдачи зачета по теме "Указатели и массивы".Предназначен только для студенческих задач, лучше использовать двумерный вектор.
Код:
#include <iostream>
#include <iomanip>
#include <ctime>
using namespace std;
int Menu();// Меню
void OutMatrix(int**, int, int);// Вывод на экран матрицы
int** AddRow(int**, int&, int, int);// Добавить строку
int** AddCol(int**, int, int&, int);// Добавить столбец
int** DelRow(int**, int&, int, int);// Удалить строку
int** DelCol(int**, int, int&, int);// Удалить столбец
int _tmain(int argc, _TCHAR* argv[])
{
    wcout.imbue(locale(".866"));//Руссификация консоли
             srand(time(0));
    int row,col,menu = 0,index = 0;
    do{
     wcout<<L"Введите количество строк"<<endl;
     cin>>row;
    }while(row <= 0);
    do{
     wcout<<L"Введите количество столбцов"<<endl;
     cin>>col;
    }while(col <= 0);
    int **m = new int*[row];// матрица
    // Создаем матрицу
    for(int i = 0;i < row;++i){
       m = new int[col];
       for(int j = 0;j < col;++j)
            m[j] = rand() %100;// заполняем случ.числами
    }
    system("cls");// очистка консоли
    OutMatrix(m, row, col);

    while(menu != 5){
        menu = Menu();
        switch(menu){  
        case 1:
            wcout<<L"Индекс: ";
            cin>>index;
            m = AddRow(m, row, col, index);
            break;
        case 2:
            wcout<<L"Индекс: ";
            cin>>index;
            m = AddCol(m, row, col, index);
            break;
        case 3:
            if(row == 1) wcout<<L"Нельзя удалить!\n";
            else{
                wcout<<L"Индекс: ";
                cin>>index;
                m = DelRow(m, row, col, index);
            }
            break;
        case 4:
            if(row == 1) wcout<<L"Нельзя удалить!\n";
            else{
                wcout<<L"Индекс: ";
                cin>>index;
                m = DelCol(m, row, col, index);
            }
            break;
        case 5:
            exit(0);
        default:
            system("cls");
            wcout<<L"Неверный идентификатор!\n";
            break;
        }
        system("cls");
        OutMatrix(m, row, col);
    }
    for(int i=0;i<row;i++)// Освобождение памяти
        delete[] m;
    delete[] m;
    return 0;
}
int Menu(){
    int answer=0;
    wcout<<L"\n\n1. Добавить строку\n2. Добавить столбец\n3. Удалить строку\n4. Удалить столбец\n5. Выход\n";
    cin>>answer;
    return answer;
}
void OutMatrix(int **m, int row, int col){
    wcout<<L"\tМатрица"<<"\n\n";
    for(int i=0;i<row;i++){
        for(int j=0;j<col;j++)
            cout<<setw(4)<<m[j];
        cout<<"\n\n";
    }
}

int** AddRow(int **m, int &row, int col, int index){
    if(index > row){
        system("cls");
        return m;
    }
    int **temp = new int*[++row];
    for(int i=0;i<row;i++){
        if(i < index) temp = m;
        else if(i > index) temp = m[i-1];
        else{
            temp = new int[col];
            for(int j=0;j<col;j++)
                temp[j] = rand()%100;
        }
    }
    delete[] m;
    return temp;
}
int** AddCol(int **m, int row, int &col, int index){

    if(index > col){
        system("cls");
        return m;
    }
    col++;
    int **temp = new int*[row];
    for(int i=0;i<row;i++){
        temp = new int[col];
        for(int j=0;j<col;j++){
            if(j == index) temp[j] = rand()%100;
            else if(j > index) temp[j] = m[j-1];
            else temp[j] = m[j];
        }
    }
    for(int i=0;i<row;i++) delete[] m;
    delete[] m;
    return temp;
}
int** DelRow(int **m, int &row, int col, int index){

    if(index >= row){
        system("cls");
        return m;
    }
    int **temp = new int*[--row];
    for(int i=0;i<row+1;i++){
        if(i < index) temp = m;
        else if(i > index) temp[i-1] = m;
        else delete[] m;
    }
    delete[] m;
    return temp;
}
int** DelCol(int **m, int row, int &col, int index){
    if(index >= col){
        system("cls");
        return m;
    }
    col--;
    int **temp = new int*[row];
    for(int i=0;i<row;i++){
        temp = new int[col];
        for(int j=0;j<col+1;j++){
            if(j < index) temp[j] = m[j];
            if(j > index) temp[j-1] = m[j];
        }
    }
    for(int i=0;i<row;i++) delete[] m;
    delete[] m;
    return temp;
}

Небольшое оnступление:не создавайте динамический массив с помощью auto_ptr.Этого так просто сделать нельзя,т.е:
 
Код:
...
auto_ptr<T> p(new T[n]);// Неправильно
...

Такой код может компилироваться,но работать будет неправильно,мы можем ожидать утечку памяти.Происходит вот что:каждый delete должен соответствовать виду своего new.Если вы используете new для одного обьекта,то должен использоваться и delete для одного обьекта.
new - использовать потом - delete
new[] - использовать потом - delete[]
Иначе получаем неопределенное поведение программы.auto_ptr всегда указывает на одиночный обьект,поэтому для его освобождения он всегда вызывает только delete,но не delete[].
320
05 сентября 2007 года
m_Valery
1.0K / / 08.01.2007
Условие : создать одномерный динамический массив( получаем случайный размер от 10 до 20),заполнить его последовательностью целых чисел начиная с 1 в возрастающем порядке.Переставить элементы массива случайным образом(наподобие тасование колоды).
Код:
#include <iostream>
#include <ctime>
using namespace std;
void shuffle(int *a,int s[COLOR="SeaGreen"]);// ф-ия перестановки[/COLOR]
int _tmain(int argc, _TCHAR* argv[])
{
    srand(time(0)); [COLOR="SeaGreen"]//рандомизация[/COLOR]
    int size;//размер массива
    size = rand() % 10 + 10; [COLOR="SeaGreen"]//получаем в диапазоне от 10 до 20[/COLOR]
             cout<<"Size : "<<size<<endl;
    int *mass = new int[size];[COLOR="SeaGreen"] //динамический массив[/COLOR]            
            for(int i = 0;i < size;++i) [COLOR="SeaGreen"]// заполняем числами[/COLOR]
        mass = i + 1;
             for(int i = 0;i < size;++i) [COLOR="SeaGreen"]//печатаем[/COLOR]
                 cout<<mass<<' ';  
    cout<<endl;
    cout<<"After shuffle"<<endl;
    shuffle(mass,size); [COLOR="SeaGreen"]// перестановка[/COLOR]
    for(int i = 0;i < size;++i) [COLOR="SeaGreen"]//печатаем[/COLOR]
        cout<<mass<<' ';
    cout<<endl;
    delete[] mass; [COLOR="SeaGreen"]//удаляем[/COLOR]
    return 0;
}
void shuffle(int *a,int s)
{
    for(int i = 0;i < s;++i){
      int j = rand() % s;
      int temp = a;
      a = a[j];
      a[j] = temp;
    }
}

Теперь смотрим как это решение выглядит,если мы используем STL контейнер и обощенные алгоритмы.
Код:
#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    srand(time(0));
    int size = rand() % 10 + 10;[COLOR="SeaGreen"] // получаем размер[/COLOR]
    vector<int> coll; [COLOR="SeaGreen"]// пустой вектор целых чисел[/COLOR] 
             cout<<"\size : "<<size<<endl;
    for(int i = 0;i < size;++i)[COLOR="SeaGreen"] //заполняем числами[/COLOR]
        coll.push_back(i + 1);
    copy(coll.begin(),coll.end(),
        ostream_iterator<int>(cout," ")); [COLOR="SeaGreen"]// печатаем[/COLOR]
    cout<<"\nAfter random_shuffle"<<endl;
    [COLOR="SeaGreen"]//перестановка элементов в случайном порядке при помощи
    // обобщенного алгоритма random_shuffle[/COLOR]
    random_shuffle(coll.begin(),coll.end());
    copy(coll.begin(),coll.end(),
        ostream_iterator<int>(cout," ")); [COLOR="SeaGreen"]//печатаем[/COLOR]
    cout<<endl;
    return 0;
}
320
09 сентября 2007 года
m_Valery
1.0K / / 08.01.2007
Условие : написать класс двумерного массива таким образом,чтобы можно было создавать обьект так matrix a(4,5) , а значения отдельных элементов менять так
a[0][0] = 11;
a[1][1] = 22;

Это задачу любят давать на экзамене по С++.
Два варианта решения.
1 - й вариант.
Код:
...
class matrix;
class Row{
public:
    Row(const matrix* m,int r) : row(r),array(m)    {}
    int &operator[](int index);
private:
     const matrix* array;
     int row;
};
class matrix
{
    friend class Row;
    friend ostream &operator << (ostream &, matrix &);
public:
    matrix (int,int);
    ~matrix();
    Row operator[] (int);
private:
    int  **mass;    
    int  row, col; 
};

matrix::matrix(int r, int c) : row(r), col(c)
{
    mass = new int*[row];
    for(int i=0; i<row; ++i)
    {
        mass = new int[col];
        for(int j = 0;j<col;++j)
          mass[j] = rand() % 100;
    }
}

matrix::~matrix()
{
    for(int i=0; i<row; ++i)
        delete [] mass;
    delete  mass;
}
Row matrix::operator[] (int i)
{
    return Row(this,i);
}
ostream &operator<<(ostream &out,  matrix &mass)
{
    out<<endl;
    for(int i = 0;i < mass.row;++i){
         for(int j = 0;j < mass.col;++j)
              out<<setw(5)<<mass[j];
     out<<"\n\n";
    }
     return out;
}
int& Row::operator[](int index)
 {
     return array->mass[row][index];
 }...

2 - й вариант.
Код:
...
class matrix
{
    friend ostream &operator << (ostream &,const matrix &);
public:
    matrix (int,int);
    ~matrix();
    int* operator[] (int)const;
private:
    int  **mass;    
    int  row, col; 
};

matrix::matrix(int r, int c) : row(r), col(c)
{
    mass = new int*[row];
    for(int i=0; i<row; ++i)
    {
        mass = new int[col];
        for(int j = 0;j<col;++j)
          mass[j] = rand() % 100;
    }
}

matrix::~matrix()
{
    for(int i=0; i<row; ++i)
        delete [] mass;
    delete  mass;
}
int* matrix::operator[] (int i)const
{
    return (i < 0 || i >= row) ? NULL : mass;
}
ostream &operator<<(ostream &out, const matrix &mass)
{
    out<<endl;
    for(int i = 0;i < mass.row;++i){
         for(int j = 0;j < mass.col;++j)
              out<<setw(5)<<mass[j];
     out<<"\n\n";
    }
     return out;
}...

Используем потом так
Код:
...
int _tmain(int argc, _TCHAR* argv[])
{
    srand(time(0));
    matrix arr(5,6);  
    cout<<arr;
    arr[0][0] = 11;
    arr[1][1] = 22;
    arr[2][2] = 33;
    cout<<arr;
    return 0;
}
245
07 ноября 2007 года
~ArchimeD~
1.4K / / 24.07.2006
Шаблон класса Матриц (C++)

http://sources.codenet.ru/download/1692/matrix_cc.html

два класса:
родительский table - таблица
дочерний matrix - матрица

относительно matrix перегружены следующие операторы:

>> (friend) - ввод матрицы
<< (friend) - вывод матрицы
~ - транспонирование
+ - сложение
- - вычитание
* - умножение
! - обратная матрица (нахождение с помощью алгебраических дополнений)
[] - обращение к объекту, как к двумерному массиву
= - оператор присваивания

дополнительные члены:
det ( void ) - нахождение определителя матрицы
ret_w ( void ) - возвращает кол-во столбцов в матрице
ret_h ( void ) - возвращает кол-во строк в матрице
matrix ( const matrix<T> &obj ) - конструктор копий
350
28 ноября 2007 года
cheburator
589 / / 01.06.2006
Наиполезнейшая библиотека, которая пригодится любому разработчику под C++ (после STL/STLport) - boost, которая по сути является целым набором библиотек (около 70) разнообразного назначения. boost - кроссплатформенная библиотека, создававшаяся членами рабочей группы комитета по стандарту С++, хорошо отлаженная и проверенная годами работы.
Пользователи MS Visual studio версий 7.1 (2003) и 8.0 (2005) могут скачать инсталлятор здесь: http://www.boost-consulting.com/boost_1_34_1_setup.exe (188 Кб), после чего запустить его, и установщик сожрет еще около 70 Мб вашего трафика. Пользователи всех платформ, включая Windows/MS Visual studio, не богатые интернетом, могут скачать здесь: http://sourceforge.net/project/showf...ackage_id=8041 (12 Мб - в формате 7z, 24 Мб - zip, есть и другие форматы), но возможно, придется помучиться с установкой.
Большинство библиотек полностью состоят из заголовочных файлов (*.hpp) и не содержат *.cpp, *.lib, *.obj, *.dll и т. п. и поэтому для пользования такими библиотеками достаточно скачать 7z, распаковать, все заголовочные файлы будут лежать в подкаталоге boost. Я бы рекомендовал просто скопировать подкаталог boost в директорию include вашей среды разработки, после чего подключение этих заголовочных файлов будет очень простым - #include <boost/some_library.hpp>.

Полный список библиотек и документацию (на английском) можно почитать здесь: http://boost.org/libs/libraries.htm

Самые распространенные библиотеки boost:

1) smart_ptr. Включает в себя "умные" указатели - используйте их, когда не хотите заботиться об уничтожении выделенной с помощью new памяти - delete вызывается автоматически.
1.1) scoped_ptr - контролируемый "умным указателем" объект уничтожается при выходе из области видимости. В отличие от std::auto_ptr, оператор присваивания не предусмотрен, т. е. невозможна передача контроля другому scoped_ptr.
1.2) scoped_array - то же, но для массивов. Вызывается оператор delete[] вместо delete.
1.3) shared_ptr - основан на счетчике ссылок. На объект могут указывать множество "умных указателей", объект будет уничтожен только тогда, когда на него перестает указывать последний shared_ptr. По сути, это практически полная автоматизация уничтожения объектов.
1.4) shared_array - то же, но для массивов.
1.5) intrusive_ptr - тот же smart_ptr (основан на счетчике ссылок), но подразумевает, что ваш собственный тип данных уже содержит счетчик ссылок. Ваш тип должен иметь методы intrusive_ptr_add_ref, intrusive_ptr_release для того, чтобы intrusive_ptr мог обращаться к счетчику ссылок.

2) multi_array. Многомерные массивы с переменной размерностью. Поскольку "родные" массивы C/C++ не предусматривают типов - многомерных массивов с переменными размерностями (например, int [][][]) и "неопределенной" может быть только "старшая" размерность (int [][20][30]), приходится подобные массивы объявлять как одномерные, после чего вручную вычислять смещение в массиве, исходя из его текущих размерностей. Что чревато путаницей и ошибками. boost::multi_array позволит этого избежать.

3) multi_index. Универсальный контейнер с поддержкой многих индексов. Если ваш контейнер имеет два поля (например, фамилию и дату рождения), и по обоим требуется обеспечить быстрый поиск, boost::multi_index решит задачу. Индексировать можно по полям вашего типа данных (если хранимый в контейнере тип данных - класс или структура), по членам-функциям (вычисляемый индекс), поддерживаются также хэшированные индексы и индекс-порядок (sequenced), в котором элементы располагаются в линейном порядке, подобно std::list.
multi_index имеет смысл использовать даже при одном индексе, т. к. имеются дополнительные возможности, по сравнению со стандартными контейнерами.

4) random. Содержит различные генераторы случайных чисел. Лично я пользовался мало, но ИМХО, лучше пользоваться генераторами Агнера Фога http://www.agner.org/random/ - тоже вполне кроссплатформенные, и содержат гораздо больше генераторов с различными распределениями (от распределения Бернулли до некоего "Multivariate Wallenius noncentral hypergeometric distribution"). Многих распределений, к сожалению, в boost.random нет.

5) pool предназначен в основном для быстрого управления памятью, когда происходит выделение большого числа маленьких объектов, особенно когда необязательно вызывать их деструкторы - можно просто "выкинуть" объекты из пула.

6) thread. Как известно, многопоточность в различных платформах реализована по-разному. thread предоставляет кроссплатформенную библиотеку для создания многопоточных приложений, включая как собственно реализацию многопоточности, так и синхронизацию потоков (мьютексы).

P. S. Некоторые библиотеки, включая threads, состоят не только из заголовочных файлов, и их нужно собирать (build). Для этого понадобится утилита bjam. Инструкцию по сборке можно найти в документации к threads.
320
08 декабря 2007 года
m_Valery
1.0K / / 08.01.2007
Класс матрицы на основе контейнера vector от модератора раздела С++
Green.
320
08 декабря 2007 года
m_Valery
1.0K / / 08.01.2007
Получение всех перестановок строки.
http://forum.codenet.ru/showthread.php?t=42248
320
28 декабря 2007 года
m_Valery
1.0K / / 08.01.2007
Самодельные классы С++,которые ,в общем-то, изобретают велосипед. Но поскольку они входят в программу изучения С++,их пишут все студенты,а их написание - своебразное посвящение в С++.Только для того чтоб не дублировались вопросы выкладываю что есть.Хочу заметить,что стандартная библиотека предлагает свои классы и рекомендуется пользоваться как раз стандартными,а не самодельными. Но для того чтоб срочно сдать хвост пойдут и эти.
Шаблонные односвязный и двусвязный списки.
Класс Строка.(смотри вложение cheburator)
Шаблонный класс Вектор.
Шаблонный класс Стек.
Шаблонный класс Очередь.
320
28 декабря 2007 года
m_Valery
1.0K / / 08.01.2007
Программа открывает текстовый файл и записывает в него текущий набор символов.
Код:
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
void writeCharsetToFile(const string& filename);
void outputFile(const string &filename);
int _tmain(int argc, _TCHAR* argv[])
{
    writeCharsetToFile("f1.txt");
    outputFile("f1.txt");
    return 0;
}
void writeCharsetToFile(const string& filename)
{
    ofstream file(filename.c_str());
    if(!file)
    {
        cerr<<"can't opetn output file "<<endl;
        exit(EXIT_FAILURE);
    }
    for(int i = 32;i < 256;++i)
    {
        file<<"value : "<<setw(3)<<i<<" "
            <<"char : "<<static_cast<char>(i)<<endl;
    }
}
void outputFile(const string &filename)
{
    ifstream file(filename.c_str());
    if(!file)
    {
        cerr<<"can't open input file "<<endl;
            exit(EXIT_FAILURE);
    }
    char c;
    while(file.get(c))
    {
        cout.put(c);
    }
}
320
28 декабря 2007 года
m_Valery
1.0K / / 08.01.2007
Код:
#include <iostream>
#include <fstream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    // Открываем файл
    ifstream file("f1.txt");
    // Выводим в консоль
    cout<<file.rdbuf();
    // Выведем начиная с 20 символа от конца
    file.seekg(-20,ios::end);
    cout<<"********************\n\n";
    cout<<file.rdbuf();
    return 0;
}

Позиционирование в начало файла
 
Код:
file.seekg(0,ios::beg);

Позиционирование на 100 символов вперед от текущей позиции
 
Код:
file.seekg(100,ios::cur);

Позиционирование на 50 символов от конца
 
Код:
file.seekg(-50,ios::end);
320
28 декабря 2007 года
m_Valery
1.0K / / 08.01.2007
Читаем текстовый файл,заполняем контейнер,сортируем,удаляем дубликаты и выводим на экран.Используем алгоритм STL - copy.
Код:
#include <iostream>
#include <set>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    ifstream in("f1.txt");
    istream_iterator<string> ifile(in);
    istream_iterator<string> eos;
    set<string> coll;
    copy(ifile,eos,inserter(coll,coll.begin()));
    copy(coll.begin(),coll.end(),
        ostream_iterator<string>(cout,"\n"));
    return 0;
}
276
11 января 2008 года
Rebbit
1.1K / / 01.08.2005
Вчера читал эту тему и вижу что не все уважаемые форумчане, которые помогают студентам, знают как это делать.
Приведу пример условия.
Пощитать суму ряда
(-2)^i / i! (i = 1, 2, 3 .....)
Можно пробовать делать в лоб. Сделать цикл по i, на каждой итерации вычислять (-2)^i, i!, член ряда и складывать это все.
Цитата:

Код:
double sum,fact;
int i,j,n;
......
sum = 0;
for(i=1;i<n;i++)
{
  fact =1;
  for(j=1;j<i;j++)
     fact *= j;
  sum += pow(-2,i)/fact;
}

.

При таком подходе мы будем получать большие значения в fact и pow(-2,i) уже на начальных итерациях цикла. Правильнее будет сохранять член ряда с предыдущей итерации и корректировать его на следующей итерации.

Код:
double sum,el;
int i;
......
sum = 0; el = 1; i = 0;
while(не достигнута нужная точность)
{
  i++;
  el *= -2;
  el /= i;
  sum += el;
}

Примерно так. (Возможно гдето ошибся, код от руки писал).
9
22 декабря 2008 года
Lerkin
3.0K / / 25.03.2003
[COLOR="DarkRed"]Самое начало.[/COLOR]

Тема, как видно, актуальна. Поэтому, с разрешения модераторов, приведу один вариант.

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

Описание функций:
1. Подготовка строки к обработке. Убираем знаки препинания, лишние пробелы, цифры, переводы строк и приводим все символы к нижнему регистру.
2. Заполнение словаря уникальными словами и подсчет повторов.
3. Выведение списка повторяющихся слов.
4. Пример использования.

Особенности:
1. Используется структура односвязного списка.
2. Используемые библиотечные функции:
[SIZE="2"][FONT="Courier New"]printf, malloc, free[/FONT][/SIZE] - вывод на экран, выделение и освобождение памяти.
3. Компилятор С\С++ - любой, операционная система - любая общеизвестная.

Итак. Вначале опишем 2 не обязательные функции.
1. Функция mystrlen (аналог библиотечной [FONT="Courier New"][SIZE="2"]strlen[/SIZE][/FONT]).
Иногда преподаватели требуют не использовать библиотечную функцию. Ну что же, напишем сами.
Параметр - символьная строка, на выходе - размер этой строки.
 
Код:
int mystrlen( str )
char* str;
{
    int len = 0;

    while (*str++)
    len++;

    return len;
}


2. Функция prepstr (работает в DOS-кодировке).
Назначение: Формирует текстовую строку исключительно из букв русского и английского алфавита, а так же символа пробел (0x20) и символа тире (0x2d). Убирает повторяющиеся пробелы (сжимает строку) и переводит все символы в нижний регистр. Условие использования такой функции не всегда является обязательным при зачетах и лабораторных работах, но иногда необходима.
Параметр - произвольная символьная строка, на выходе - новая форматная строка.
Код:
char* prepstr( str )
char* str;
{
    char sym, *buff, *ptr, *tmp;

    [COLOR="Green"]// Здесь, вместо mystrlen можно использовать стандартную strlen[/COLOR]
    buff = (char*)malloc( mystrlen( str ) );
    if (NULL != buff)
    {
    ptr = str, tmp = buff;

    while (sym = *ptr++)
        if  (sym == 0x20 || sym == 0x2d  ||
        (sym >= 0x41 && sym <= 0x5a) ||
        (sym >= 0x61 && sym <= 0x7a) ||
        (sym >= 0x80 && sym <= 0x9f) ||
        (sym >= 0xa0 && sym <= 0xaf) ||
        (sym >= 0xe0 && sym <= 0xf1))
        {
            if ((sym >= 0x41 && sym <= 0x5a) ||
            (sym >= 0x80 && sym <= 0x8f))
            sym += 0x20;
            else if (sym >= 0x90 && sym <= 0x9f)
            sym += 0x80;
            else if (sym == 0xf0)
            sym++;

            *tmp++ = sym;
        }

    *tmp = '\0';
    tmp = ptr = buff;

    while( *ptr++ )
        if( *ptr != *tmp || *ptr != 0x20 )
        *(++tmp) = *ptr;

    *(++tmp) = '\0';
    }

    return buff;
}


Продолжение следует...
9
22 декабря 2008 года
Lerkin
3.0K / / 25.03.2003
Предыдущая часть.

Итак, с необязательными функциями разобрались (но в дальнейших примерах будем использовать только их). Теперь перейдем к сути вопроса.

Предлагаемый вариант подразумевает ведение словаря из встречающихся в текстовой строке слов, и подсчета их дублей. Организовать такой словарик проще всего на основе односвязного списка (есть такая структура данных, должны помнить если лекции не прогуливали, балбесы :D).
Вот как это пишется на языке Си:
 
Код:
[COLOR="Green"]// Структура элемента словаря[/COLOR]
typedef struct _mylist
{
    char* word;
    int count, len;
    struct _mylist* next;
} MYLIST, *PMYLIST;

[COLOR="Green"]// Глобальное объявление словаря[/COLOR]
PMYLIST list = NULL;


Теперь, функция поиска слова в словаре. Если такое слово в словаре уже присутствует, то просто увеличим счетчик дублей этого слова.
Код:
int check( myword )
char* myword;
{
    int len;
    char *w1, *w2;
    PMYLIST ptr = list;

    if (NULL == ptr)
    return 0;

    while (ptr)
    {
    w1 = myword, w2 = ptr->word;

    len = mystrlen( w1 );
    if (ptr->len == len)
    {
        while (--len)
        if (*w1++ != *w2++)
            break;

        if (0 == len)
        {
        ptr->count++;
        return 1;
        }
    }

    ptr = ptr->next;
    }

    return 0;
}

Достаточно простая функция. Параметр - слово для поиска слова в словаре, на выходе: 1 - слово найдено и счетчик увеличен, 0 - слова в словаре нет.

Продолжение следует...
9
22 декабря 2008 года
Lerkin
3.0K / / 25.03.2003
Предыдущая часть.

Теперь процедура составления словаря из текста.
Как обычно, параметр - подготовленная (или нет) текстовая строка.
Код:
void parse_str( str )
char* str;
{
    int len;
    PMYLIST item, ptr = NULL;
    char *myword, *tmp, *p = str;

    while (*p)
    {
    len = 0;
    tmp = p;

    while (*tmp)
        if (0x20 != *tmp++)
        len++;
        else
        break;

    myword = (char *)malloc( ++len );
    tmp = myword;

    while (len--)
        *tmp++ = *p++;
    *tmp = '\0';

    if (!check( myword ))
    {
        item = (PMYLIST)malloc( sizeof(MYLIST) );
        item->count = 1;
        item->next = NULL;
        item->word = myword;
        item->len = mystrlen( myword );

        if (NULL == list )
        {
        list = item;
        ptr = list;
        }
        else
        {
        ptr->next = item;
        ptr = ptr->next;
        }
    }
    }
}


И сразу же, чтобы не забывать, функция очистки словаря и освобождения выделенной памяти:
Код:
void free_list( void )
{
    PMYLIST ptr = list, item;

    while (ptr)
    {
    item = ptr;
    ptr = ptr->next;

    free( item->word );
    free( item );
    }
}


Продолжение следует...
9
22 декабря 2008 года
Lerkin
3.0K / / 25.03.2003
Предыдущая часть.

Теперь можно написать процедуру, которая покажет нам список уникальных слов, и укажет, сколько раз и какое слово повторялось в тексте. Процедурка очень простая:
 
Код:
void print_list( void )
{
    PMYLIST ptr = list;

    while (ptr)
    {
    printf("[%i] %s\n", ptr->count, ptr->word);
    ptr = ptr->next;
    }
}


Вообщем-то и все. Осталось это дело объединить в действующую программку и получить зачёт (лодыри :D).

Итак, скелет программы:
Код:
#include <stdio.h>
#include <stdlib.h>

[COLOR="Green"]// тут помещаем структуру односвязного списка и объявление словаря[/COLOR]
...

[COLOR="Green"]// тут помещаем функцию mystrlen[/COLOR]
...

[COLOR="Green"]// тут помещаем функцию prepstr[/COLOR]
...

[COLOR="Green"]// тут помещаем функцию check[/COLOR]
...

[COLOR="Green"]// тут помещаем процедуру parse_str[/COLOR]
...

[COLOR="Green"]// тут помещаем процедуру free_list[/COLOR]
...

[COLOR="Green"]// тут помещаем процедуру print_list[/COLOR]
...

[COLOR="Green"]// Главная функция программы[/COLOR]
int main( void )
{
    char* buff = NULL;
    char* str = "... тут какая-нибудь текстовка для разбора ...";

[COLOR="Green"]    // получим новую, подготовленную для разбора строку[/COLOR]
    buff = prepstr( str );
    if (NULL != buff)
    parse_str( buff );
    else
    return -1;

[COLOR="Green"]    // удаляем её теперь (за ненадобностью)[/COLOR]
    free( buff );

[COLOR="Green"]    // выводим словарик на экран[/COLOR]
    print_list();

[COLOR="Green"]    // удаляем словарь и освобождаем память[/COLOR]
    free_list();

[COLOR="Green"]    // выходим[/COLOR]
    return 0;
}


Продолжение следует...
9
26 декабря 2008 года
Lerkin
3.0K / / 25.03.2003
Предыдущая часть.

А вот, собственно, решение той же задачи, но на С++.
Код:
#include <map>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;

int main( void )
{
    multimap<string, int> dict;
    multimap<string, int>::iterator mm_iter;

    stringstream ss( "...здесь текстовка для разбора..." );
    while (!ss.eof())
    {
    string p;
    getline( ss, p, ' ' );

    string::iterator it = p.begin();
    if (p.empty() || (1 == p.length() && !isalpha( *it )))
        continue;
    else
        while (it != p.end())
        *it++ = tolower( *it );

    if (!isalpha( *(--it) ))
        p.erase( it );

    mm_iter = dict.find( p );
    if (mm_iter == dict.end())
        dict.insert( make_pair( p, 1 ) );
    else
        mm_iter->second++;
    }

    for (mm_iter = dict.begin(); mm_iter != dict.end(); mm_iter++)
    cout << "[" << mm_iter->second << "] " << mm_iter->first << endl;

    return 0;
}

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

В начало.
87
26 декабря 2008 года
Kogrom
2.7K / / 02.02.2008
Предлагаю другой вариант той же программы на c++. Если влез не в свою область - удалите.

Код:
#include <map>
#include <string>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    map<string, int> dict;

    // с русскими буквами в этом примере не будем морочиться
    stringstream ss( "...one, two, three, One, one, *one, *one!, ONE!..." );
    while (!ss.eof())
    {
        string str;
        getline( ss, str, ' ' );

        // убираем не буквы спереди
        while(str.size() && !isalpha(str[0]))
            str.erase(str.begin());
        // убираем не буквы сзади
        while(str.size() && !isalpha(str[str.size() - 1]))
            str.erase(str.end() - 1);
        if(str.empty()) continue;
        // меняем регистр
        transform( str.begin(), str.end(), str.begin(), ::tolower );

        dict[str]++;
    }

    for (map<string, int>::const_iterator mm_iter = dict.begin(); mm_iter != dict.end(); mm_iter++)
        cout << "[" << mm_iter->second << "] " << mm_iter->first << endl;

    return 0;
}

В своем примере я использовал следующее свойство контейнера map: при обращении к контейнеру по ключу, которого нет, в контейнер добавляется соответствующий элемент, в котором второй элемент создаётся с конструктором по умолчанию. Для встроенных типов записываются нули.
535
02 декабря 2010 года
Нездешний
537 / / 17.01.2008
Функция Determinant считает определитель матрицы. Матрица, передаваемая на вход функции, должна быть квадратной. Функция рекурсивна. Определитель считается методом разложения по строке.

Функция Cramer получает решение СЛАУ методом Крамера. Возвращает true или false в зависимости от существования единственного решения СЛАУ. Искомые неизвестные возвращаются через параметр X. Использует функцию подсчета определителя.
Код:
#include <vector>
#include <math.h>

//Назначение: подсчет определителя квадратной матрицы
//Возвращаемое значение: определитель
double Determinant(const std::vector< std::vector<double> > &Matrix)
{
    if (Matrix.size() == 1) return Matrix[0][0];

    double Result = 0;
    for (unsigned i = 0; i < Matrix.size(); ++i)
    {
        std::vector< std::vector<double> > SubMatrix(Matrix);
        SubMatrix.resize(SubMatrix.size() - 1);
        for (unsigned j = 0; j < SubMatrix.size(); ++j) SubMatrix[j].erase(SubMatrix[j].begin() + i);
        if (Matrix[Matrix.size() - 1] != 0)
        {
            Result += Matrix[Matrix.size() - 1] * pow(-1, i+Matrix.size()) * Determinant(SubMatrix);
        }
    }

    return Result;
}

//Назначение: решение СЛАУ вида Matrix * X = Fx
//Возвращаемое значение: true - если существует единственное решение,
//false - в остальных случаях
bool Cramer(
    const std::vector< std::vector<double> > &Matrix,
    const std::vector<double> &Fx,
    /*out*/ std::vector<double> &X)
{
    //check params
    if (Fx.size() != Matrix.size()) return false;
    for (unsigned i = 0; i < Matrix.size(); ++i)
    {
        if (Matrix.size() != Matrix.size()) return false;
    }

    X.clear();
    X.resize(Matrix.size());

    double detMain = Determinant(Matrix);
    if (0 == detMain)   return false;

    for (unsigned i = 0; i < X.size(); ++i)
    {
        std::vector< std::vector<double> > SubMatrix = Matrix;
        for (unsigned j = 0; j < Fx.size(); ++j)    SubMatrix[j] = Fx[j];

        X = Determinant(SubMatrix) / detMain;
    }

    return true;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог