FAQ - часто задаваемые вопросы
[COLOR=purple]Ищем исходники[/COLOR] здесь.
Если в приведенных здесь решениях есть ошибки, просьба сообщить мне об этом. Спасибо.
#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 <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;
}
Задача представляет собой своего рода считалку:элементы становяться в "круг", вводиться
некоторое число.Необходимо, начиная с первого элемента, отсчитать к-ый элемент списка и удалить его.Далее отсчет начинается с (к+1)-го элемента и опять удаляется к-ый элемент.Так продолжается
то тех пор,пока в списке не останеться один элемент.Выдать содержимое последнего оставшегося элемента"[/quote]
Language C/C++
#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;
}
[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]
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');
}
/*освобождаем память когда массив уже не нужен(как минимум в конце программы)*/
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
{
int sum = 0;
while(n)
{
sum += (n % 10);
n /= 10;
}
return sum;
}
#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]);
}
}
#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');
}
Если нужно генерировать ПСЧ в криптографических функциях, то это действительно бывает непросто. Но для "бытовых" генераторов используются следующие алгоритмы генерации - примеры того как эти функции были реализованы в некоторых прошлых версиях популярных компиляторов.
Итак -
// 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. Не ручаюсь за точность констант в конкретных версиях, это лишь примеры:)
Даны действительные числа 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
1)для удаления дубликатов(повторов) всех символов, если они рассположены последовательно(подряд)
например: "aaabbf ttr...."
результат: "abf tr."
2)для удаления последовательных повторов указанного символа (например символ точка)
например: "aabbf ttr...."
результат: "aabbf ttr."
функцию написал Lerkin
{
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");
}
1 - delch - удаляет последовательно рассположенные дубликаты символа ch
{
char *ptr = src;
while( *ptr++ )
if( *ptr != *src || *ptr != ch)
*(++src) = *ptr;
}
2 - deldup - удаляет все последовательно рассположенные дубликаты символов
{
char *ptr = src;
while( *ptr++ )
if( *ptr != *src)
*(++src) = *ptr;
}
удобная среда разработки приложений на С++ и С: присутствует автодополнение кода, подсветка синтаксиса, поставляется вместе с компилятором mingw(порт gcc под Windows), в пакете также имеется отладчик gdb, примеры, файл справки, и плюс ко всему простой и удобный интерфейс - для студентов вещица просто необходимая. размер всего 9 Мб.
Если есть вопросы, то задаём их здесь.
[URL="http://forum.codenet.ru/showthread.php?t=34580"]Dev-C++, кто работал? [/url]
#include "windows.h". Создаем функцию
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 <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;
}
- [COLOR=purple]Написать программу, подсчитывающую количество символов ASCII в строке.[/COLOR]
#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]
#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]
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;
}
Класс является хорошим примером контейнера STL,определяемого пользователем.В данном случае стандартный контейнерный интерфейс реализуется как оболочка вокруг массива.
Вот как выглядит определение этого класса:
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 <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.
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!!!
#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, на основе стратегий).
Преподы часто дают такой пример для сдачи зачета по теме "Указатели и массивы".Предназначен только для студенческих задач, лучше использовать двумерный вектор.
#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[].
#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 <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;
}
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;
}
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 ) - конструктор копий
Пользователи 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.
Green.
Шаблонные односвязный и двусвязный списки.
Класс Строка.(смотри вложение cheburator)
Шаблонный класс Вектор.
Шаблонный класс Стек.
Шаблонный класс Очередь.
#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);
}
}
#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;
}
Позиционирование в начало файла
Позиционирование на 100 символов вперед от текущей позиции
Позиционирование на 50 символов от конца
#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;
}
Приведу пример условия.
Пощитать суму ряда
(-2)^i / i! (i = 1, 2, 3 .....)
Можно пробовать делать в лоб. Сделать цикл по i, на каждой итерации вычислять (-2)^i, i!, член ряда и складывать это все.
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) уже на начальных итерациях цикла. Правильнее будет сохранять член ряда с предыдущей итерации и корректировать его на следующей итерации.
int i;
......
sum = 0; el = 1; i = 0;
while(не достигнута нужная точность)
{
i++;
el *= -2;
el /= i;
sum += el;
}
Примерно так. (Возможно гдето ошибся, код от руки писал).
Тема, как видно, актуальна. Поэтому, с разрешения модераторов, приведу один вариант.
Тема:
Поиск и подсчет повторяющихся слов в тексте, без использования библиотечных функций работы со строками.
Описание функций:
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]).
Иногда преподаватели требуют не использовать библиотечную функцию. Ну что же, напишем сами.
Параметр - символьная строка, на выходе - размер этой строки.
char* str;
{
int len = 0;
while (*str++)
len++;
return len;
}
2. Функция prepstr (работает в DOS-кодировке).
Назначение: Формирует текстовую строку исключительно из букв русского и английского алфавита, а так же символа пробел (0x20) и символа тире (0x2d). Убирает повторяющиеся пробелы (сжимает строку) и переводит все символы в нижний регистр. Условие использования такой функции не всегда является обязательным при зачетах и лабораторных работах, но иногда необходима.
Параметр - произвольная символьная строка, на выходе - новая форматная строка.
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;
}
Продолжение следует...
Итак, с необязательными функциями разобрались (но в дальнейших примерах будем использовать только их). Теперь перейдем к сути вопроса.
Предлагаемый вариант подразумевает ведение словаря из встречающихся в текстовой строке слов, и подсчета их дублей. Организовать такой словарик проще всего на основе односвязного списка (есть такая структура данных, должны помнить если лекции не прогуливали, балбесы :D).
Вот как это пишется на языке Си:
typedef struct _mylist
{
char* word;
int count, len;
struct _mylist* next;
} MYLIST, *PMYLIST;
[COLOR="Green"]// Глобальное объявление словаря[/COLOR]
PMYLIST list = NULL;
Теперь, функция поиска слова в словаре. Если такое слово в словаре уже присутствует, то просто увеличим счетчик дублей этого слова.
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 - слова в словаре нет.
Продолжение следует...
Теперь процедура составления словаря из текста.
Как обычно, параметр - подготовленная (или нет) текстовая строка.
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;
}
}
}
}
И сразу же, чтобы не забывать, функция очистки словаря и освобождения выделенной памяти:
{
PMYLIST ptr = list, item;
while (ptr)
{
item = ptr;
ptr = ptr->next;
free( item->word );
free( item );
}
}
Продолжение следует...
Теперь можно написать процедуру, которая покажет нам список уникальных слов, и укажет, сколько раз и какое слово повторялось в тексте. Процедурка очень простая:
{
PMYLIST ptr = list;
while (ptr)
{
printf("[%i] %s\n", ptr->count, ptr->word);
ptr = ptr->next;
}
}
Вообщем-то и все. Осталось это дело объединить в действующую программку и получить зачёт (лодыри :D).
Итак, скелет программы:
#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;
}
Продолжение следует...
А вот, собственно, решение той же задачи, но на С++.
#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;
}
Вот и все, мои маленькие друзья. Если нашли какую-то неточность, ошибочку или еще какой баг, пишите в ПМ. Исправим, людям - на пользу, себе - в удовольствие.
В начало.
#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: при обращении к контейнеру по ключу, которого нет, в контейнер добавляется соответствующий элемент, в котором второй элемент создаётся с конструктором по умолчанию. Для встроенных типов записываются нули.
Функция Cramer получает решение СЛАУ методом Крамера. Возвращает true или false в зависимости от существования единственного решения СЛАУ. Искомые неизвестные возвращаются через параметр X. Использует функцию подсчета определителя.
#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;
}