Рваные массивы

Тема в разделе "Общие вопросы по С и С++", создана пользователем masime, 8 май 2009.

  1. masime

    masime Гость

    У меня в рваном массиве способ хранения кол-ва элементов - терминальный символ в конце строки. Записать я его записал, но как его мне прочитать? Помогите, пожалйста. Вот код:
    [codebox]//Создание массива
    double** ConstructAr()
    {
    double** p = NULL;
    int N, M;
    //poluchaem lo-vo strok
    do
    {
    randomize();
    N = random(10);
    }while (N < 1 || N > 10);
    printf("N = %d", N);
    //videlyaem pamyat'
    p = (double**)malloc( sizeof(double*)*N + sizeof(int));
    //zapominaem v -1 kol-vo strok
    ((int*)p)[0] = N;
    //sdvigaem ukasatel'
    ((int*)p)++;

    //organizuem postrochnyi vvod
    for (int i=0; i<N; i++)
    {
    //opredelyaem kol-vo simvolov v stroke
    do
    {
    randomize();
    M = random(10);
    }while(M < 1 || M > 10);
    printf("M = %d", M);
    //videlyaem pamyat'
    p = (double*)malloc((M+1)*sizeof(double) + sizeof(int));
    ((int*)(p))[M+1] = M;
    //vvodim elti s klavy
    for (int j=0; j<M; j++)
    {
    double m;
    do
    {
    printf("\nEnter A[%d][%d](1<=A[%d][%d]<=10): ", i,j,i,j);
    scanf("%lf", &m);
    }while(m<1 || m>10);
    p[j]=m;
    }

    }
    return p;
    }
    //вывод массива на экран
    void PrintArray(double **p)
    {
    int N,M;
    N = ((int*)p)[-1];

    for(int i=0; i<N; i++)
    {
    M = //вот здесь как его мне получить?
    for(int j=0; j<M; j++)
    printf("%-6.2lf", p[j]);
    printf("\n");
    }

    }[/codebox]
     
  2. shisik

    shisik Well-Known Member

    Регистрация:
    26 авг 2007
    Сообщения:
    154
    Симпатии:
    0
    Что-то я не совсем понял проблему. Если мне нужно сделать многомерный массив со строками разной длины, я пишу эту длину в начало массива. Кстати, именно так у тебя и сделано для N: ((int*)p)[0] = N; Другого варианта быть не может, т.к. найти неизвестную длину по адресу, который от этой длины как раз и зависит, невозможно.
    И ещё. Здесь ты выделяешь лишний элемент:

    Если ты хочешь записать длину в конец, то зачем выделять M+1 ячеек для данных и ещё одну для длины? Ячейка со смещением M в таком случае будет пустой, т.е. достаточно выделить malloc(M*sizeof(double) + sizeof(int)); Кстати, в случае с N ты именно так и делаешь.
    В таком случае на твой вопрос "M = //вот здесь как его мне получить?" можно ответить так:
    Код (Text):
    M = ((int*)p)[i][0];
    Кстати, если в ((int*)p)[0] ты записывашь длину массива, а потом сдвигаешь указатель ((int*)p)++;, то ты эту длину можно сказать теряешь :) Я б сказал, это плохой тон...
     
  3. masime

    masime Гость

    Задачу придумал не я. И если есть такое условие, значит у нее есть и решение. Длину этого массива по условию необходимо хранить в конце.
    тут действительно косяк((. Но в задче у меня указано: способ хранения кол-ва элементов - терминальный символ в конце строки, а способ хранения количества строк - число в -1 эл-те вектора указателей.
     
  4. shisik

    shisik Well-Known Member

    Регистрация:
    26 авг 2007
    Сообщения:
    154
    Симпатии:
    0
    Тогда всё ясно. нужно выделить какой-то один символ (число), как служебное. Обычно это 0 (в обычных строках char *) и его ставить на конце строки. Но у такого способа есть недостаток - другие элементы массива не могут быть нулями, иначе они будут неверно опознаны как конец строки и все следующие символы этой строки будут потеряны.
    Вот как-то так:
    Код (Text):
    #include <stdio.h>

    const int TERM = -1;

    int N;
    int M;


    int main()
    {
    N = rand() % 10;

    double **p = (double **) malloc(N * sizeof(double*) + sizeof(int));

    ((int *)p)[0] = N;

    double ps;
    int i, j;
    for (i = 1; i < N + 1; i++) {
    M = rand() % 10;

    p[i] = (double *) malloc(M * sizeof(double) + sizeof(int));
    ((int *)p + i)[M] = TERM;

    for (j = 0; j < M; j++)
    p[i][j] = (double) (rand() % 10);
    }

    for (i = 1; i < N + 1; i++) {
    j = 0;
    while (((int *)p + i)[j] != TERM)
    printf("%f\n", p[i][j++]);
    }

    return 0;
    }
     
  5. Гость

    Можно использовать не один символ.
    Например, любую из esc-последовательностей
    тогда проблема решится
     
  6. shisik

    shisik Well-Known Member

    Регистрация:
    26 авг 2007
    Сообщения:
    154
    Симпатии:
    0
    Ну, не на 100%, но в значительной мере это выход. Просто если такой последовательностью будет, скажем, 12345, то теоретически она может встретиться и в середине массива, что приведёт к ошибочному определению его длины :) Хотя вероятность этого значительно ниже, чем с 1 символом...
     
  7. Гость

    Тебе стоит разобраться в том, что такое эскейп - последовательности.
    В грядущем пригодится)
     
  8. masime

    masime Гость

    Подскажите пожалйста, что в этой программе не так и почему она не работает. Сделал как советуетshisik, но все равно не получается(

    Код (Text):
    #include <stdlib.h>
    #include <stdio.h>
    #include <conio.h>


    //Prototype func
    void PrintArray(double **p);
    double** ConstructAr();
    void DestructArray(double **p);

    const int TERM = -1;

    /////////////////////////////////

    void main (void)
    {
    double **pA;
    clrscr();

    pA = ConstructAr();
    PrintArray(pA);
    DestructArray(pA);
    getch();
    }

    double** ConstructAr()
    {
    double **p = NULL;
    int N, M;
    //poluchaem lo-vo strok
    do
    {
    randomize();
    N = random(10);
    }while (N < 1 || N > 10);
    printf("N = %d", N);
    //videlyaem pamyat'
    p = (double **)malloc(N*sizeof(double*) + sizeof(int));
    //zapominaem v -1 kol-vo strok
    ((int *)p)[0] = N;

    //organizuem postrochnyi vvod
    for (int i=1; i<N+1; i++)
    {
    //opredelyaem kol-vo simvolov v stroke
    do
    {
    randomize();
    M = random(10);
    }while(M < 1 || M > 10);

    printf("M = %d", M);
    //videlyaem pamyat'
    p[i] = (double *) malloc(M*sizeof(double) + sizeof(int));
    ((int *)p+i)[M] = TERM;
    //vvodim elti s klavy
    for (int j=0; j<M; j++)
    {
    double m;
    do
    {
    printf("\nEnter A[%d][%d](1<=A[%d][%d]<=10): ", i,j,i,j);
    scanf("%lf", &m);
    }while(m<1 || m>10);
    p[i][j]=m;
    }
    }
    return p;
    }
    void DestructArray(double **p)
    {
    if(!p) return;//proverka korrekt

    int N; // kol-vo strok
    N = ((int *)p)[-1];
    for(int i=0; i<N; i++)
    {
    ((int *)(p[i]))--;
    free(p[i]);
    }
    ((int *)p)--;
    free(p);
    printf("End free");
    }

    void PrintArray(double **p)
    {
    int N;
    N = ((int*)p)[0];
    printf("Poluch N=%d", N);
    getch();

    for(int i=1; i<N+1; i++)
    {
    getch();
    int j = 0;
    while(((int *)p+i)[j] != TERM)
    printf("%f ", p[i][j++]);
    printf("\n");
    }
    }
     
Загрузка...
Похожие Темы - Рваные массивы
  1. Искушенный
    Ответов:
    0
    Просмотров:
    432
  2. Искушенный
    Ответов:
    1
    Просмотров:
    426
  3. Искушенный
    Ответов:
    1
    Просмотров:
    393
  4. Rpp
    Ответов:
    1
    Просмотров:
    812
  5. romanovbadboy2
    Ответов:
    0
    Просмотров:
    670

Поделиться этой страницей