Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
Steelandrew
Заблокирован
1

Что означают эти функции

03.06.2018, 07:34. Просмотров 320. Ответов 16
Метки нет (Все метки)

Что означают эти записи?
C
1
2
system("chcp 1251");
system("cls");
Добавлено через 5 минут
Еще вот это не понятно, для чего getchar 2 раза.
C
1
2
3
free(a);
    getchar();   getchar();
    return 0;
Добавлено через 40 минут
ещё сразу вопрос, почему в этой программе нет функции memset() для обнуления памяти

C
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
26
27
28
29
30
31
32
33
34
35
36
37
38
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
int main()
{
    int *a;  // указатель на массив
    int i, j, n, m;
    system("chcp 1251");
    system("cls");
    printf("Введите количество строк: ");
    scanf("%d", &n);
    printf("Введите количество столбцов: ");
    scanf("%d", &m);
    // Выделение памяти
    a = (int*)malloc(n*m * sizeof(int));
    // Ввод элементов массива
    for (i = 0; i<n; i++)  // цикл по строкам
    {
        for (j = 0; j<m; j++)  // цикл по столбцам
        {
            printf("a[%d][%d] = ", i, j);
            scanf("%d", (a + i * m + j));
        }
    }
    // Вывод элементов массива
    for (i = 0; i<n; i++)  // цикл по строкам
    {
        for (j = 0; j<m; j++)  // цикл по столбцам
        {
            printf("%5d ", *(a + i * m + j)); // 5 знакомест под элемент массива
        }
        printf("\n");
    }
    free(a);
    getchar();   getchar();
    return 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.06.2018, 07:34
Ответы с готовыми решениями:

Объяснить, что означают строки кода
float res = 0; res += f(a); res += f(b); res += f((a + b)/2); ...

Что означают цифры после двоеточия в объявлении полей структуры
У Петзолда встретился с вот таким вот объявлением typedef struct { unsigned...

Что делают эти 2 строки?
#include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; int main() { system(&quot;chcp...

Что означают символы *""
Что означает символ &quot; *&quot;&quot; &quot; в С? Пример: while (str!=*&quot;&quot;)

что делают вот эти две строки?
не понимаю какую функцию они выполняют тут опишите подробно printf...

16
Adrian_One
11 / 11 / 16
Регистрация: 23.04.2018
Сообщений: 77
03.06.2018, 08:07 2
Steelandrew
1)Изменение кодовой страницы и очистка консоли...Один из способов нормального отображение кириллицы в консоли - "chcp 1251".После применения в консоли появляется соответствующая надпись, для очистки консоли используют - "cls"(CleanScreen).
C
1
2
system("chcp 1251");
system("cls");
2)Судя по всему это Dev-C++...Там где то в буфере остался ENTER, первый getchar(); его принял, а второй ждет ввода.
C
1
2
3
free(a);
    getchar();   getchar();
    return 0;
3)Зачем обнулять? Вы выделили диапазон памяти для массива и сразу же его заполнили.

Добавлено через 1 минуту
Это работает?
C
1
a = (int*)malloc(n*m * sizeof(int));
1
Steelandrew
Заблокирован
03.06.2018, 09:04  [ТС] 3
Adrian_One, всё работает, я просто спросил. Это язык Си.

Добавлено через 8 минут
Adrian_One, на счёт memset().. у нас в методичке просто сказано:
после использования функции malloc всегда проверять, успешно ли выделилась память! (проверять указатель на NULL).
После выделения память всегда нужно инициализировать! (memset())
0
Adrian_One
11 / 11 / 16
Регистрация: 23.04.2018
Сообщений: 77
03.06.2018, 09:38 4
Steelandrew
В случаи если malloc() не удалось выделить память, то функции вернет NULL. Проверка:
C
1
2
3
4
    if (a == NULL) {
        puts("Error");
        return -1;
    }
В ваше примере после выделения памяти Вы сразу ее используете...Возможно, в другом случаи, и стоило бы обнулить ведь никогда не знаешь какие значения находились в выделенной памяти
0
COKPOWEHEU
1047 / 729 / 172
Регистрация: 09.09.2017
Сообщений: 3,223
05.06.2018, 11:40 5
Цитата Сообщение от Adrian_One Посмотреть сообщение
Это работает?
C
1
a = (int*)malloc(n*m * sizeof(int));
А что с этим кодом не так? На первый взгляд это обычный двумерный динамический массив.
Цитата Сообщение от Steelandrew Посмотреть сообщение
После выделения память всегда нужно инициализировать! (memset())
...Либо помнить что там мусор и готовиться к увлекательной отладке.
В ряде случаев это оправдано.
Цитата Сообщение от Steelandrew Посмотреть сообщение
memset()
либо сразу calloc(), поскольку частенько инициализация заключается в забивании всего нулями
0
stake-k26
440 / 354 / 287
Регистрация: 25.04.2016
Сообщений: 1,051
05.06.2018, 14:00 6
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
На первый взгляд это обычный двумерный динамический массив.
вообще-то это одномерный массив, а двумерным он "становится" из-за магии указателей (a + i * m + j) и *(a + i * m + j) в циклах.

2 гетчара из-за кривизны функции scanf(), которая любит оставлять после себя символ '\n' в потоке ввода.
0
COKPOWEHEU
1047 / 729 / 172
Регистрация: 09.09.2017
Сообщений: 3,223
05.06.2018, 14:22 7
Цитата Сообщение от stake-k26 Посмотреть сообщение
вообще-то это одномерный массив, а двумерным он "становится" из-за магии указателей
В компьютере вся память - одномерный массив байтов, многомерные массивы это абстракция. И не важно какой уровень абстракции, языка или исходного кода.
Традиционная запись char arr[5][5]; это выделение 25 последовательно идущих байт, только "магию указателей" проводит компилятор скрыто от программиста.
На всякий случай: char **arr; это не динамический двумерный массив, это массив одномерных массивов. Размеры этих массивов не обязательно одинаковы и совершенно точно не идут по порядку.
0
stake-k26
440 / 354 / 287
Регистрация: 25.04.2016
Сообщений: 1,051
05.06.2018, 14:53 8
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
многомерные массивы это абстракция
я не это имел в виду, к двумерному массиву int ** a; вы можете обращаться стандартным способом: a[i][k], однако к массиву выделенному таким образом данная "магия" не применима, поскольку он является одномерным, т.е. int * a; и обращаться к нему получится только как a[i] без доступа ко "второму измерению" штатными средствами. Для чего используется пляска с бубном и указателями.

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

Думаю тут вы мне скажете, что int * a - это не массив, а указатель...
0
SlavaSokolov
170 / 134 / 105
Регистрация: 14.04.2016
Сообщений: 735
05.06.2018, 15:05 9
Цитата Сообщение от stake-k26 Посмотреть сообщение
является одномерным, т.е. int * a
int* a не может быть ни одномерным, ни девятимерным, ни стомерным, так как это указатель!
0
stake-k26
440 / 354 / 287
Регистрация: 25.04.2016
Сообщений: 1,051
05.06.2018, 15:16 10
Цитата Сообщение от stake-k26 Посмотреть сообщение
Думаю тут вы мне скажете, что int * a - это не массив, а указатель...
SlavaSokolov, ага, я за вас рад.

думаю так понятнее будет:
C
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
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdlib.h>
#include <stdio.h>
 
int main (void)
{
    int size_n = 5, size_m = 7; // размеры массива
    int i, k;                   // переменные-счетчики
    int ** a = NULL;            // указатель на будущй двумерный массив a[][]
 
    // запрашиваем память под двумерный массив:
    if ((a = (int**) malloc(size_n * sizeof(int*))) == NULL)
        return -1;      // память не была выделена! выходим с ошибкой
    if ((a[0] = (int*) malloc(size_n * size_m * sizeof(int))) == NULL)
    {
        free(a);        // память не была выделена! Освобождаем ту, что успели занять
        return -1;      // выходим с ошибкой
    }
 
    // если все прошло успешно, переписываем указатели:
    size_t x;
    for (x=1; x<size_n; x++)
        a[x] = a[x-1] + size_m;
 
    // у нас получился двумерный массив a[5][7], к которому мы можем обращаться
    // как обычно:
    for (i=0; i<size_n; i++)
    {
        for (k=0; k<size_m; k++)
            printf("%4d", a[i][k] = i+k);       // заполняем и выводим на экран
        printf("\n");
    }
 
    // в конце программы освобождаем память занятую массивом и выходим:
    free(a[0]);
    free(a);
    return 0;
}
попробуйте то же самое провернуть с массивом
C
1
a = (int*)malloc(n*m * sizeof(int));
0
COKPOWEHEU
1047 / 729 / 172
Регистрация: 09.09.2017
Сообщений: 3,223
05.06.2018, 15:24 11
Цитата Сообщение от stake-k26 Посмотреть сообщение
я не это имел в виду, к двумерному массиву int ** a;
Будьте внимательнее: int **a; это не двумерный массив. В лучше случае это одномерный массив указателей.
Цитата Сообщение от stake-k26 Посмотреть сообщение
вы можете обращаться стандартным способом
Но не могу стандартными функциями вроде memcpy(), memset().
Цитата Сообщение от stake-k26 Посмотреть сообщение
int * a; и обращаться к нему получится только как a[i] без доступа ко "второму измерению" штатными средствами. Для чего используется пляска с бубном и указателями.
Считаете что использование особенностей языка для имитации двумерного массива, являющейся на самом деле не массивом элементов, а массивом массивов, является доказательством?
Цитата Сообщение от stake-k26 Посмотреть сообщение
Вообще какая-то странная у вас тяга к исчерпывающим ответам
Вообще-то все началось с вопроса: "что не так в стандартной инициализации динамического двумерного массива?". У Adrian_One'а почему-то были сомнения в работоспособности такой записи, мне захотелось узнать на чем они основаны.

Добавлено через 3 минуты
Цитата Сообщение от stake-k26 Посмотреть сообщение
думаю так понятнее будет:
Думаю, вам стоило попробовать скомпилировать свой код, прежде чем выкладывать. Вы инициализируете внешний массив и его 0-й элемент. А как же остальные вложенные массивы? Для подобной имитации двумерного массива нужен цикл, инициализирующий все элементы первого массива.
Цитата Сообщение от stake-k26 Посмотреть сообщение
попробуйте то же самое провернуть с массивом
Провернуть что? Сформулируйте задачу конкретнее
1
stake-k26
440 / 354 / 287
Регистрация: 25.04.2016
Сообщений: 1,051
05.06.2018, 15:30 12
COKPOWEHEU, вы всегда такой зануда?

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Провернуть что? Сформулируйте задачу конкретнее
C
1
printf("%4d", a[i][k] = i+k);
думаю конкретнее уже некуда.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
В лучше случае это одномерный массив указателей.
а по-моему это указатель на указатель... если уж так хоцца конкретики.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Но не могу стандартными функциями вроде memcpy(), memset().
а зачем они вам в на столько простом коде?

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Считаете что использование ...
нет не считаю, но давайте раздуем тему еще немножко?

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Думаю, вам стоило попробовать скомпилировать свой код
думаю вы удивитесь, но я его еще и валгриндом проутюжил почитайте код, подумайте, может узнаете для себя что-то новое. Учиться никогда не поздно.
0
COKPOWEHEU
1047 / 729 / 172
Регистрация: 09.09.2017
Сообщений: 3,223
05.06.2018, 15:46 13
Цитата Сообщение от stake-k26 Посмотреть сообщение
попробуйте то же самое провернуть с массивом
Что-то вроде этого, полагаю:
C
1
2
3
4
5
6
7
8
9
10
11
  int m=5, n=3;
  int *arr = (int*)malloc(m*n*sizeof(int));
  if(arr == NULL){printf("Not enough memory\n"); return -1;}
  int *tmp = arr;
  for(int i=0; i<m; i++)
    for(int j=0; j<n; j++){
      tmp[0] = i+j;
      printf("arr[%i, %i] = %i\n", i, j, tmp[0]);
      tmp++;
    }
  free(arr);
Рекомендую обратить внимание: в моем коде на каждый элемент приходится всего одно разыменование, точно так же как в статическом двумерном массиве, либо любом одномерном

Добавлено через 14 минут
Цитата Сообщение от stake-k26 Посмотреть сообщение
а по-моему это указатель на указатель... если уж так хоцца конкретики.
Разные уровни абстракции. Для машины это всего лишь число. Для компилятора - указатель. Для программиста - массив. А для конкретной задачи - составная часть многомерного массива или его имитации.
Цитата Сообщение от stake-k26 Посмотреть сообщение
а зачем они вам в на столько простом коде?
Не верю что не можете придумать применения функции копирования массивов или заполнения одинаковыми значениями.
Цитата Сообщение от stake-k26 Посмотреть сообщение
почитайте код, подумайте, может узнаете для себя что-то новое. Учиться никогда не поздно.
Интересная реализация, такой и правда не видел.
Из недостатков:
- более сложная инициализация: два выделения памяти, да еще цикл настройки
- те же memcpy(), memset() и т.д. нужно использовать очень аккуратно, помня что ваш "массив" это не указатель непосредственно на данные.
- немного больше занимаемая память, причем тем больше, чем больше размерность
- при большой размерности надо считать звездочки
Достоинства:
- более интуитивное обращение к произвольному элементу
- не обязательно хранить размер
Особенности:
- двойное разыменование при доступе к элементу. Впрочем, что быстрее, оно или "магия" неизвестно - в смысле зависит от компилятора
Лично я вряд ли буду этим пользоваться, но вот как альтернатива традиционному массиву массивов вполне пригодится
0
stake-k26
440 / 354 / 287
Регистрация: 25.04.2016
Сообщений: 1,051
05.06.2018, 15:53 14
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Что-то вроде этого, полагаю:
вы неправильно предположили.

но все это написано чуть выше. И да, я никогда не выкладываю непроверенный или нерабочий код. Хотя кто я такой, чтобы об этом говорить, верно?

Добавлено через 2 минуты
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
два выделения памяти
да, все верно, в коде два выделения памяти, но за счет этого и ровно два free, если взять, скажем каноничную реализацию, то там получается одно вы деление памяти для массива указателей и по одному выделению для каждой строки-массива, и точно столько же free для того, чтобы освободить память, так что такой подход избавляет от необходимости выкручиваться с указательной арифметикой и сокращает число обращений к malloc() и free()

если только вы не планируете вовсю играться с указателями.. но для этого есть другие, более удобные способы.
0
COKPOWEHEU
1047 / 729 / 172
Регистрация: 09.09.2017
Сообщений: 3,223
05.06.2018, 16:02 15
Цитата Сообщение от stake-k26 Посмотреть сообщение
вы неправильно предположили.
В таком случае все же прошу расшифровать и написать ТЗ в текстовом виде, а не как кусок кода.
Цитата Сообщение от stake-k26 Посмотреть сообщение
Хотя кто я такой, чтобы об этом говорить, верно?
Для меня один из множества участников форума, о котором у меня нет информации и мнения.
Цитата Сообщение от stake-k26 Посмотреть сообщение
такой подход избавляет от необходимости выкручиваться с указательной арифметикой и сокращает число обращений к malloc() и free()
Как я уже писал, именно такой способ имитации двумерного массива вижу впервые. Поэтому предпочел бы не пытаться косячить самостоятельно. Покажите как этим способом изобразить, скажем, четырехмерный массив. На первый взгляд все же придется городить массивы массивов, но, возможно, все же есть изящный обходной способ.
0
Steelandrew
Заблокирован
05.06.2018, 22:05  [ТС] 16
вот это понеслась у вас
Цитата Сообщение от stake-k26 Посмотреть сообщение
На первый взгляд это обычный двумерный динамический массив.
вообще-то это одномерный массив, а двумерным он "становится" из-за магии указателей (a + i * m + j) и *(a + i * m + j) в циклах.
2 гетчара из-за кривизны функции scanf(), которая любит оставлять после себя символ '\n' в потоке ввода.
stake-k26, вы первый начали с ним спорить)
там (int*)malloc(n*m * sizeof(int)
имелось в виду, что динамическая память выделяется под двумерный массив (в человеческом понимании), потому что были указаны переменные n и m, сколько строк и столбцов.
а так, насколько я понимаю, компьютер вообще не работает напрямую с языком Си, его код преобразуется до машинного кода из нолей и единичек, так о чём тогда спорить, если это (высокоуровневость) всё просто для того, чтобы нам же было удобно понимать что мы пишем. Низкоуровневое программирование наверное вот настоящий хардкор.
0
stake-k26
440 / 354 / 287
Регистрация: 25.04.2016
Сообщений: 1,051
05.06.2018, 22:45 17
Цитата Сообщение от Steelandrew Посмотреть сообщение
насколько я понимаю, компьютер вообще не работает напрямую с языком Си
напрямую компьютер работает только с машинным кодом, т.е. языком нулей и единиц, и любая программа на любом языке программирования транслируется до этих самых нулей и единиц, а чтобы вы не занимались таким вот хардкором, и были придуманы языки более высокого уровня, упрощающие написание программ. Чем выше уровень языка, тем дальше вы от машинного кода, и наоборот.
0
05.06.2018, 22:45
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.06.2018, 22:45

Дана строка. Известно, что она содержит ровно две одинаковые буквы. Найдите эти буквы
Дана строка. Известно, что она содержит ровно две одинаковые буквы. Найдите эти...

Что означают префиксы "_" и "__"?
Доброго Вам времени суток. Что означают префиксы &quot;_&quot; и &quot;__&quot;?. З.Ы.:...

Что означают эти строки
Может кто нибуть подскажет что означают эти строчки, дело в том что на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru