Avatar billede whynot Nybegynder
22. juni 2004 - 22:27 Der er 22 kommentarer og
1 løsning

stringreplace ' med *

Hejsa

jeg har en tekststreng som indholder "volapyk" dvs. et array[0..1] of kunderecord som er lagt direkte ned i en fil.

Denne tekststreng indholder et hav af ' tegn og det giver problemer når jeg prøver at gemme denne tekststreng i en mysql database.. fordi ' er et tegn som bruges til at adskille variabler med.

derfor har jeg tænkt mig at erstatte alle ' med * med functionen "stringreplace" som jo er en delphi funktion.

tempstring := stringreplace(tempstring, "'", "*", [rfReplaceAll]);

Men DELPHI brokker sig over en unterminated string.. og det er jo klart fordi den antager at ' er sat fordi jeg vil adskille en tekststreng... men det er jo ikke min hensigt.

Anyway.. jeg har prøvet med:
tempstring := stringreplace(tempstring, '''', '*', [rfReplaceAll]);
... men så bliver ' ikke erstattet med *

Jeg kan ikke helt gennemskue hvad pokker jeg skal gøre for at løse problemet.

Kan nogen af jer derude hjælpe?
Avatar billede thesurfer Nybegynder
22. juni 2004 - 22:30 #1
Man plejer at escape sådanna karakter, med et "\"..

så prøv: tempstring := stringreplace(tempstring, '\'', '*', [rfReplaceAll]);
Avatar billede thesurfer Nybegynder
22. juni 2004 - 22:31 #2
ooops.. sådan her:
tempstring := stringreplace(tempstring, "\'", "*", [rfReplaceAll]);

Bruger man ' eller " ved strenge..?

(jeg programmere ikke i Delphi, men i Visual Basic..)
Avatar billede snowball Novice
22. juni 2004 - 22:46 #3
StringReplace(Edit1.Text, '''', '*', [rfReplaceAll]); virker fint hos mig.
Avatar billede cautoo Nybegynder
22. juni 2004 - 22:48 #4
" " er ikke mulige strengindkapslere.. .det skal være ' ' og \ kan heller ikke bruges... men du kan derimod erklære værdien med #39...

tempstring := stringreplace(tempstring, #39, '*', [rfReplaceAll]);
Avatar billede doc404 Novice
23. juni 2004 - 00:24 #5
Når Delphi brokker sig er det en syntax fejl i din kode... Delphi bruger ' til strenge og ikke ". Så snowball's er korrekt.
Avatar billede hrc Mester
23. juni 2004 - 08:52 #6
Hvad om man bruger en af funktionerne QuotedStr() eller AnsiQuotedStr(). De pløjer strengen igennem og alle steder med enkelt' bliver dobbelt - endelig indkapsles strengen med et par ''er.
Avatar billede whynot Nybegynder
23. juni 2004 - 12:43 #7
Tdeltur = record
    indhold: string[100];
    art: string[100];
    navn: string[100];
    tom: string[10];
  end;

  Tgridarray = array[0..10] of Tdeltur;

procedure TForm1.ButtonGemClick(Sender: TObject);
var
  x: integer;
  gridarray: Tgridarray;
  MapFile: file of Tgridarray;
begin
  for x := 0 to 10 do
  begin
    gridarray[x].indhold := inttostr(x);
    gridarray[x].navn := 'TTextualColumn';
    gridarray[x].art := 'TTextualColumn';
    gridarray[x].tom := 'false';
  end;

  AssignFile(MapFile, 'hejsa.txt');
  Rewrite(MapFile);
  Write(MapFile, gridarray);
  CloseFile(MapFile);
end;


function hentgrid_frafil_somstring: string;
var
  myFile: file;
  ch: char;
  tempstring: string;
  i: integer;
begin
  AssignFile(myFile, 'hejsa.txt');
  tempstring := '';
  FileMode := fmOpenRead;
  Reset(myFile, 1);
  while not Eof(myFile) do
  begin
    BlockRead(myFile, ch, 1);
    tempstring := tempstring + ch;
  end;
  CloseFile(myFile);
  result := tempstring;
end;

Nu er det så at jeg gerne vil have tempstring til at være en string hvor ' er lavet om til * 
... men det lader ikke til at virke... når jeg læser et tegn afgangen henter proceduren stadig flere tegn igennem
f.eks. '3' skulle der ikke kun komme ét tegn tilbage som f.eks. ' eller 3 ?

Når jeg kører:
tempstring := stringreplace(tempstring, '''', '*', [rfReplaceAll]);
som virker på andre strings så sker der virkelig ingen verdens ting.. meget skørt..!

er der nogen som har en løsning til mig?
Avatar billede nico26 Nybegynder
24. juni 2004 - 18:03 #8
var
  i : Integer;
  s : string;
begin
  ...

  for i := 1 to Length(s) do
    if s[i] = #39 then
      s[i] = '*';
Avatar billede hrc Mester
24. juni 2004 - 21:09 #9
nico26: Hvad så hvis der forekommer en '*' i data??? Det er ikke en god rutine og den virker ikke begge veje.

WhyNot: Jeg antager at følgende sker ved din:

  tempstring := stringreplace(tempstring, '''', '*', [rfReplaceAll]);

Lad os antage at der er forsøgt fyldt 'Hej's''d''s''s''s's's's'!' ind i TempString. Det er min antagelse at Delphi er ret ligeglad med det og stopper efter 'Hej'. Har du prøvet at skrive TempString ud i en MessageBox eller tage længden på den?

Prøv at sætte en QuotedStr rundt om TempString og se hvad der sker. Det skulle ikke undre mig om den så gled lige ind i MySql.
Avatar billede whynot Nybegynder
24. juni 2004 - 21:19 #10
nico.. ja det burde virke - men det gør det ikke.!?!?

hrc.. længden på min string er 3454. jeg har faktisk prøvet det der med quotedstr.. og det virkede heller ikke.. jeg fatter det simpelthen ikke.!

Af en eller anden grund lader det til at min tempstring ikke bliver gennemløbet korrekt af nogen af de nævnte procedurer og det er jo skørt.! Men faktum er at når jeg gemmer mit array til en fil og derefter samler filens tegn op enkeltvis og sætter dem sammen til en streng - så sker der noget som ikke skal ske.

Jeg har set at selv om min procedure burde samle ét tegn op fra filen - så kan den finde på at samle #4 op.. efter min logik er det to tegn eller`? Og her er det min mistanke bliver - nemlig at '3' kan blive betragtet som ét tegn og ikke tre. Men det virker meget mærkeligt.

For at få det til at køre bliver jeg vel nød til at gennemløbe mit array og selv lave min tempstring "manuelt" f.eks. med værdier adskilt med ; eller sådan noget.. men jeg synes bare det andet burde virke.
Avatar billede whynot Nybegynder
24. juni 2004 - 21:43 #11
det virker til at der er forskel på hvad jeg kan vise ved en showmessage og en "halt-step-by-step" (jeg ved ikke hvad det hedder men det er den funktion hvor man sætter en rød prik ud for den linie som delphi skal stoppe ved) kørsel i delphi. Hvis jeg showmessage'er tempstring[3] altså det 3. tegn i strengen.. så bliver der vist et helt andet tegn end ved denne der før nævnte "halt-step-by-step-delphi-ting".
Avatar billede thesurfer Nybegynder
26. juni 2004 - 11:57 #12
Jeg hopper ud af dette spm..
Hvis I har en besked til mig, skriv en henvisning her: http://www.eksperten.dk/spm/501654
Avatar billede whynot Nybegynder
27. juni 2004 - 06:18 #13
jeg lukker dette spørgsmål og deler point ud til alle som har bidraget med viden.. så hvis alle i spørgsmålet (som ønsker points) lige ville komme med et "svar".. så deler jeg points ud i morgen.

.. jeg ønsker alle tak med Jeres bidrag.. men der må være en eller anden bug i delphi lige på dette lige felt. Hvis jeg en dag finder ud af en løsning eller hvad problemet var - poster jeg det.

Min løsning blev at gennemløbe arrayet inden det blev lagt en i en fil og lave min egen string med værdier adskildt med et ;  Håbløs workaround - men det virker i det mindste.
Avatar billede hrc Mester
27. juni 2004 - 20:00 #14
Jeg ved nu ikke om din løsning er så dum endda. Jeg startede egentlig denne kommentar for at spørge hvorfor du ikke bare læste TGridArray ind igen, sådan som den var skrevet. For mig at se, er det hvad du har brug for.

procedure TForm1.HentGridFraMapFil(var aGrid : TGridArray);
var
  i : integer;
  MapFileStream : TFileStream;
begin
  i := 0; // Du har en grid på 11 elementer - er det en fejl?
  MapFileStream := TFileStream.Create('hejsa.dat',fmOpenRead);
  try
    for i := low(aGrid) to high(aGrid) do
      MapFileStream.ReadBuffer(aGrid[i],sizeof(TDelTur));
  finally
    MapFileStream.Free;
  end; // try
end;

procedure TForm1.SkrivGridTilMapFil(aGrid : TGridArray);
var
  i : integer;
  MapFileStream : TFileStream;
begin
  MapFileStream := TFileStream.Create('Hejse.dat',fmCreate);
  try
    for i := low(aGrid) to high(aGrid) do begin
      with aGrid[i] do begin
        Indhold := IntToStr(i);
        Navn := 'TTextualColumn';
        Art := 'TTextualColumn'; // Burde være en enum type!
        Tom := 'false'; // Hvorfor ikke bare lave den til en boolean?
      end;
      MapFileStream.WriteBuffer(aGrid[i],sizeof(TDelTur));
    end; // for
  finally
    MapFileStream.Free;
  end; // try
end;

Beklager at jeg ikke har haft tid til at kigge dit spørgsmål igennem - håber jeg har ramt noget rigtigt denne gang - sender i alt fald et svar.

Bemærk, at ovenstående ikke er testet, men det håber jeg at få tid til lidt senere. Jeg bruger i øvrigt TFileStreams i stedet for "file of TEtEllerAndet" og blockread - synes det sidste er noget antikveret. Egentlig burde man nedarve TFileStream til en variant der håndterede TDelTur direkte (en nem og pæn løsning)
Avatar billede hrc Mester
27. juni 2004 - 20:22 #15
Nå, men der var ingen fejl i ovenståede - du får lige testprogrammet her

unit FMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

const
  FileNameConst = 'Hejsa.dat'; // Lav konstant i stedet for at skrive 2 steder i koden

type
  TDelTurTypes = (dttTextualColumn); // Bare tilføj flere om de dukker op

(*
  TDelTur = record // Din record
    Indhold : string[100];
    Art : string[100];
    Navn : string[100];
    Tom : string[10];
  end;
*)

  TDelTur = record // Sparer ca. 108 tegn pr. record ved at lave denne version
    Indhold : string[100];
    Art : TDelTurTypes;
    Navn : string[100];
    Tom : boolean;
  end;

  TGridArray = array[0..10] of TDelTur;

  TfrmMain = class(TForm)
    btnRead: TButton;
    btnSave: TButton;
    btnGenerate: TButton;
    procedure btnGenerateClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnReadClick(Sender: TObject);
  private
    fGrid : TGridArray;
    procedure Read(const aFileName : string);
    procedure Save(const aFileName : string);
  public
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

{ TfrmMain }

procedure TfrmMain.Read(const aFileName : string);
var
  i : integer;
  MapFileStream : TFileStream;
begin
  MapFileStream := TFileStream.Create(aFileName,fmOpenRead);
  try
    for i := low(fGrid) to high(fGrid) do
      MapFileStream.ReadBuffer(fGrid[i],sizeof(TDelTur));
  finally
    MapFileStream.Free;
  end; // try
end;

procedure TfrmMain.Save(const aFileName : string);
var
  i : integer;
  MapFileStream : TFileStream;
begin
  MapFileStream := TFileStream.Create(aFileName,fmCreate);
  try
    for i := low(fGrid) to high(fGrid) do
      MapFileStream.WriteBuffer(fGrid[i],sizeof(TDelTur));
  finally
    MapFileStream.Free;
  end; // try
end;

procedure TfrmMain.btnGenerateClick(Sender: TObject);
var
  i : integer;
begin
  for i := low(fGrid) to high(fGrid) do
    with fGrid[i] do begin
      Indhold := IntToStr(i);
      Navn := 'TTextualColumn';
      Art := dttTextualColumn; // 'TTextualColumn';
      Tom := false;
    end;
end;

procedure TfrmMain.btnSaveClick(Sender: TObject);
begin
  Save(FileNameConst);
end;

procedure TfrmMain.btnReadClick(Sender: TObject);
begin
  Read(FileNameConst);
end;

end.

Hvis du vil have en demo af en nedarvet TFileStream, så kan du sige til.
Avatar billede whynot Nybegynder
28. juni 2004 - 09:12 #16
jamen dog.. hrc det ser interessant ud.. men jeg kan ikke helt se hvordan det løser mit problem nemlig at jeg have mit array lavet om til en string som jeg kan lagre i en database. Derefter skal jeg kunne lave den om igen til et array og gemme det i filen igen.

.. det er sikkert mig som ikke forstår hvad du mener. Men det som jeg ser i dit eksempel er en lækker facon at gemme et array ned i en fil og hente den tilbage igen. Og jeg hilser dit oplæg velkommen fordi jeg bestemt kan lære en masse af det.. men det løser bare ikke rigtig mit problem.... der må "mangle" to knapper.. nemlig: "lav array om til string" og "lav string om til array".
Avatar billede whynot Nybegynder
28. juni 2004 - 09:14 #17
...eller er det mig som er en spade?
Avatar billede hrc Mester
28. juni 2004 - 10:33 #18
Jeg tror nok at jeg har en forståelsesblokade fordi jeg synes det er underligt, at du vil gemme hele recorden i et strengfelt.

Skulle jeg gemme recorden i en database, ville jeg gøre det i et blob-felt og så have søgetekst placeret i et specifikt søgefelt (Desuden ville jeg bruge nul-terminerede strenge så der ikke var så meget pladsspild).

Helt ideelt ville jeg nok lave en tabel der havde samme felter som recorden. Det er noget skod det du er på vej ud i - synes jeg altså.
Avatar billede doc404 Novice
28. juni 2004 - 11:18 #19
Jeg har heller ikke helt forstået konceptet, men kan da pege på et par ting:

Når du gemme dit array på den måde og ønsker at læse det som en streng er der en bunke, der går galt.

1. Strengene gemmes på disken som en byte indeholdende længden efterfulgt af indholdet. Derfor vil du støde ind i "underlige" tegn når du læser fra filen. #3 er IKKE to tegn, men en byte med værdien 3 (sikkert en længde).

2. Når du ikke benytter packed record word eller dword aligner delphi felterne. Derfor vil du finde enten nuller eller tilfældige værdier mellem strengende i filen (prøv at åbne den med en hex editor). Og så vil din temp string indeholde nuller på forskellige steder - og så er der intet der vil virke.


>> hrc : sorry, din mail blev "glemt" i en mailserver ændring - svarer dig asap
Avatar billede doc404 Novice
28. juni 2004 - 11:22 #20
Er dit spm i bund og grund et ønske om at lave din array om til en string - som du kan lave om til en array igen?
Avatar billede whynot Nybegynder
28. juni 2004 - 12:59 #21
I har begge ret - det er noget snavs det som jeg er på vej ud i.. det bliver mig mere og mere tydeligt.

doc404: ja basalt set vil jeg gerne have mit array til at være en string og kunne få det tilbage igen.
Avatar billede hrc Mester
28. juni 2004 - 15:35 #22
Hvorfor? Hvad skal du bruge det til?
Avatar billede whynot Nybegynder
29. juni 2004 - 09:04 #23
det er et styk "lappeløsning" der er tale om.!

..jeg prøver at hjælpe en kammerat med et projekt han har.. problemet er en ringe databasestruktur samt kun at have én tuppel til rådighed til dette array.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester