Ввод и вывод двумерного(динамического) массива. (Не могу понять в чем дело.)

Модератор: Модераторы разделов

scriper
Сообщения: 25
ОС: FreeBSD 7.0-STABLE

Ввод и вывод двумерного(динамического) массива.

Сообщение scriper »

Нужно ввести двумерный массив с неопределенной заранее размерностью(NxM) для решения некоторой задачи.

Код: Выделить всё

#include <stdio.h>
int main(){
int N,M; //N- количество строк, M-количество стобцов.
printf("Введи количество строк матрицы A:");
scanf("%d",&N);
printf("Введи количество столбцов матрицы A:");
scanf("%d",&M);
int** A;
A= new int*[N];
//Ввод матрицы
int i,j;
for (i=0;i<N;i++)
 { A[i]=new int[M];
   for(j=0;j<M;j++)
    {
     scanf("%d",&A[i][j]);
    }
 }
//Вывод введенной матрицы
printf("Введенная матрица:");
for (i=0;i<N;i++)
 {
   A[i]=new int[M];
   for(j=0;j<M;j++)
    {
     printf("%d\t",A[i][j]);
    }
  printf("\n");
 }
delete []A;
return 0;
}

Резальтат выполнения

Код: Выделить всё

scriper@scriper.ate.loc: /usr/home/scriper/proj/labs2> g++ lab1_2.cpp
scriper@scriper.ate.loc: /usr/home/scriper/proj/labs2> ./a.out
Введи количество строк матрицы A:2
Введи количество столбцов матрицы A:2
1
2
3
4
Введенная матрица:-1515870811   -1515870811
-1515870811     -1515870811

Где ошибка? :(
Спасибо сказали:

Аватара пользователя
Liksys
Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys »

Сначала отформатируй по человечески код
Спасибо сказали:

scriper
Сообщения: 25
ОС: FreeBSD 7.0-STABLE

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение scriper »

Darth Liksys писал(а):
14.10.2007 15:50
Сначала отформатируй по человечески код

Что ты имеешь ввиду? Это как то повлияет на работаспособность програмы?
Спасибо сказали:

scriper
Сообщения: 25
ОС: FreeBSD 7.0-STABLE

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение scriper »

Все, разбрался :)
Спасибо сказали:

Аватара пользователя
Liksys
Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys »

Понял, как повлияет? :)
Спасибо сказали:

sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение sergio »

Darth Liksys писал(а):
14.10.2007 16:19
Понял, как повлияет? :)

*ржот* :crazy:
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:

Аватара пользователя
azrael
Сообщения: 73
ОС: KUbuntu 8.04 Hardy Heron

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение azrael »

Гениальное решение темы, 5 баллов :notworthy:
Спасибо сказали:

apacho
Сообщения: 110
ОС: MOPSLinux 5.1

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение apacho »

А для чего собственно нужна строка 23?У меня без неё всё отлично работает!
bash-3.1$ ./a.out
Введи количество строк матрицы A:2
Введи количество столбцов матрицы A:2
1
2
3
4
Введенная матрица:1 2
3 4
Окошки не нужны, нужны ПИНГВИНЫ!!!
Слака рулит!!!!!!
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty »

apacho писал(а):
29.10.2007 12:32
А для чего собственно нужна строка 23?У меня без неё всё отлично работает!

ну и код у вас, господа... :( 23я строка это которая с new? А как же у вас с ней работало???
Это кстати не двухмерный массив, это массив указателей на одномерные массивы, и если их удалять, надо сначала удалить все эти одномерные массивы, а затем массив указателей. В Си нет многомерных массивов. Т.е. окончание должно выгладеть примерно так:

Код: Выделить всё

//Вывод и удаление введенной матрицы
printf("Введенная матрица:");
for (i=0;i<N;i++)
{
   for(j=0;j<M;j++)
    {
     printf("%d\t",A[i][j]);
    }
  printf("\n");
  delete[] A[i];
}
delete[] A;
return 0;
}

