我正在使用Pascal创建音乐播放器的基本概念,但我很难在其中显示专辑。我得到的错误说“(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);
时只显示专辑,但这是不可能的,因为曲目仍然必须在专辑的“内部”,这样当我显示专辑并选择时其中之一,它会显示曲目......
对此和/或第二个的任何帮助或建议将非常感谢^^
答案 0 :(得分:1)
您的原始问题包含许多多余的细节。在编辑之后,您删除了类型声明,但保留了大量多余的细节。
但是,可以识别将记录数组传递给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;
答案 1 :(得分:0)
在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.