Я создаю базовую концепцию музыкального плеера, используя Паскаль, но мне трудно отобразить альбомы внутри него. В полученной мной ошибке говорится: «(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);
, но это было невозможно, потому что треки по-прежнему должны находиться «внутри» альбома, поэтому, когда я показываю альбомы и выбираю один из них, тогда он будет отображать треки ....
Любая помощь или предложение по этому поводу и / или по второму будут очень благодарны ^^
Хорошо, я попытался сократить его, надеюсь, что это немного помогло.
Что ж, теперь мы не знаем, что это за типы. Нам не нужен весь ввод и так далее. Конечно, все, что нам нужно, это массив и ваш вызов Writeln. В любом случае вы не можете передать массив Writeln.
Ваш исходный вопрос содержал много лишних деталей. После редактирования вы удалили объявления типов, но сохранили большую часть лишних деталей.
Однако можно распознать проблему, когда вы передаете массив записей в 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;
Большое спасибо! У меня это отлично сработало. Я также попытаюсь узнать, какие биты оставить, а какие вырезать в следующий раз, когда я вставлю свой код ...
Спасибо за понимание!
В процедурах 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.
Можете ли вы сократить это до минимального примера и указать на строку кода, которая не работает. Это должно быть возможно не более чем в 20 строках кода.