И вообще, раз оператор new выполнился 1+N раз(в данном случае), значит оператор delete должен выполнится ровно столько же раз.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение sergio »

apacho писал(а):
29.10.2007 12:32
А для чего собственно нужна строка 23?У меня без неё всё отлично работает!

А с ней? :)
В ней и заключалась "неисправность"...
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:

apacho
Сообщения: 110
ОС: MOPSLinux 5.1

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение apacho »

А вот так нельзя сделать?

#include <stdio.h>
int main(){
int N,M; //N- количество строк, M-количество стобцов.
printf("Введи количество строк матрицы A:");
scanf("%d",&N);
printf("Введи количество столбцов матрицы A:");
scanf("%d",&M);
int A[N][M];
//Ввод матрицы
int i,j;
for (i=0;i<N;i++)
{
for(j=0;j<M;j++)
{
scanf("%d",&A[i][j]);
}
}
Окошки не нужны, нужны ПИНГВИНЫ!!!
Слака рулит!!!!!!
Спасибо сказали:

sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение sergio »

apacho писал(а):
29.10.2007 17:24
А вот так нельзя сделать?

Почему низзя? :happy:
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:

apacho
Сообщения: 110
ОС: MOPSLinux 5.1

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение apacho »

Значит и надо так сделать!А то с этими указателями мозг перегреется!
Окошки не нужны, нужны ПИНГВИНЫ!!!
Слака рулит!!!!!!
Спасибо сказали:

Аватара пользователя
Liksys
Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys »

А на старых компилерах нииибуууудет работать :crazy:
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty »

apacho писал(а):
29.10.2007 17:24
А вот так нельзя сделать?

Нет, сам попробуй:

Код: Выделить всё

int N,M;
int A[N][M];

Это ж не бейсик, всё ж... можно int A[N][M];тогда и только тогда, когда N,M целочисленные константы, а у тебя переменные.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

Аватара пользователя
Attila
Сообщения: 125
Статус: Тролль-Лѣсовичокъ
ОС: Свободная aka ArchLinux

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Attila »

Нет, ну совсем недавно же эта тема поднималась :) По стандарту С99 массивы переменной длины допустимы
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty »

Attila писал(а):
29.10.2007 19:35
Нет, ну совсем недавно же эта тема поднималась :) По стандарту С99 массивы переменной длины допустимы

...многомерные? :crazy:
темы что-то не нашёл.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

apacho
Сообщения: 110
ОС: MOPSLinux 5.1

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение apacho »

Ну тогда вот так:
#include <stdio.h>
int main(){
int i; //N- количество строк, M-количество стобцов.
printf("Введи количество строк матрицы A:");
scanf("%d",&i);
const int N=i;
printf("Введи количество столбцов матрицы A:");
scanf("%d",&i);
const int M=i;
int A[N][M];
}
Окошки не нужны, нужны ПИНГВИНЫ!!!
Слака рулит!!!!!!
Спасибо сказали:

Аватара пользователя
Liksys
Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys »

Многомерные! :crazy:

Код: Выделить всё

[liksys@max ~]$ cat > test.c
int main()
{
        int a = 5;
        int b = 10;

        if ( a == 5 ) b = 10;

        int arr[a][b];

        return 0;
}
[liksys@max ~]$ gcc -std=c9x -o test test.c
[liksys@max ~]$ ./test
Но лучше использовать malloc()/free()
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty »

apacho писал(а):
29.10.2007 19:46
Ну тогда вот так:
const int M=i;
int A[N][M];

тоже не пойдёт. M - константная переменная типа const int. Ну хотя бы потому, что компилятору надо выделить памяти под A[][], а он не знает сколько именно. Когда используют new, вопрос стоит по другому: память выделяет не компилятор, а операционная система. Можно сделать так:

