WideCharToMultiByte does best-fit mapping for any characters that aren't supported by the specified character set, including stripping diacritics. You can do exactly what you want by using that and passing 20127 (US-ASCII) as the codepage.
function BestFit(const AInput: AnsiString): AnsiString;
const
CodePage = 20127; //20127 = us-ascii
var
WS: WideString;
begin
WS := WideString(AInput);
SetLength(Result, WideCharToMultiByte(CodePage, 0, PWideChar(WS),
Length(WS), nil, 0, nil, nil));
WideCharToMultiByte(CodePage, 0, PWideChar(WS), Length(WS),
PAnsiChar(Result), Length(Result), nil, nil);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(BestFit('aàà????–—€¢?'));
end;
Calling that with your examples produces results you're looking for, including the emdash-to-minus case, which I don't think is handled by Jeroen's suggestion to convert to Normalization form D. If you did want to take that approach, Michael Kaplan has a blog post the explicitly discusses stripping diacritics (rather than normalization in general), but it uses C# and an API that was introduces in Vista. You can get something similar using the FoldString api (any WinNT release).
Of course if you're only doing this for one character set, and you want to avoid the overhead from converting to and from a WideString, Padu is correct that a simple for loop and a lookup table would be just as effective.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…