Имя пользователя:

Пароль:



Объявления
Поздравляем
kostya_onishenko

С С++ - Вопросы программирования

Подписчиков: Kordan

С С++ - Вопросы программирования

Номер сообщения:#21  Непрочитанное сообщение Kordan » 05 ноя 2016, 00:16

Написал программку и возникли вопросы по языку Си:
Код: выделить все · Развернуть
#include <stdio.h>

void main(void){
   float arr[10] = {0};
   float a = 25.0;
   float k = 0.0;

   printf("\n");
   for(char i = 0; i < 10; i++, k += 0.1){
      arr[i] = a + k;
   printf("%.1f - %f\n", arr[i], arr[i]);
   }
return;
}


1. Почему вещественные типы float и double не обеспечивают точности вывода заданных чисел в пределах хотя бы 6 знаков после запятой, заложенных в функцию printf по умолчанию без форматирования? Результат форматирования 20-ю знаками после запятой на втором скрине. Почему тогда два результата из 10 с идеальной точностью?
2. Почему переменную "к" нужно обязательно инициализировать нулем, ведь она глобальная? При простом объявлении программа выдает мусор.
https://yadi.sk/i/dW7PIFWVy6Dfk
https://yadi.sk/i/heV1-zZmy6DmF
Аватар пользователя
Kordan
.
.
      Автор темы
Сообщений: 2451
Возраст: 49
Зарегистрирован: 63 месяцев и 2 дня
Откуда: Саратов
Национальный флаг:
Russia
Благодарил (а): 667 раз.
Поблагодарили: 1220 раз.
Имя: Валерий
Пункты репутации: 25
Молодой трейдерМолодой трейдерМолодой трейдер

С С++ - Вопросы программирования

Номер сообщения:#22  Непрочитанное сообщение coder-ex » 05 ноя 2016, 06:00

Kordan писал(а):

Написал программку и возникли вопросы по языку Си:
Код: выделить все · Развернуть
#include <stdio.h>

void main(void){
   float arr[10] = {0};
   float a = 25.0;
   float k = 0.0;

   printf("\n");
   for(char i = 0; i < 10; i++, k += 0.1){
      arr[i] = a + k;
   printf("%.1f - %f\n", arr[i], arr[i]);
   }
return;
}


1. Почему вещественные типы float и double не обеспечивают точности вывода заданных чисел в пределах хотя бы 6 знаков после запятой, заложенных в функцию printf по умолчанию без форматирования? Результат форматирования 20-ю знаками после запятой на втором скрине. Почему тогда два результата из 10 с идеальной точностью?
2. Почему переменную "к" нужно обязательно инициализировать нулем, ведь она глобальная? При простом объявлении программа выдает мусор.
https://yadi.sk/i/dW7PIFWVy6Dfk
https://yadi.sk/i/heV1-zZmy6DmF

1. Валера, эти типы обеспечивают точность входа согласно своей спецификации, используй их правильно. Этот вопрос из серии часто задаваемых - как сравнивать вещественные типы правильно и как их использовать. Тут тебе грамотно ответит Pyyx.
2. В функционал создания переменной не входит сразу инициализация значением, это право пользователя (программиста).
3. Когда ты создаешь переменную, то под нее выделяется какой то участок в памяти, который ранее мог быть использован другой программой (переменными) и там остались какие то значения. Поэтому при создании переменных их нужно сразу инициализировать значениями, что бы не получить мусор.
Си — это причудливый, несовершенный, но невероятно успешный язык.
— Dennis M. Ritchie.
Аватар пользователя
coder-ex
.
.
Сообщений: 848
Возраст: 47
Зарегистрирован: 14 месяцев и 2 дня
Откуда: Томск
Национальный флаг:
Russia
Благодарил (а): 10 раз.
Поблагодарили: 21 раз.
Имя: Константин
Пункты репутации: 2
Ученик трейдера

С С++ - Вопросы программирования

Номер сообщения:#23  Непрочитанное сообщение Kordan » 05 ноя 2016, 13:55

Пока ясности не прибавилось. Я инициализирую переменную числом 25,9, а там при выводе оказывается 25,899999618530273.
https://yadi.sk/i/D_ezgSLfy7K2d Увеличил число проходов до 50. Что-то даже логики не нашел.

По объявлению переменной в учебнике сказано:
Цитата:
Глобальные и статические глобальные переменные инициализируются только при запуске программы. Локальные переменные инициализируются каждый раз при входе в блок, где они были объявлены. Статические локальные переменные инициализируются только один раз, а не каждый раз при входе в блок. Глобальные и статические локальные переменные инициализируются нулем, если не указано инициализационное значение. Неинициализирующиеся нестатические локальные и регистровые переменные будут иметь неопределенное значение.
Т.е. если я объявляю глобальную переменную, то в ней должен быть ноль, а не мусор. Переменная "к" в моем коде какая? В реальности, без явной инициализации ее нулем, в ней мусор.

Переменная получается не статическая, если она изменяется в цикле. Если цикл закомментировать, то "к" все же инициализируется нулем при объявлении.
Аватар пользователя
Kordan
.
.
      Автор темы
Сообщений: 2451
Возраст: 49
Зарегистрирован: 63 месяцев и 2 дня
Откуда: Саратов
Национальный флаг:
Russia
Благодарил (а): 667 раз.
Поблагодарили: 1220 раз.
Имя: Валерий
Пункты репутации: 25
Молодой трейдерМолодой трейдерМолодой трейдер

С С++ - Вопросы программирования

Номер сообщения:#24  Непрочитанное сообщение coder-ex » 05 ноя 2016, 14:53

Валера обрати внимание на то, в какой области ты объявляешь переменные. В скрине я тебе специально эти моменты выделил комментариями.
kordan_primer.jpg
Если быть точнее. то ты объявил свои переменные на локальном уровне, т.е. в функции!!!, глобальный уровень предполагает объявление за функциями.
т.к. ты поставил запрет на расширения исходников и исполняемые файлы (что странно для такой тематической ветки), то лови просто исходник в тексте:
Код: выделить все · Развернуть
#include <stdio.h>

float one;           // объявление переменной на глобальном уровне
float two = 25.1;    // объявление и инициализация значением переменной на глобальном уровне

int main(int argc, char *argv[]) {
   /* объявление переменных на глобальном уровне */
   printf("Объявление переменных \"one\" и \"two\" на глобальном уровне\n\rone = %f two = %f\n", one, two);
   float _tmp;
   _tmp = one;
   printf("result = %f\n", _tmp);
   _tmp = two;
   printf("result = %f\n", _tmp);

//---
   /* объявление переменных на локальном уровне */
   float arr[10] = {0};    // объявление массива и инициализация значениями его элементов на локальном уровне
   float a = 25.0;         // объявление и инициализация значением переменной на локальном уровне
   float k = 0.0;          // объявление и инициализация значением переменной на локальном уровне

   printf("объявление переменных \"arr[]\" и \"a\" и \"k\"на локаьном уровне\n\r");
   for(char i = 0; i < 3; i++, k += 0.1) {
      arr[i] = a + k;
      printf("%.1f - %f\n", arr[i], arr[i]);
   }
//---
   return 0;
}
У вас нет доступа для просмотра вложений в этом сообщении.
Си — это причудливый, несовершенный, но невероятно успешный язык.
— Dennis M. Ritchie.
Аватар пользователя
coder-ex
.
.
Сообщений: 848
Возраст: 47
Зарегистрирован: 14 месяцев и 2 дня
Откуда: Томск
Национальный флаг:
Russia
Благодарил (а): 10 раз.
Поблагодарили: 21 раз.
Имя: Константин
Пункты репутации: 2
Ученик трейдера

С С++ - Вопросы программирования

Номер сообщения:#25  Непрочитанное сообщение Kordan » 06 ноя 2016, 02:23

Домашнее задание: Вывести таблицу умножения как в школьной тетради, используя вложенные циклы while и for. https://yadi.sk/i/xAFjvdQ5y8zYq
Скрытый текст: показать
Код: выделить все · Развернуть
#include <stdio.h>

void main(void){

   printf("\n");
   unsigned char i = 1;

    while (i <= 9){
    unsigned char j = 1;
      while(j <= 9){
         printf("%4d", i*j);
      if (0 == (j % 9)) printf("\n");
      j++;
      }
   i++;
    }

    printf("\n");
   return;
}

Скрытый текст: показать
Код: выделить все · Развернуть
#include <stdio.h>

void main(void){
   printf("\n");

   for(unsigned char i = 1; i <= 9; i++){
      for(unsigned char j = 1; j <= 9; j++){
         printf("%4d", i*j);
       if (0 == (j % 9)) printf("\n");
      }
   }

    printf("\n");
   return;
}
Аватар пользователя
Kordan
.
.
      Автор темы
Сообщений: 2451
Возраст: 49
Зарегистрирован: 63 месяцев и 2 дня
Откуда: Саратов
Национальный флаг:
Russia
Благодарил (а): 667 раз.
Поблагодарили: 1220 раз.
Имя: Валерий
Пункты репутации: 25
Молодой трейдерМолодой трейдерМолодой трейдер

С С++ - Вопросы программирования

Номер сообщения:#26  Непрочитанное сообщение coder-ex » 06 ноя 2016, 06:01

Валера, твой выигрыш от 10 итераций между int и unsigned char нулевой, но при этом показываешь плохой стиль используя типы не по назначению. Или ты для микроконтроллеров пишешь код, где вычислительные мощности слабые и в общем ресурсы ограничены? Пойми, сейчас подобной оптимизацией нет смысла заниматься даже для смартфонов :hi_hi_hi:
Ты кстати по вопросам лучше стучись в Telegram, я со следующей неделе тут буду очень редко.
Си — это причудливый, несовершенный, но невероятно успешный язык.
— Dennis M. Ritchie.
Аватар пользователя
coder-ex
.
.
Сообщений: 848
Возраст: 47
Зарегистрирован: 14 месяцев и 2 дня
Откуда: Томск
Национальный флаг:
Russia
Благодарил (а): 10 раз.
Поблагодарили: 21 раз.
Имя: Константин
Пункты репутации: 2
Ученик трейдера

С С++ - Вопросы программирования

Номер сообщения:#27  Непрочитанное сообщение Kordan » 06 ноя 2016, 12:40

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

P.S. :
Запрет на расширения я не ставил. По умолчанию все запрещены. Просто надо добавлять новые. Хотя, я думаю, код в тексте лучше смотрится, чем в файле.
Аватар пользователя
Kordan
.
.
      Автор темы
Сообщений: 2451
Возраст: 49
Зарегистрирован: 63 месяцев и 2 дня
Откуда: Саратов
Национальный флаг:
Russia
Благодарил (а): 667 раз.
Поблагодарили: 1220 раз.
Имя: Валерий
Пункты репутации: 25
Молодой трейдерМолодой трейдерМолодой трейдер

С С++ - Вопросы программирования

Номер сообщения:#28  Непрочитанное сообщение Kordan » 06 ноя 2016, 17:07

Задача. Проверить массив и если в нем попадется хоть один элемент со значением ноль, то прекратить бессмысленный дальнейший его перебор. Используем оператор break.
Скрытый текст: показать
Код: выделить все · Развернуть
    #include <stdio.h>
    #define N 10

    void main (void){
    printf("\n");
       int arr[N] = {6, 5, -4, 3, -7, 2, 7, 0, 3, 9};

       for (int i=0;  i<N;  i++){
          printf("%d ", i); // Просто проверка
        //if (  arr[i]   == 0){
          if (*(arr + i) == 0){
             printf("\nStop. Array contains zero");
             break;
          }
       }
    printf("\n\a");
       return;
    }


Задача. Скопировать из одного массива в другой числа больше нуля. Оператор continue прерывает итерацию цикла, если очередной элемент массива меньше или равен нулю. Дописал пример с использованием указателей, которые работают быстрее стандартного синтаксиса использования массивов с квадратными скобками.
Скрытый текст: показать
Код: выделить все · Развернуть
    #include <stdio.h>
    #define N 10

    void main (void){
    printf("\n");

       int arr[N] = {6, 5, -4, 3, -7, 2, 7, 0, 3, 9};
       int new_arr[N] = {0}, i, j;

        for (i=0, j=0;  i<N;  i++){
            if (*(arr + i) <= 0) continue;
        //  if ( arr[i]    <= 0) continue;
            *(new_arr + j) = *(arr + i);
        //    new_arr[j]   =   arr[i];
            printf("%d ", *(new_arr + j)); // Проверка
        //  printf("%d ",   new_arr[j]  ); // Проверка
            j++;
       }

    printf("\n\a");
        return;
    }

Если условие изменить на противоположное, то можно обойтись и без continue.

Сообщение добавлено... спустя 15 минут 17 секунд:
Стоит ли досконально изучать побитовые операции, действия с двоичными, восьмиричными, 16-тиричными представлениями чисел? Часто ли они пригождаются в программировании?

Сообщение добавлено... спустя 3 часа 22 минуты 29 секунд:
Вывод символов на экран с помощью функций printf и putchar.
Скрытый текст: показать
Код: выделить все · Развернуть
#include <stdio.h>

void main (void){
printf("\n");
//-----------------------------------
char str[] = "Hello";
int i;
//----------
   printf("%s\n", str);    // первое Hello
//----------
for (int i=0; str[i] != '\0';  i++)
   putchar(str[i]);       // второе Hello
//-----------------------------------
printf("\n");
   return;
}


Вывод строки, разделяя ее символы другим символом, например тире, сложнее.
Скрытый текст: показать
Код: выделить все · Развернуть
#include <stdio.h>

void main (void){
printf("\n");
//-----------------------------------
char str[] = "Hello";
int i;

for (i=0; str[i] != '\0';  i++)
   printf("%c-", str[i]);   
   printf("%c%c %c", '\b', '\0', '\n');    // H-e-l-l-o
//----------
for (i=0; str[i] != '\0';  i++){
   putchar(str[i]);
   putchar('-');
}
   printf("%c%c %c", '\b', '\0', '\n');    // H-e-l-l-o
//-----------------------------------
printf("\n");
   return;
}
Последние операторы конструкций убирают лишний символ (тире) в конце строки (H-e-l-l-o-).
Аватар пользователя
Kordan
.
.
      Автор темы
Сообщений: 2451
Возраст: 49
Зарегистрирован: 63 месяцев и 2 дня
Откуда: Саратов
Национальный флаг:
Russia
Благодарил (а): 667 раз.
Поблагодарили: 1220 раз.
Имя: Валерий
Пункты репутации: 25
Молодой трейдерМолодой трейдерМолодой трейдер

С С++ - Вопросы программирования

Номер сообщения:#29  Непрочитанное сообщение Zaaartu » 09 ноя 2016, 01:40

Цитата:
Стоит ли досконально изучать побитовые операции, действия с двоичными, восьмиричными, 16-тиричными представлениями чисел? Часто ли они пригождаются в программировании?

Изучай Валер, лишним не будет. Это основа - "низы" если хочешь. Может и не так часто будут пригождаться при работе с высокоуровневыми языками (сишарп, пхп и др.), но порой бывают задачи которые без эти знаний либо не решаемы вообще, либо требуют ну очень "творческого" подхода.

А куда с форума пропала форма быстрого ответа? И быстрое цитирование выделенного текста...
:wizard: "Еще не волшебник, но уже лечусь" :psih:
Аватар пользователя
Zaaartu
White Pirate
White Pirate
Сообщений: 1394
Возраст: 27
Зарегистрирован: 61 месяцев и 14 дней
Национальный флаг:
Russia
Благодарил (а): 34 раз.
Поблагодарили: 837 раз.
Имя: Михаил
Пункты репутации: 37
Молодой трейдерМолодой трейдерМолодой трейдерМолодой трейдер

С С++ - Вопросы программирования

Номер сообщения:#30  Непрочитанное сообщение Kordan » 09 ноя 2016, 21:25

Код: выделить все · Развернуть
int  main(int argc, char* argv[])

Вот опять, например, главная функция программы в Си. Если разработчики языка Си являются грамотными программистами, то они явно указывают, что функция main может вернуть 4 млрд кодов ошибок, в случае неудачного исполнения программы, причем половина из них со знаком минус. С аргументами вообще маразм. Аргумент argc имеет тип данных int, и содержит количество параметров, передаваемых в функцию main. Причем argc всегда не меньше 1, даже когда мы не передаем никакой информации, так как первым параметром считается имя функции. Если предположить, что в функцию main по замыслу разработчиков языка Си, мы можем передать 2 млрд параметров, то как быть с остальными, отрицательным числом, т.е. отрицательным количеством параметров? И это грамотное использование типов? В принципе это конечно словоблудие.
Аватар пользователя
Kordan
.
.
      Автор темы
Сообщений: 2451
Возраст: 49
Зарегистрирован: 63 месяцев и 2 дня
Откуда: Саратов
Национальный флаг:
Russia
Благодарил (а): 667 раз.
Поблагодарили: 1220 раз.
Имя: Валерий
Пункты репутации: 25
Молодой трейдерМолодой трейдерМолодой трейдер

С С++ - Вопросы программирования

Номер сообщения:#31  Непрочитанное сообщение Kordan » 13 ноя 2016, 03:07

Задача. Написать программу, которая будет считывать введенное пятизначное число. После чего, каждую цифру числа необходимо вывести в новой строке. В этой задаче нужно воспользоваться операцией - остаток от деления %. http://cppstudio.com/post/2591/
Скрытый текст: показать
Код: выделить все · Развернуть
#include <stdio.h>
#include <locale.h>

void main (void){
   start:
printf("\n");
setlocale (LC_ALL, "rus");

unsigned int num;   
const unsigned int k = 10;
char str[] = "цифра равна: ";
printf ("----------------------------------------\n\n");
printf ("\tДеление числа на разряды\n\n");
printf ("----------------------------------------\n");
err:
printf ("Введите целое положительное пятизначное число: ");
printf ("\n\n"); 
scanf  ("%u", &num );
printf ("\n");

if (num < 10000 || num > 99999){
   printf ("Ошибка. Вы ввели не пятизначное число!\n");
   goto err;
}
else{
   printf ("----------------------------------------\n");
   printf ("\nРезультат:\n");
   for (unsigned int i=1;  i<=5;  i++){
      unsigned int j=0;
      switch(i){
         case 1: j= num/10000;   break;
         case 2: j=(num/1000)%k; break;
         case 3: j=(num/100)%k;  break;
         case 4: j=(num/10)%k;   break;
         case 5: j= num%k;       break;
         default: printf ("Ошибка")   ;
      }
   printf ("%d-я %s [%u]\n", i, str, j);
   }
printf ("\n----------------------------------------\n");
}
unsigned short menu;
menu:
printf ("\n1 - Продолжить работу\n0 - Выход из программы\n\nСделайте выбор (1 или 0): ");
scanf ("%hu", &menu );
   switch(menu){
      case 1: goto start; break;
      case 0: return;    break;
      default: {printf ("\nВы ошиблись. Будьте внимательны!\n"); goto menu;}
   }
printf ("\n----------------------------------------\n");
}
Использовал операторы goto, хотя это считается плохим тоном программирования, но оказывается удобным в реализации. Может и можно как-то по другому реализовать. Пока не получается с локализацией русского языка на Windows. setlocale (LC_ALL, "rus") не помогает. На линуксе и без него работает русский.

Скрин моего рабочего стола в ubuntu. Использую Sublime Text, очень удобный редактор, сниппеты позволяют вставлять большие куски кода, множественное выделение и т.д.. GCC версии 5.4.0 находит больше ошибок, чем на windows. На винде последняя 5.3.0
У вас нет доступа для просмотра вложений в этом сообщении.
Аватар пользователя
Kordan
.
.
      Автор темы
Сообщений: 2451
Возраст: 49
Зарегистрирован: 63 месяцев и 2 дня
Откуда: Саратов
Национальный флаг:
Russia
Благодарил (а): 667 раз.
Поблагодарили: 1220 раз.
Имя: Валерий
Пункты репутации: 25
Молодой трейдерМолодой трейдерМолодой трейдер

С С++ - Вопросы программирования

Номер сообщения:#32  Непрочитанное сообщение coder-ex » 15 ноя 2016, 11:52

Kordan писал(а):

Код: выделить все · Развернуть
int  main(int argc, char* argv[])

Вот опять, например, главная функция программы в Си. Если разработчики языка Си являются грамотными программистами, то они явно указывают, что функция main может вернуть 4 млрд кодов ошибок, в случае неудачного исполнения программы, причем половина из них со знаком минус. С аргументами вообще маразм. Аргумент argc имеет тип данных int, и содержит количество параметров, передаваемых в функцию main. Причем argc всегда не меньше 1, даже когда мы не передаем никакой информации, так как первым параметром считается имя функции. Если предположить, что в функцию main по замыслу разработчиков языка Си, мы можем передать 2 млрд параметров, то как быть с остальными, отрицательным числом, т.е. отрицательным количеством параметров? И это грамотное использование типов? В принципе это конечно словоблудие.

видимо ты не понял предназначение аргументов в данной функции, почитай побольше информации, к тому же эта функция создана вместе с языком Си, год не помню точно, но какой то очень "лохматый" :)
насчет возвращаемых значений все то же самое...
Си — это причудливый, несовершенный, но невероятно успешный язык.
— Dennis M. Ritchie.
Аватар пользователя
coder-ex
.
.
Сообщений: 848
Возраст: 47
Зарегистрирован: 14 месяцев и 2 дня
Откуда: Томск
Национальный флаг:
Russia
Благодарил (а): 10 раз.
Поблагодарили: 21 раз.
Имя: Константин
Пункты репутации: 2
Ученик трейдера

С С++ - Вопросы программирования

Номер сообщения:#33  Непрочитанное сообщение coder-ex » 18 ноя 2016, 22:47

Kordan писал(а):

Использовал операторы goto, хотя это считается плохим тоном программирования, но оказывается удобным в реализации. Может и можно как-то по другому реализовать. Пока не получается с локализацией русского языка на Windows. setlocale (LC_ALL, "rus") не помогает. На линуксе и без него работает русский.


В твоем случае лучше завернуть все что до goto в функцию с возвращаемым значением, можно указателем на структуру, если много чего нужно вернуть, а goto говорит о слабом алгоритме, иными словами это костыль из прошлого ))
насчет локализации - есть несколько вариантов, остановись на одном конкретном и давай обсудим как решить проблему
Си — это причудливый, несовершенный, но невероятно успешный язык.
— Dennis M. Ritchie.
Аватар пользователя
coder-ex
.
.
Сообщений: 848
Возраст: 47
Зарегистрирован: 14 месяцев и 2 дня
Откуда: Томск
Национальный флаг:
Russia
Благодарил (а): 10 раз.
Поблагодарили: 21 раз.
Имя: Константин
Пункты репутации: 2
Ученик трейдера

С С++ - Вопросы программирования

Номер сообщения:#34  Непрочитанное сообщение Kordan » 20 ноя 2016, 18:34

Пример с использованием Константного указателя и Указателя на константу:
Скрытый текст: показать
  https://code.martinforex.ru/3
Код: выделить все · Развернуть
#include <iostream.h>
 
int main()
{
    int a=100;//два обычных объекта типа int   
    int b=222;
     
        int *const P2=&a; //Константный указатель
    *P2=987; //Менять значение разрешено
    //P2=&b; //Но изменять адрес не разрешается
 
    const int *P1=&a; //Указатель на константу
        //*P1=110; //Менять значение нельзя
    P1=&b; //Но менять адрес разрешено
 
        const int *const P3=&a;//Константный указатель на константу
    //*P3=155; //Изменять нельзя ни значение
    //P3=&b; //Ни адрес к которому такой указатель привязан
     
    cin.get();
 return 0;
}

Казалось бы мы надежно защищены константами, но проделываем такой трюк и убеждаемся, что значение константного указателя на константу можно изменить с помощью другого указателя.

P.S. :
Пока не победил локаль на windows, на ubuntu работает и без нее.
Аватар пользователя
Kordan
.
.
      Автор темы
Сообщений: 2451
Возраст: 49
Зарегистрирован: 63 месяцев и 2 дня
Откуда: Саратов
Национальный флаг:
Russia
Благодарил (а): 667 раз.
Поблагодарили: 1220 раз.
Имя: Валерий
Пункты репутации: 25
Молодой трейдерМолодой трейдерМолодой трейдер

С С++ - Вопросы программирования

Номер сообщения:#35  Непрочитанное сообщение coder-ex » 21 ноя 2016, 05:56

Kordan писал(а):

Пример с использованием Константного указателя и Указателя на константу:
Скрытый текст: показать
  https://code.martinforex.ru/3
Код: выделить все · Развернуть
#include <iostream.h>
 
int main()
{
    int a=100;//два обычных объекта типа int   
    int b=222;
     
        int *const P2=&a; //Константный указатель
    *P2=987; //Менять значение разрешено
    //P2=&b; //Но изменять адрес не разрешается
 
    const int *P1=&a; //Указатель на константу
        //*P1=110; //Менять значение нельзя
    P1=&b; //Но менять адрес разрешено
 
        const int *const P3=&a;//Константный указатель на константу
    //*P3=155; //Изменять нельзя ни значение
    //P3=&b; //Ни адрес к которому такой указатель привязан
     
    cin.get();
 return 0;
}

Казалось бы мы надежно защищены константами, но проделываем такой трюк и убеждаемся, что значение константного указателя на константу можно изменить с помощью другого указателя.

тут ты неявно приводишь к типу, поэтому и менять уже можно можно. Это один из приемов в программировании. Обычно это делают кастами, что бы было сразу видно и однозначно сработало приведение.
Kordan писал(а):

P.S. :
Пока не победил локаль на windows, на ubuntu работает и без нее.

если я правильно понял, то тебе это не особо нужно
Си — это причудливый, несовершенный, но невероятно успешный язык.
— Dennis M. Ritchie.
Аватар пользователя
coder-ex
.
.
Сообщений: 848
Возраст: 47
Зарегистрирован: 14 месяцев и 2 дня
Откуда: Томск
Национальный флаг:
Russia
Благодарил (а): 10 раз.
Поблагодарили: 21 раз.
Имя: Константин
Пункты репутации: 2
Ученик трейдера

С С++ - Вопросы программирования

Номер сообщения:#36  Непрочитанное сообщение coder-ex » 31 янв 2017, 13:52

Может кто подскажет решение ))
Нужно перебрать все возможные способы размещения в векторе трех значений: -1 0 1
Код который делает это частично:
Код: выделить все · Развернуть
#include <iostream>
#include <algorithm>
#include <cmath>

//--- точка входа в программу------------------------------------------------------------
int main(int argc, char **argv) {
   setlocale(0, "rus");
   int n = 3, m = 0;
   int* array;
   int _cnt = 1;

   std::cout << "Введите длину вектора исследования ";
   std::cin >> m;

   if(n > m)
      std::cout << "Нет решения " << std::endl;
   else {
      array = new int[m + 1];

      for(int i = 0; i < m; i++) {
         if(i < n)
            array[i] = i - 1;
         else
            array[i] = -1;

      std::sort(array, array + m);

      do {
         std::cout << _cnt << ". ";
         for(int i = 0; i < m; i++)
            std::cout << array[i] << " ";

         std::cout << std::endl;
      } while(std::next_permutation(array, array + m));
   }
//---
   return 0;
}

выводит всего шесть вариантов для вектора длиной 3 элемента:
Код: выделить все · Развернуть
Введите длину вектора исследования 3
1. -1 0 1
2. -1 1 0
3. 0 -1 1
4. 0 1 -1
5. 1 -1 0
6. 1 0 -1

а должно быть 27=3^3. Т.е. в данном варианте учитываются только именно присутствие -1 0 1, но не учитываются какие либо отсутствующие варианты из предложенных.
Си — это причудливый, несовершенный, но невероятно успешный язык.
— Dennis M. Ritchie.
Аватар пользователя
coder-ex
.
.
Сообщений: 848
Возраст: 47
Зарегистрирован: 14 месяцев и 2 дня
Откуда: Томск
Национальный флаг:
Russia
Благодарил (а): 10 раз.
Поблагодарили: 21 раз.
Имя: Константин
Пункты репутации: 2
Ученик трейдера

С С++ - Вопросы программирования

Номер сообщения:#37  Непрочитанное сообщение coder-ex » 31 янв 2017, 20:42

Решение описанной выше задачи, может кому пригодится :) Есть правда одна проблема с большими векторами, к примеру вектор на 20 значений, создаст 3^20=3.486.784.401 список векторов ))) и память будет сжираться гигами, куда она девается не разбирался ))
На большой оверхед не обращайте внимание:
Код: выделить все · Развернуть
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <array>
#include <list>
#include <chrono>
#include <thread>

template <typename T>
void InfoOut(std::list<T> &a_array,const std::size_t a_x);
template <typename T>
bool RepetitionTest(std::list<T> &a_array,const std::size_t a_x);
template <typename T>
bool Compare(std::list<T> a_array,T a_vector,const std::size_t a_idx,const std::size_t a_x);

//--- точка входа в программу------------------------------------------------------------
int main(int argc, char **argv) {
   setlocale(0, "rus");

   std::array<int, 3> _model {-1, 0, 1};     // эталон значений
   std::size_t _size = 0;                    // размер вектора
   std::vector<int> _vec;                    // вектор вариантов
   std::list<std::vector<int>> _array_vec;   // список векторов

   std::cout << "Введите длину вектора исследования ";
   std::cin >> _size;
   _vec.resize(_size);

//--- замерим время исполнения
   std::chrono::time_point<std::chrono::high_resolution_clock> start, stop;
   start = std::chrono::high_resolution_clock::now();

   for(auto i = 0; i < std::pow(3, _size)/*27*/; i++) {
      auto _val = i;

      for(int k = 0; k < 3; k++, _val /= 3)
         _vec[k] = _model[_val%3];

      _array_vec.push_back(_vec);
   }

   stop = std::chrono::high_resolution_clock::now();
   std::cout << "время создания шаблона матрицы: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count() << " mcs\n";

   if(!RepetitionTest(_array_vec, _size))
      std::cout << "есть повторения!!!";
   else
      InfoOut(_array_vec, _size);
//---
   return 0;
}
//--- функции ---------------------------------------------------------------------------
/*!
   \brief   Проверка на повторения
   \param   td::list<T> &a_array - массив векторов
   \param   std::size_t a_x - размер одного вектора
   \return  true в случае успеха, иначе false
*/
template <typename T>
bool RepetitionTest(std::list<T> &a_array,const std::size_t a_x) {
   typename std::list<T>::iterator _it_array;

   std::size_t _idx = 0;
   for(_it_array = a_array.begin(); _it_array != a_array.end(); ++_it_array, ++_idx) {
      T _vec(*_it_array);
      if(!Compare(a_array, _vec, _idx, a_x))
         return false;
   }
//---
   return true;
}
/*!
   \brief Сравнение
   \param   std::list<T> &a_array - массив векторов
   \param   T &a_vector - вектор для сравнения
   \param   const std::size_t a_idx - индекс сравниваемого вектора в массиве
   \param   const std::size_t a_x - размер одного вектора
   \return  true в случае отсутствия повторений, иначе false
*/
template <typename T>
bool Compare(std::list<T> a_array,T a_vector,const std::size_t a_idx,const std::size_t a_x) {
   typename std::list<T>::iterator _it_array;

   std::size_t _idx = 0;
   for(_it_array = a_array.begin(); _it_array != a_array.end(); ++_it_array, ++_idx) {

      if(a_idx == _idx)       // если один и тот же вектор
         continue;

      T _vec = *_it_array;
      for(int i = 0; i < a_x; ++i)
         if(_vec[i] == a_vector[i])
            continue;
         else
            return true;
   }

   std::cout << "Совпадение: " << a_idx << " " << _idx;
//---
   return false;
}
/*!
   \brief   Вывод информации в консоль
   \param   td::vector<T> &a_array - массив векторов
   \param   std::size_t a_x - размер одного вектора
*/
template <typename T>
void InfoOut(std::list<T> &a_array,const std::size_t a_x) {
   std::size_t _cnt = 0;
   typename std::list<T>::iterator _it_array;

   std::cout << "--->\n" << std::endl;
   int _num = 1;
   for(_it_array = a_array.begin(); _it_array != a_array.end(); ++_it_array, ++_num) {
      std::cout << _num << ". ";
      T _vec = *_it_array;
      for(int i = 0, j = _vec.size(); i < j; ++i) {
         std::cout << _vec[i] << " ";

         if(_cnt < a_x - 1)
            _cnt++;
         else {
            _cnt = 0;
            std::cout << std::endl;
         }
      }
   }

   std::cout << "--->\n" << std::endl;
}

test_matrix.zip

ВНИМАНИЕ!!! используется стандарт С++11 :)
У вас нет доступа для просмотра вложений в этом сообщении.
Си — это причудливый, несовершенный, но невероятно успешный язык.
— Dennis M. Ritchie.
Аватар пользователя
coder-ex
.
.
Сообщений: 848
Возраст: 47
Зарегистрирован: 14 месяцев и 2 дня
Откуда: Томск
Национальный флаг:
Russia
Благодарил (а): 10 раз.
Поблагодарили: 21 раз.
Имя: Константин
Пункты репутации: 2
Ученик трейдера

С С++ - Вопросы программирования

Номер сообщения:#38  Непрочитанное сообщение coder-ex » 02 фев 2017, 22:12

Ну и чего ни кто не отписывается, как у всех попадали от расчетов компы %)
Сама скорость составления шаблона матрицы в принципе быстрая, все тормозится именно на проверке достоверности уже составленного шаблона матрицы, т.е. для теста алгоритма, к тому же собирать такую большую сущность как список смысла тоже нет, достаточно собирать временными пакетами по несколько десятков тысяч и потом отправлять на GPU для использования в дальнейших расчетах весов ))
Си — это причудливый, несовершенный, но невероятно успешный язык.
— Dennis M. Ritchie.
Аватар пользователя
coder-ex
.
.
Сообщений: 848
Возраст: 47
Зарегистрирован: 14 месяцев и 2 дня
Откуда: Томск
Национальный флаг:
Russia
Благодарил (а): 10 раз.
Поблагодарили: 21 раз.
Имя: Константин
Пункты репутации: 2
Ученик трейдера

Пред.

Вернуться в Программное обеспечение



Кто сейчас на форуме

Пользователь просматривает форум: нет зарегистрированных пользователей

  • Объявления
cron