Код: Выделить всё

int main()
{
   int A[10][10];
  do{
//ввод N, M так же
     }while(!(N<10 && M<10) || printf("повторите пожалуйста"));
//дальше так-же
}
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

Аватара пользователя
Attila
Сообщения: 125
Статус: Тролль-Лѣсовичокъ
ОС: Свободная aka ArchLinux

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Attila »

Liksys, может, прикрутите где-нить здесь описание массивов в С? Многомерных, переменной длины и т.п. Раз уж такой вопрос возникает у людей с завидным постоянством?
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty »

Liksys писал(а):
29.10.2007 19:59
Многомерные! :crazy:

Больше эксплойтов, хороших и разных. Сначала один неизвестно сколько new понаставил, а вместо того, чтоб прибраться - ещё столькоже new. Дык система у нас самая лучшая, и по стандарту обязана за нами какашки подбирать! А за памятью можно и магазин сбегать. А теперь умные люди и стандарт переписали, пущай программа сколько хошь места в стеки возьмёт, стек большой, на всех хватит... Отстал я от жизни.
Но лучше использовать malloc()/free()

А какая разница, всё равно никто не проверяет, что там malloc вернёт. На исключение надеются, что-ли?
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

Аватара пользователя
Liksys
Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys »

Кто не проверяет, а кто проверяет...
Любую мою программу посмотри, у меня любая функция, которая потенциально может вернуть код об ошибке, заключается в if.
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty »

Liksys писал(а):
29.10.2007 20:25
Кто не проверяет, а кто проверяет...
Любую мою программу посмотри,

Ну в примерах, имхо, допустимо. Чтобы код не заграмождать. Хотя в этой теме наверное и нужно(в смысле ...Для начинающих). Вот только как проверить что там с переменным массивом? Мне интерестно, как туда впихнуть проверку?
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

Аватара пользователя
Liksys
Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys »

Вот и фиг, что никак, если только реагировать на сигналы, но это кастыль :)
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty »

Liksys писал(а):
29.10.2007 20:33
Вот и фиг, что никак, если только реагировать на сигналы, но это кастыль :)

значит никогда не надо так делать. Да и malloc, имхо, тоже не лучший вариант. Никогда мне не приходило в голову его использовать. А такие костыли - давить. Си это не ассемблер.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

Аватара пользователя
Liksys
Сообщения: 2910

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Liksys »

Ну на malloc() глупо катить бочку :)
А такие массивы - это да. Мало ли что в стандарте написано :)
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty »

Liksys писал(а):
29.10.2007 21:07
Ну на malloc() глупо катить бочку :)

она как goto, когда человек точно знает что делает - благо. А если он пишет "как в бейсике" - зло.
А такие массивы - это да. Мало ли что в стандарте написано :)

В стандарте и в правду очень много букв :) Только, имхо, бегинеру всё сразу не нужно, всё равно, всё он не осилит. В первом сообщении приводилась распостронённая задача про двухмерный массив. И данные там были представленны правильно: ввиде массива указателей на массивы. Такой подход наиболее естественнен в си(да навероное и в с++).
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:

Аватара пользователя
Iroln
Сообщения: 201
ОС: openSUSE 10.3

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение Iroln »

Подытоживая и структурируя все вышесказанное. :)
Я это делал так:

ревизия: 09.11.08

Код: Выделить всё

/* Ввод и вывод двумерного динамического массива */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int i, j, m, n, tmp;
    int status;
    double **array;

    printf("Количество строк (q-выход): ");
    status = scanf("%d",&m);
    if (status!=1)
        return 0;

    printf("Количество столбцов (q-выход): ");
    status = scanf("%d",&n);
    if (status!=1)
        return 0;

// Динамическое выделение памяти под двумерный массив
    array = (double**) malloc(m * sizeof(double*));
    if (array==NULL)
    {
        fprintf(stderr,"Не удалось выделить память\n");
        exit(EXIT_FAILURE);
    }
    for (i=0; i<m; i++)
    {
        array[i] = (double*) malloc(n * sizeof(double));
        if (array[i]==NULL)
         {
            fprintf(stderr,"Не удалось выделить память\n");

            for(tmp=0; tmp<i; tmp++)
                free(array[tmp]);
            free(array);
            exit(EXIT_FAILURE);
        }
     }
     fprintf(stderr,"Выделено памяти под массив: %zd байт(а)\n", (sizeof **array)*m*n);

// Ввод массива
    printf("Введите мaссив размерностью %d x %d (q-выход):\n", m, n);
        for (i=0; i<m; i++)
        {
            for (j=0; j<n; j++)
            {
                printf("(%d,%d) ", i+1, j+1);
                if (scanf("%lf", &array[i][j]) != 1)
                {
                    for (tmp=0; tmp<m; tmp++)
                         free(array[tmp]);
                    free(array);
                    return 0;
                }
            }
        }

// Вывод массива
    for (i=0; i<m; i++)
    {
        printf("\n\n");
        for (j=0; j<n; j++)
            printf("%7.1f", array[i][j]);
    }

    printf("\n\n");

    for (i=0; i<m; i++)
    {
        free(array[i]);
    }
    free(array);
    return 0;
}

Код: Выделить всё

iroln@iroln:~/debug> ./io_dyn_arr2
Количество строк (q-выход): 4
Количество столбцов (q-выход): 3
Выделено памяти под массив: 96 байт(а)
Введите массив размерностью 4 x 3 (q-выход):
(1,1) 1
(1,2) 4
(1,3) 2
(2,1) 5
(2,2) 2
(2,3) 5
(3,1) 3
(3,2) 6
(3,3) 5
(4,1) 3
(4,2) 5
(4,3) 3


    1.0    4.0    2.0

    5.0    2.0    5.0

    3.0    6.0    5.0

    3.0    5.0    3.0

iroln@iroln:~/debug>

Задание на дом для начинающих :)
Напишите кусок кода для динамического выделения памяти под массив размерностью n (ну то бишь больше двух).
Тайною мир держится
Спасибо сказали:

Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: Ввод и вывод двумерного(динамического) массива.

Сообщение drBatty »

Код: Выделить всё

// Динамическое выделение памяти под двумерный массив
    array = (double**) malloc(m * sizeof(double*));
    for (i=0; i<m; i++)
        array[i] = (double*) malloc(n * sizeof(double));
    if (array==NULL)
неверно. если памяти в первом malloc не хватит - программа рухнет после второго(даже если ему хватит, при попытке записать по адресу (NULL + i) <= NULL, а если в цикле - тоже рухнет.
видимо так надо:

Код: Выделить всё

// Динамическое выделение памяти под двумерный массив
    array = (double**) malloc(m * sizeof(double*));
    for (i=0; array && i<m; i++)
        if(!(array[i] = (double*) malloc(n * sizeof(double)))
             break;
    if (array==NULL)
    {
        fprintf(stderr,"Не удалось выделить память\n");
        exit(EXIT_FAILURE);
    }
    else
        fprintf(stderr,"Выделено памяти под массив: %zd байт(а)\n", (sizeof **array)*m*n);
тут цикл вообще не начнётся если первый malloc вернёт ноль, а если не вернёт, вылетит из цикла после первого же ошибочного второго malloc'а.
размер массива ИМХО логичнее записать как m*sizeof(double**) + m * (n * sizeof(double))

Код: Выделить всё

free(array);

Эх блин... Столько распинался... А вы так ничего не поняли... :cry: :frusty:
ну не вернётся память обратно!!! вернётся только массив из m указателей на указатели. А m массивов doublе так и останется висеть оторванным :( ладно было бы C++, мы бы деструктор к элементам array написали, он m раз выполнился и m массивов удалил... А так... Эх...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали: