вторник, 23 апреля 2019 г.

Перевод числа в строку и наоборот в С++

#include <iostream>
#include <sstream>
using namespace std;
int main()
{
    string s="12";
    istringstream in_str;
    in_str.str(s);
    int k;
    in_str >> k;
    cout<<k*2<< endl;

    ostringstream out_str;
    int N = 123;
    out_str << N;
    s = out_str.str()+" year";
    cout<<s;
    out_str.str(""); // clear stringstream
}



среда, 10 января 2018 г.

Ввод массива неизвестной длины

В некоторых задачах необходимо ввести элементы массива, но при этом сколько элементов не задано точно, кроме этого нужно считывать только данные с одной строки (например, список вершин графа). Как считать до конца строки, т.е. когда нажата клавиша Enter?

int n,a;
cin>>n; //кол-во вершин
vector <int> A[n]; //список смежных вершин
for(int i=0;i<n;i++)
{
  do{    
    cin>>a;
    A[i].push_back(a);
  }while(cin.get()!=10);//если после числа не Enter, но может быть пробел
}

Получается разреженная матрица:

for (int i=0; i<n; i++)
{
    for(int j=0; j<A[i].size(); j++)
        cout<<A[i][j]<<" ";
    cout<< endl;
}



Кодировка символов

Как узнать код нажатой клавиши?

    unsigned char c;
    do{
      c=cin.get();
      cout<<c<<":"<<int(c)<<endl;
    }while(c!=10); //пока не ввели Enter (код 10):

Но существует проблема с русскими буквами: в таблице ASCII (шрифт Terminal) они разбросаны, поэтому лучше собрать их в одну строку:

    string s="абвгдеёжзийклмнопрстуфхцчшщъыьэюя";

При этом кодировка текста программы не должна быть 16-битной, установите, например, windows-1251. Сменить кодировку можно в Блокноте.

При выводе сменить кодировку можно с помощью библиотеки locale.h:

    setlocale(0,"rus");

Если нужен код русского символа, то он будет отрицательным, поэтому используйте сдвиг на 256 или преобразование типов unsigned int:

    for (int i=0;i<s.size();i++)
        cout<<s[i]<<":"<<int(s[i])+256<<endl;

Ввод из файла лучше осуществить построчно:

    ifstream fin("input.txt");
    string f;
    while(getline(fin,f))
    {
        cout<<f.size()<<":"<<f<<endl;
    }

Если всё же нужен посимвольный ввод, то есть проблема с русской буквой 'я'. Её код совпадает с кодом конца файла EOF (-1).

    char q;   
    do
    {
        q=fin.get();

//не все буквы русские, если код отрицательный - делаем сдвиг:

        cout<<q<<":"<<(int(q)+256)%256 << endl;

        cout<<q<<":"<<(int(q)+((q<0)?256:0) << endl; 

//если в тексте есть буква  'я' и это не конец файла,
//то нужно как то прочитать файл дальше:   
 
     if(q==EOF)
        {
            q=fin.get();
            cout<<q<<":"<<int(q)<<endl;
        }

    }while(q!=EOF);

Вывод всех символов и их кодов в виде таблицы:
 
    for (int i=0; i<256; i++)
    {
          cout.width(5);//ширина столбца 5 символов

//есть команды/клавиши с кодами:
//7 - подача звука
//8 - BackSpace
//9 -Tab
//10 - Enter
//13 - в начало строки
//27 - Esc
//32 - Space (пробел)
// их вывод лучше пропустить:

        if (i==7 || i==8 || i==9 || i==10 || i==13 || i==27)
           cout<<i<<":";
       else
          cout<<i<<":"<<char(i);

 //вывод в 6 столбиков:

        if (i%6==0) cout << endl;
    }
   

суббота, 6 января 2018 г.

Сокращения команд

Если надоело писать одни и те же команды, то можно их сократить.

#include <iostream>
using namespace std;

#define fi(n) for (int i = 0; i < (n); i++)
#define FOR(i, k, n) for (int i = (k); i < (n); i++)
#define li long long

int main()
{
  int n;
  cin>>n;
  li A[n];
  fi(n) 
     cin>>A[i];
  li s=0;
  FOR(i,0,n)s=s+A[i];
  cout<<s;
  return 0;
}

Задание начального значения элементам массива

Очень часто при решении задач с массива требуется задать им начальное значение или обнулить. Самый простой способ использование цикла. Но есть и специальные функции, которые по указанному количеству байт задает им начальное значение.

В Паскале:

var A:array[1..100]of integer;
FillChar(A, 100*SizeOf(integer), 0);

Для строк:
Var S:string;
S:='';

или
Var S:string[100];
FillChar(S, SizeOf(S), ' ');

В С++:

int A[10]={0};
int B[10]={1};

Но для массива с переменной длиной не будет работать, надо так:

int n;
cin>>n;
fill(A, A+n, 0); 
Здесь A - хранит адрес начала массива, А+n - переносим указатель на n элементов, т.е. в конец массива, третий аргумент - чем заполнить массив, можно поставить 1.

fill(&A[0], &A[0]+n,0);
Здесь &A[0] - получаем адрес на начальный элемент массива с индексом 0.

Таким образом можно обнулять часть массива, например, начиная с середины:
fill(&A[n/2], &A[0]+n,0); 

Если это двумерный массив:
int n, m;
cin>>n>>m;
double A[n][m];
fill(&A[0][0], &A[0][0]+n*m, 0);

Если массив объявлен как vector:
vector <bool> A;
int n;
cin>>n;
A.resize(n,false);

или
fill(A.begin(), A.end(),true);