Как вывести массив, содержащий вложенные массивы в Паскале

Я создаю базовую концепцию музыкального плеера, используя Паскаль, но мне трудно отобразить альбомы внутри него. В полученной мной ошибке говорится: «(134, 29) Ошибка: не удается прочитать или записать переменные этого типа». Я предполагаю, что он говорит так, потому что я использую массив внутри массива, и ему трудно отображать оба одновременно (хотя я хочу, чтобы он отображал только альбомы, а не треки).

Вот как выглядит мой код:

function ReadAllTrack(prompt: String): Tracks;
var
    i: Integer;
    trackArray: Array of Track;
    trackCount: Integer;
begin
    WriteLn(prompt);
    trackCount := ReadIntegerGreaterThan1('Please enter the number of tracks you would like to add: ');
    Setlength(trackArray, trackCount);
    for i := 0 to trackCount - 1 do
    begin
        WriteLn('Enter the details for your track:');    
        trackArray[i] := ReadTrack();
    end;
    result := trackArray;
end;

function ReadAlbum(): Album;
begin
    result.albumName := ReadString('Album name: ');
    result.artistName := ReadString('Artist name: ');
    result.albumGenre := ReadGenre('Genre:');
    result.trackCollection := ReadAllTrack('Track Collection:');
end;

function ReadAllAlbums(): Albums;
var
    i: Integer;
    albumArray: Array of Album;
    albumCount: Integer;
begin
    albumCount := ReadIntegerGreaterThan1('Please enter the number of albums you would like to add: ');
    Setlength(albumArray, albumCount);
    for i := 0 to albumCount - 1 do
    begin
        WriteLn('Enter the details for your album:');
        albumArray[i] := ReadAlbum();
    end;
    result := albumArray;
end;

procedure DisplayAlbumOptions(listOfAllAlbums: Albums);
var
    userInput: Integer;
begin
    WriteLn('1. Display all albums');
    WriteLn('2. Display all albums for a genre');
    userInput := ReadIntegerRange('Please enter a number (1, 2) to select: ', 1, 2);

    case userInput of
        1: WriteLn(listOfAllAlbums); //Error: Can't read or write variables of this type
    end;
end;

По сути, он попросит пользователя показать 5 вариантов: 1. Добавьте альбомы 2. Показать альбомы так далее

Если пользователь выбирает 1, программа попросит пользователя ввести количество альбомов, которые он хочет ввести. Затем для каждого альбома он попросит ввести детали, а затем треки.

Затем, если пользователь выберет 2, программа попросит пользователя выбрать либо отображение каждого отдельного альбома, либо отображение всех альбомов для одного жанра (я буду работать над этим после решения этой проблемы). Сначала я думал, что это будет так же просто, как WriteLn(TheAlbumArray);, но оказалось, что это было сложнее, чем я думал, потому что я не думаю, что программа может отображать это таким образом. Я попытался разделить альбомы и треки так, чтобы он отображал альбомы только при использовании WriteLn(TheAlbumArray);, но это было невозможно, потому что треки по-прежнему должны находиться «внутри» альбома, поэтому, когда я показываю альбомы и выбираю один из них, тогда он будет отображать треки ....

Любая помощь или предложение по этому поводу и / или по второму будут очень благодарны ^^

Можете ли вы сократить это до минимального примера и указать на строку кода, которая не работает. Это должно быть возможно не более чем в 20 строках кода.

David Heffernan 02.05.2018 07:57

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

Khang 02.05.2018 08:15

Что ж, теперь мы не знаем, что это за типы. Нам не нужен весь ввод и так далее. Конечно, все, что нам нужно, это массив и ваш вызов Writeln. В любом случае вы не можете передать массив Writeln.

David Heffernan 02.05.2018 08:29
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
3
480
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

Однако можно распознать проблему, когда вы передаете массив записей в Writeln. Функция Writeln может принимать в качестве аргументов только определенные простые типы, например строки, числовые типы, логические. Вы, конечно, не можете передать массив в Writeln. Вы должны перебирать массив и обрабатывать каждый член индивидуально.

Так что вы можете попробовать

for i := low(listOfAllAlbums) to high(listOfAllAlbums) do
  WriteLn(listOfAllAlbums[i]);

Но это тоже не работает, потому что listOfAllAlbums[i] - это запись, а запись - составной тип, который нельзя передать в Writeln. Так что вам нужно обрабатывать запись отдельно. Если вы хотите отобразить только заголовок, вы пишете:

for i := low(listOfAllAlbums) to high(listOfAllAlbums) do
  WriteLn(listOfAllAlbums[i].albumName);

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

for i := low(listOfAllAlbums) to high(listOfAllAlbums) do
begin
  WriteLn(listOfAllAlbums[i].albumName);
  for j := low(trackCollection) to high(trackCollection) do
    WriteLn(listOfAllAlbums[i].trackCollection[j]);
end;

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

Khang 02.05.2018 11:18

Спасибо за понимание!

David Heffernan 02.05.2018 11:31

В процедурах Read[ln] и Write[ln] нельзя использовать составные типы (массивы, записи, ...).

Чтобы сделать ваш код более прозрачным, вы можете создать вспомогательный тип для вашего массива (ов) и использовать хорошо известное свойство AsString. Вот пример простого array of Integer:

program foo;

{$mode objfpc}{$H+}
{$modeswitch typehelpers}

uses
    Classes, SysUtils;

type
    TMyArray = array of Integer;

    TMyArrayHelper = type helper for TMyArray
    private
        function GetAsString: string;
        procedure SetAsString(const AValue: string);
    public
        property AsString: string read GetAsString write SetAsString;
    end;

function TMyArrayHelper.GetAsString: string;
var
    i: Integer;
begin
    Result := '';
    for i in Self do
    begin
        if Result <> '' then
            Result := Result + ', ';
        Result := Result + IntToStr(i);
    end;
    Result := '[' + Result + ']';
end;

// Relatively simple parser
// Fill free to implement ones for your array type
procedure TMyArrayHelper.SetAsString(const AValue: string);
var
    tmp, s: string;
    items: TStringArray;
    i: Integer;
begin
    tmp := Trim(AValue);
    if not (tmp.StartsWith('[') and tmp.EndsWith(']')) then
        raise Exception.CreateFmt('Invalid array literal format: "%s"', [tmp]);
    tmp := tmp.Trim(['[', ']']);
    items := tmp.Split([',']);
    for s in items do
        try
            StrToInt(s);
        except
            on e: Exception do
                raise Exception.CreateFmt('Invalid integer literal: "%s"', [s]);
        end;
    SetLength(Self, Length(items));
    for i := 0 to Length(items) - 1 do
        Self[i] := StrToInt(items[i]);
end;

var
    a1, a2: TMyArray;
begin
    a1.AsString := '[1,2,3,5]';
    Writeln('a1 = ', a1.AsString);
    a2.AsString := a1.AsString;
    a2[1] := 999;
    Writeln('a2 = ', a2.AsString);
end.

Другие вопросы по теме