Zeichen in String eins höher zählen funktioniert nicht. Warum?
Klaus1
- php
- programmiertechnik
Hallo,
ich bin schon fast am Verzweifeln...
In dem String "QMF 71328_C Test" möchte ich aus dem "C" ein "D" machen und dann in eine MySQL-Tabelle speichern.
Mein erster Versuch war:
$string = "QMF 71328_C Test";
$rev = substr($string,10,1);
$next_rev = ++$rev;
$string[10] = $next_rev;
$sql = "update tabelle set titel = '$string' where id = '123'";
In der Tabelle wird aber "Array" gespeichert.
Nächster Versuch mit $string = strval($string);
machte keinen Unterschied.
Neuer Versuch mit
$string = substr_replace($string,$next_rev,10,1);
schreibt jetzt einen Leerstring in die Tabelle.
Wenn ich den Code in einer Sandbox teste, funktioniert alles einwandfrei.
Wo ist denn bloß mein Fehler?
LG Klaus
Hallo,
hat sich erledigt. Ich habe den Fehler gefunden. Er lag (natürlich) nicht an dem Code zum Hochzählen des Index, sondern vorher schon an der Ermittlung des Strings.
Danke trotzdem.
LG Klaus
ich bin schon fast am Verzweifeln...
Das wirst Du bals wieder sein - oder jemand anderes.
In dem String "QMF 71328_C Test" möchte ich aus dem "C" ein "D" machen und dann in eine MySQL-Tabelle speichern.
Mein erster Versuch war:
$string = "QMF 71328_C Test"; $rev = substr($string,10,1); $next_rev = ++$rev; $string[10] = $next_rev; $sql = "update tabelle set titel = '$string' where id = '123'";
Offensichtlich willst Du einfach das nächste Zeichen der ASCII-Tabelle nehmen. Das gänge als Einzeiler.
$string[10] = chr( 1 + ord( $string[10] ) );
Ich markiere das als „schlechten Code“, denn die ganze Methode bereitet mir Kopfschmerzen, die hat keine Zukunft:
<?php
# Nicht nachmachen!
$string = "QMF 71328_C Test";
for ( $i = 0; $i < 100; $i++) {
$string[10] = chr( 1 + ord( $string[10] ) );
echo $string.PHP_EOL;
}
Ergebnisse (Auswahl)
…
0 : QMF 71328_D Test
1 : QMF 71328_E Test
2 : QMF 71328_F Test
…
22 : QMF 71328_Z Test
23 : QMF 71328_[ Test
24 : QMF 71328_\ Test
…
29 : QMF 71328_a Test
30 : QMF 71328_b Test
31 : QMF 71328_c Test
…
54 : QMF 71328_z Test
55 : QMF 71328_{ Test
…
60 : QMF 71328_� Test
61 : QMF 71328_� Test
…
188 : QMF 71328_ Test
189 : QMF 71328_ Test
190 : QMF 71328_ Test
191 : QMF 71328_ Test
192 : QMF 71328_ Test
193 : QMF 71328_ Test
194 : QMF 71328_ Test
195 : QMF 71328_ Test
196 : QMF 71328 Test
197 : QMF 71328_ Test
198 : QMF 71328_
Test
199 : QMF 71328_
Test
200 : QMF 71328_
Test
Test QMF 71328_
…
221 : QMF 71328_! Test
222 : QMF 71328_" Test
…
236 : QMF 71328_0 Test
237 : QMF 71328_1 Test
…
245 : QMF 71328_9 Test
246 : QMF 71328_: Test
247 : QMF 71328_; Test
…
252 : QMF 71328_@ Test
253 : QMF 71328_A Test
254 : QMF 71328_B Test
255 : QMF 71328_C Test
256 : QMF 71328_D Test
…
DAS wirst Du nicht wollen, Dein Auftraggeber wohl auch nicht. Bevor das aufscheinende Problem aus Sicht des Programmierers gelöst werden kann muss es eine bessere Vorschrift
Zitat:
In diesem Zusammenhang nutzen der Kryptoexperte Bruce Schneier und die Netzwerksicherheitsfirma RSA den Begriff. In einem Kommentar im RSA-Blog vom 7. Dezember 2010 erweiterte der Gastautor Ian Farquhar das Netzwerkmodell um Layer 8 und noch zwei weitere Layer.
Das gesamte erweiterte OSI-Modell sieht dann wie folgt aus:
- Layer 8: das Individuum (Human Layer)
- Layer 9: die Organisation (Organization Layer)
- Layer 10: der Staat (Legal and External Compliance Layer)
Hallo,
Ich markiere das als „schlechten Code“, denn die ganze Methode bereitet mir Kopfschmerzen, die hat keine Zukunft:
Gut, dass du deinen eigenen Code so markierst. Möglicherweise hat Klaus mit Absicht den Increment-Operator verwendet, der die aufgezeigten Probleme offenbar nicht hat.
Bevor das aufscheinende Problem aus Sicht des Programmierers gelöst werden kann muss es eine bessere Vorschrift
- für den Aufbau des Strings und
- für die Ermittlung des Kennzeichens der "neuen Version" (Bei Dir war das "C"→"D") geben.
Das ist natürlich sinnvoll.
Gruß
Kalk
. Möglicherweise hat Klaus mit Absicht den Increment-Operator verwendet, der die aufgezeigten Probleme offenbar nicht hat.
Mag sein. Aber eine echte Verbesserung tritt nicht ein, bzw. bleibt es bei minestens der aufgezeigten Probleme:
<?php
$string = "QMF 71328_C Test";
for ( $i = 0; $i < 257; $i++) {
$rev = substr($string,10,1);
$next_rev = ++$rev;
$string[10] = $next_rev;
echo "$i : $string" . PHP_EOL;
}
0 : QMF 71328_D Test
1 : QMF 71328_E Test
…
23 : QMF 71328_A Test
24 : QMF 71328_B Test
25 : QMF 71328_C Test
26 : QMF 71328_D Test
…
48 : QMF 71328_Z Test
49 : QMF 71328_A Test
50 : QMF 71328_B Test
51 : QMF 71328_C Test
52 : QMF 71328_D Test
53 : QMF 71328_E Test
…
Aus gutem Grund nehme ich nämlich an, dass die Versionisierung ein[ein]deutig sein soll.
Eine mögliche Lösung könnte dann so aussehen:
<?php
$string = "QMF 71328_C Test";
for ( $i = 0; $i < 257; $i++) {
list( $p1, $p2 ) = explode( '_', $string, 2 );
list( $p2, $p3 ) = explode( ' ', $p2, 2 );
$next_p2 = ++$p2;
$string = $p1.'_'.$next_p2.' '.$p3;
echo "$i : $string" . PHP_EOL;
}
Ausgaben:
…
22 : QMF 71328_Z Test
23 : QMF 71328_AA Test
…
48 : QMF 71328_AZ Test
49 : QMF 71328_BA Test
…
Hallo Raketentheo,
ich hatte gedacht, mit preg_replace_callback könnte es einfacher sein, aber ist es das wirklich? 🤔
$string = "QMF 71328_X Test";
for ($i=0; $i<10; $i++)
{
$string = preg_replace_callback(
"/_(.*?) /",
function($treffer) { return "_" . ++$treffer[1] . " "; },
$string);
echo "$i - nächster Schritt ist $string \n";
}
Rolf
aber ist es das wirklich? 🤔
Kommt drauf an, für wen und für was. 😛
Hallo,
TIL: PHP kann Strings inkrementieren 😲.
Und wiedermal erweist sich: PHP kann alles, aber nichts richtig.
$a = "123_Z";
$b = "123Z";
$c = "Z";
++$a;
++$b;
++$c;
echo "$a \n"; // 123_A
echo "$b \n"; // 124A
echo "$c \n"; // AA
Man kann für jede einzelne der gezeigten Verhaltenweisen gute Gründe finden, aber jede Ausnahme mehr, die man beachten muss, macht es chaotischer.
Rolf
"123_Z" -> "123_A" (erwartet hätte ich "123_AA")
"123Z" -> "124A" (erwartet hätte ich "123AA")
... "geht gar nicht". Aus dem Grund ist das Inkrementieren von Strings in PHP nicht das, was ich empfehlen würde.
Da fällt mir aber ein, ich habe vor Jahren mal was zu kruden Zahlensystemen implementiert.
<?PHP
$NS = new numberSystem('ABCDEFGHIJKLMNOPQRSTUVWXYZ');
$s='A';
echo $s . PHP_EOL;
for($i=0; $i<100; $i++) {
$s = $NS->getString( 1 + $NS->getDec( $s ) );
echo $s . PHP_EOL;
}
class numberSystem
{
protected $arChars = false;
protected $hash = false;
function __construct($var='niceReadable32') {
switch (true) {
case ( is_array($var) ):
return setChars( $var );
case ( 'bin' == $var || 'binär' == $var ):
$this -> setChars ( array('0','1') );
break;
case ( 'alphabet' == $var || 'alpha' == $var ):
$this -> setChars ('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
break;
case ( 'ascii_33_126' == $var || 'ascii_visible' == $var ):
$ar = array();
for ($i=33; $i<127; $i++) { $ar[] = chr($i); }
$this -> setChars($ar);
break;
case( 'niceReadable32' == $var ):
$this -> setChars ( array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','J','K','L','M','N','P','R','S','T','U','V','W','X','Y','Z') );
break;
case( 'decObusfacted' == $var || 'wuerfel' == $var ):
$this -> setChars ( array('0','9','8','7','1','2','3','5','4','6') );
break;
default:
$this -> setChars ( $var );
break;
}
return true;
}
public function getChars() {
return $this -> arChars;
}
public function getHash() {
return $this -> hash;
}
public function setChars($arr) {
if (! is_array( $arr ) ) {
$arr = preg_split('//u', $arr, -1, PREG_SPLIT_NO_EMPTY);
}
if (2 <= count($arr) ) {
$test = array_unique($arr);
if ( $test == $arr) {
$this -> arChars = $arr;
$this -> hash = $this -> mkHash($arr);
return count($arr);
} else {
trigger_error ( 'class: numberSystem, function: setChars :: Der übergebene Array ist nicht unique', E_USER_ERROR );
}
} else {
trigger_error ( 'class: numberSystem, function: setChars :: Es wurde kein Array übergeben oder der Array hat weniger als zwei Elemente', E_USER_ERROR );
}
return false;
}
private function mkHash( $arr ) {
$i=0;
foreach ( $arr as $element ) {
$hash[$element] = $i++;
}
return $hash;
}
public function getDec( $str ) {
$number = 0;
$length = strlen($str);
for ( $i = $length; $i > 0; $i-- ) {
$inv = $length - ( $i );
$char = $str[( $i-1 )];
if ( ! isset ( $this -> hash[$char] ) ) {
trigger_error ( 'class: numberSystem, function: getNumberFromString :: Das Zeichen "'.$char.'" ist in der verwendeten Symboltabelle nicht enthalten', E_USER_ERROR );
return false;
}
$number = $number + pow( count($this -> hash), $inv ) * ( $this -> hash[$char] );
}
return $number;
}
function getString( $int ) {
# gibt die Zahl aus dem beliebigen Zahlensystem (String) zurück
if ( $int > PHP_INT_MAX ) {
trigger_error ( 'class: numberSystem, function: getString :: Es wurde eine zu große Zahl ('.$int.') übergeben. Maximum ist '. PHP_INT_MAX , E_USER_ERROR );
}
if ( 0 == $int ) {
return $this -> arChars[$int];
}
$length = count($this -> arChars);
$str = '';
$positions = 0;
while ( pow( $length, $positions ) <= $int ) {
$positions++;
}
for ($i = $positions; $i > 0; $i-- ) {
$potenz = pow( $length, $i-1 );
$pos = floor( $int / $potenz );
$int = $int % $potenz;
$str = $str . $this -> arChars[$pos];
}
return $str;
}
}
... läuft noch mit PHP 8.0 😀-)
Hallo Rolf,
TIL: PHP kann Strings inkrementieren 😲.
ich wusste das auch noch nicht, und halte dieses "Feature" für höchst fragwürdig.
$a = "123_Z"; $b = "123Z"; $c = "Z"; ++$a; ++$b; ++$c; echo "$a \n"; // 123_A echo "$b \n"; // 124A echo "$c \n"; // AA
Die Logik dahinter erschließt sich mir nicht. Versucht PHP tatsächlich, die semantische Bedeutung eines Strings zu erraten und das basierend auf dieser Semantik zu incrementieren?
Aber selbst wenn, dann geht das erste Beispiel doch komplett in die Binsen. Nach welcher Logik ist "123_A" der Nachfolger von "123_Z"?
Und was ist hiermit:
$s = "March";
$s++;
echo $s;
Wird hier etwa "April" ausgegeben? Wäre ja irgendwie logisch.
Ich habe auf die Schnelle kein PHP zur Hand, sonst würde ich es ausprobieren.
Man kann für jede einzelne der gezeigten Verhaltenweisen gute Gründe finden
Echt? Versuch's mal. Vor allem für den ersten Fall bin ich ratlos.
Live long and pros healthy,
Martin
Hallo,
Und was ist hiermit:
$s = "March"; $s++; echo $s;
Wird hier etwa "April" ausgegeben? Wäre ja irgendwie logisch.
Ich habe auf die Schnelle kein PHP zur Hand, sonst würde ich es ausprobieren.
Mein PHP antwortet mit "Marci"...
Gruß
Kalk
Hi,
Und was ist hiermit:
$s = "March"; $s++; echo $s;
Wird hier etwa "April" ausgegeben? Wäre ja irgendwie logisch.
Ich habe auf die Schnelle kein PHP zur Hand, sonst würde ich es ausprobieren.Mein PHP antwortet mit "Marci"...
okay, das ist, was ich ohne diese ganze Magie erwartet hätte: Der Code des letzten Zeichens im String wird incrementiert, bei einem Überlauf dann auch das vorletzte, und so weiter.
Trotzdem: Ich halte den Increment- oder Decrement-Operator im Zusammenhang mit Strings für "Mumpity"++.
Live long and pros healthy,
Martin
Grundlage für Zitat #2554.
Hallo,
"Mumpity"++.
wenn nicht sogar "Mumpitx"+++
Gruß
Kalk
Hallo Martin,
Ich halte den Increment- oder Decrement-Operator im Zusammenhang mit Strings für "Mumpity"++.
MMD 😂
Decrement ist für gemischte Strings übrigens nicht definiert.
"Z99" kann man nicht dekrementieren. "99" dagegen schon. Argh!
Rolf
n'Abend,
Ich halte den Increment- oder Decrement-Operator im Zusammenhang mit Strings für "Mumpity"++.
MMD 😂
graag gedaan. 😀
Decrement ist für gemischte Strings übrigens nicht definiert.
"Z99" kann man nicht dekrementieren. "99" dagegen schon. Argh!
Wunderbar logisch und konsequent. PHP ist echt immer für Überraschungen gut!
Ich liebe es wie Apfelmus, von dem ich leider kotzen muss[1].
Live long and pros healthy,
Martin
Nein, nicht wirklich. Aber der Spruch passt gerade so gut hierher. ↩︎
Hallo Rolf B,
MMD 😂
inc(MMD) = MMDI
.
Bis demnächst
Matthias
Hallo,
MMD 😂
inc(MMD) = MMDI
.
2501? Kann PHP jetzt auch römisch zählen?
Gruß
Kalk
Hallo Tabellenkalk,
MMD 😂
inc(MMD) = MMDI
.2501? Kann PHP jetzt auch römisch zählen?
Ja. Keine Ahnung. Ich kann.
Bis demnächst
Matthias
Hallo Matthias,
$a = "MMD";
$a++;
echo $a;
MME
leider nicht. Das war wohl selbst R.L. zu viel der Obskurität ⚔️
Rolf
Hallo Der Martin,
Trotzdem: Ich halte den Increment- oder Decrement-Operator im Zusammenhang mit Strings für "Mumpity"++.
Müsste es nicht ++"Mumpity" heißen?
Bis demnächst
Matthias
Hallo Matthias,
Müsste es nicht ++"Mumpity" heißen?
Auf keinen Fall. Es muss
$unsinn = "Mumpity";
++$unsinn;
heißen, weil man Literale nicht inkrementieren kann 😉
Ob das ++ davor oder dahinter kommen muss, oder ob das überhaupt relevant ist, hängt vom Kontext ab. Weißt Du aber sicherlich.
Rolf
n'Abend Matthias,
Trotzdem: Ich halte den Increment- oder Decrement-Operator im Zusammenhang mit Strings für "Mumpity"++.
Müsste es nicht ++"Mumpity" heißen?
das ist egal, solange der Ausdruck nicht selbst Teil eines übergeordneten Ausdrucks ist. Denn ++$x bedeutet: Erhöhe $x um eins, schreibe den Wert zurück und liefere den so erhaltenen Wert als Ergebnis (Pro-Increment), während $x++ bedeutet: Merk dir den Wert von $x als Ergebnis vor, erhöhe ihn um 1 und schreibe ihn zurück (Post-Increment).
Aber Rolf hat natürlich auch Recht: Der Increment- oder Decrement-Operator braucht als Operanden ein LValue, also einen Ausdruck, der links von einem Zuweisungszeichen stehen kann. Oder anders gesagt: Ein Ausdruck, der einen Speicherplatz repräsentiert.
Live long and pros healthy,
Martin
Hallo Martin,
ja, Marci. Ist doch logisch ;)
Ich identifiziere folgende Regeln (und übersehe vermutlich Ausnahmen):
$string
die zu inkrementierende Zeichenkette.$p
auf LEN($string)-1
.$p == -1
, beende die Operation mit "1"
als Ergebnis.$c
auf $string[$p]
$c
ein Match für /[0-8A-Ya-y]/
, inkrementiere seinen Zeichencode um 1, schreibe $c
nach $string[$p]
und beende die Operation mit $string
als Ergebnis.$c == "9"
, setze $c
auf "0"
$c == "Z"
, setze $c
auf "A"
$c == "z"
, setze $c
auf "a"
$c
nach $string[$p]
$p
auf $p - 1
. Solange $p
nicht negativ ist, setze bei 4. fort.$c == "a"
oder $c == "A"
, setze $string
auf $c . $string
. Andernfalls setze $string
auf "1" . $string
.Testfragen: Nenne die Nachfolger von "19Z", "1Z99", "zzz", "zzZ" und "Zzz".
Rolf
Hallo Rolf,
da frage ich mich schon: „Was haben die geraucht?“
Gruß
Jürgen
Hi,
da frage ich mich schon: „Was haben die geraucht?“
Methamphpetamin.
cu,
Andreas a/k/a MudGuard
Hallo Jürgen,
da frage ich mich schon: „Was haben die geraucht?“
spannende Frage. Ich glaube, das möchte ich auch mal probieren. 😀
Wer weiß, was ich dann für hirnrissig-geniale Ideen habe.
Live long and pros healthy,
Martin