如何在Pascal

时间:2018-05-02 05:53:06

标签: arrays pascal freepascal

我正在使用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);时只显示专辑,但这是不可能的,因为曲目仍然必须在专辑的“内部”,这样当我显示专辑并选择时其中之一,它会显示曲目......

对此和/或第二个的任何帮助或建议将非常感谢^^

2 个答案:

答案 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.