web-dev-qa-db-fra.com

Chaîne inverse sans strrev

Il y a quelque temps, lors d'un entretien d'embauche, j'ai eu pour tâche d'inverser une chaîne dans PHP sans à l'aide de strrev.

Ma première solution ressemblait à ceci:

$s = 'abcdefg';
$temp = '';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $temp .= $s{$length - $i - 1};
}
var_dump($temp);
// outputs string(7) "gfedcba"

puis ils m'ont demandé si je pouvais le faire sans doubler l'utilisation de la mémoire (en n'utilisant pas la variable $temp ni aucune variable pour copier la chaîne inversée) et j'ai échoué . fois mais j'ai constamment échoué.

Mon dernier essai ressemble à ceci:

$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $s = $s{$i * 2} . $s;
}
var_dump($s);
// outputs string(14) "gfedcbaabcdefg"

Ce n'est pas une solution pour couper "abcdefg" après la boucle car je doublerais encore la quantité de mémoire utilisée. Je dois supprimer le dernier caractère de chaque itération de la boucle.

J'ai essayé d'utiliser mb_substr comme ceci:

$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $s = $s{$i * 2} . mb_substr($s, $length - $i - 1, 1);
}
var_dump($s);

mais cela ne me donne que des erreurs Uninitialized string offset.

C'est là que je suis coincé (encore). J'ai essayé de googler, mais toutes les solutions que j'ai trouvées ont soit echo les caractères directement, soit une variable temporaire.

J'ai également trouvé la question PHP inversion de chaîne sans utiliser de mémoire supplémentaire mais il n'y a pas de réponse à la mesure de mes besoins.

37
prehfeldt

C'est intéressant. Voici quelque chose que je viens de proposer:

$s = 'abcdefghijklm';
for($i=strlen($s)-1, $j=0; $j<$i; $i--, $j++) {
    list($s[$j], $s[$i]) = array($s[$i], $s[$j]);
}
echo $s;

list() peut être utilisé pour assigner une liste de variables en une seule opération. Donc, ce que je fais, c'est simplement échanger des caractères (en commençant par le premier et le dernier, puis le deuxième, le premier et l'avant-dernier et ainsi de suite, jusqu'à ce qu'il atteigne le milieu de la chaîne)

La sortie est mlkjihgfedcba..__ N'utilisant aucune autre variable que $s et les compteurs, j'espère que cela correspond à vos critères.

42
ksbg

Vous pouvez utiliser le fait que, dans PHP, une chaîne peut être considérée comme un tableau de caractères

Dans ce cas, vous souhaitez fondamentalement remplacer chaque caractère $i situé à gauche du milieu de la chaîne par le caractère $j situé à droite au centre, à la même distance. 

Par exemple, dans une chaîne de sept caractères, le caractère du milieu est en position 3. Le caractère en position 0 (distance 3) doit être échangé avec le caractère en position 6 (3 + 3), le caractère en position 1 (distance 2). ) doit être échangé avec le caractère en position 5 (3 + 2), etc.

Cet algorithme peut être implémenté comme suit:

$s = 'abcdefg';

$length = strlen($s); 
for ($i = 0, $j = $length-1; $i < ($length / 2); $i++, $j--) {
    $t = $s[$i];
    $s[$i] = $s[$j];
    $s[$j] = $t;
}

var_dump($s);
24
ebo
$string = 'abc';

$reverted = implode(array_reverse(str_split($string)));
9
Bartłomiej Wach

Essaye ça:

$s = 'abcdefg';

for ($i = strlen($s)-1; $i>=0; $i--) {
       $s .= $s[$i];
       $s[$i] = NULL;
 }
var_dump(trim($s));
7
Bushra Shahid

Vous pouvez utiliser l'astuce XOR swap.

function rev($str) {
    $len = strlen($str);

    for($i = 0; $i < floor($len / 2); ++$i) {
        $str[$i] = $str[$i] ^ $str[$len - $i - 1];
        $str[$len - $i - 1] = $str[$i] ^ $str[$len - $i - 1];
        $str[$i] = $str[$i] ^ $str[$len - $i - 1];
    }

    return $str;
}

print rev("example");
7
Gerard

Voici la version PHP7 de ceci:

echo "\u{202E}abcdefg"; // outs: gfedcba
6

Les chaînes PHP sont un peu mutables , mais, en raison de la copie sur écriture , il est très difficile de les modifier sur place sans qu'une copie ne soit créée. Certaines des solutions ci-dessus fonctionnent, mais uniquement parce qu'elles sont autonomes; certains échouent déjà car ils définissent une fonction sans argument Passe-à-Référence. Pour que le code fonctionne réellement sur place dans un programme plus volumineux, vous devez être particulièrement attentif aux affectations, aux arguments des fonctions et aux étendues.

Exemple:

$string1 = 'abc';
$string2 = $string1;
$string1[0] = 'b';
print("$string1, $string2");

> "abc, bbc"

Je suppose que si, entre l’initialisation de la variable et sa modification, vous n’utilisiez que des assignations de référence (&=) et des arguments de référence (function rev(&$string)) (ou affectez la chaîne à une propriété d’objet initialement, puis ne l’assignez jamais variable), vous pouvez pouvoir modifier la valeur d'origine de la chaîne sans effectuer de copie. C'est un peu ridicule, cependant, et je suppose que l'intervieweur qui a posé cette question ne connaissait pas la copie sur écriture.

Ce n'est pas tout à fait la même chose que l'immuabilité dans d'autres langues, d'ailleurs, car cela s'applique aussi aux tableaux:

$a = [0, 1, 2];
$b = $a;
$b[0] = 1;
print(implode($a).implode($b));

> "012112"

Pour résumer, tous les types (sauf pour les objets à partir de PHP5) sont affectés à la copie sur écriture sauf si vous utilisez spécifiquement l'opérateur &=. L'affectation ne les copie pas, mais contrairement à la plupart des autres langages (C, Java, Python ...) qui changent la valeur d'origine (tableaux) ou n'autorisent pas l'accès en écriture (chaînes), PHP créera une copie en mode silencieux avant d’apporter des modifications.

Bien sûr, si vous passez à une langue avec des pointeurs plus classiques et passez également à des tableaux d'octets au lieu de chaînes, vous pouvez utiliser XOR pour échanger chaque paire de caractères à la place:

for i = 0 ... string.length / 2:
    string[i] ^= string[string.length-1-i] 
    string[string.length-1-i] ^= string[i]
    string[i] ^= string[string.length-1-i]
5
Christoph Burschka

@EricBouwers répond, mais vous pouvez supprimer la 2ème variable de substitution $j

function strrev2($str)
{
    $len = strlen($str);
    for($i=0;$i<$len/2;$i++)
    {
        $tmp = $str[$i];
        $str[$i] = $str[$len-$i-1];
        $str[$len-$i-1] = $tmp;
    }

    return $str;
}

Testez pour la sortie:

echo strrev2("Hi there!"); // "!ereht iH"
echo PHP_EOL;
echo strrev2("Hello World!"); // "!dlroW olleH"

Cela passera par la liste et s'arrêtera à mi-chemin, il échangera le plus à gauche et le plus à droite, et ira de l'avant vers l'intérieur, et s'arrêtera au milieu. Si le nombre est impair, le chiffre pivot n'est jamais échangé avec lui-même, et s'il est pair, il échange les deux médianes et s'arrête. La seule mémoire supplémentaire utilisée est $len pour plus de commodité et $tmp pour la permutation.

Si vous souhaitez une fonction qui ne renvoie pas une nouvelle copie de la chaîne, mais modifie simplement l'ancienne, vous pouvez utiliser les éléments suivants:

function strrev3(&$str)
{
    $len = strlen($str);
    for($i=0;$i<$len/2;$i++)
    {
        $tmp = $str[$i];
        $str[$i] = $str[$len-$i-1];
        $str[$len-$i-1] = $tmp;
    }
}

$x = "Test String";
echo $x;           // "Test String"
strrev3($x);
echo PHP_EOL;
echo $x;           // "gnirtS tseT"

L'utilisation de &$str passe un pointeur direct sur la chaîne pour la modifier à la place.

Et pour une implémentation plus simple comme @treegardens, vous pouvez réécrire en tant que:

$s = 'abcdefghijklm';
$len = strlen($s);
for($i=0; $i < $len/2; $i++) {
    list($s[$i], $s[$len-$i-1]) = array($s[$len-$i-1], $s[$i]);
}
echo $s;

Il a la même logique, mais j’ai un peu simplifié la boucle for.

4
JPMC

C'est trop simple

//Reverse a String

$string = 'Basant Kumar';
$length = strlen($string);

for($i=$length-1;$i >=0;$i--){
    echo $string[$i];
}
3
user4931222

Vous pouvez également utiliser une récursion pour inverser la chaîne. Quelque chose comme ça par exemple: 

function reverse($s) {

    if(strlen($s) === 1) return $s;

    return substr($s, strlen($s)-1) . reverse(substr($s , 0, strlen($s)-1));
}

Ce que vous faites ici renvoie en fait le dernier caractère de la chaîne, puis vous appelez à nouveau la même fonction avec la sous-chaîne contenant la chaîne initiale sans le dernier caractère. Lorsque vous atteignez le point où votre chaîne ne compte qu'un caractère, vous mettez fin à la récursivité. 

3
csdinos

Voici mon code pour résoudre votre problème 

 <?php
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $s = $s{$i}.mb_substr($s,0,$i).mb_substr($s,$i+1);
}
var_dump($s);
?>
3
Islam Zedan

Vous pouvez utiliser ce code pour inverser une chaîne sans utiliser la fonction reserved de php. 

Code:

<?php

function str_rev($y)// function for reversing a string by passing parameters
{
for ($x = strlen($y)-1; $x>=0; $x--) {
       $y .= $y[$x];
       $y[$x] = NULL;
 }

echo $y;

}
str_rev("I am a student");
?>

Sortie:

tneduts a ma I

Dans le code ci-dessus, nous avons transmis la valeur de la chaîne en tant que paramètre. Nous avons effectué l'inversion de chaîne à l'aide de la boucle for.

1
atif

vous pouvez utiliser substr avec un début négatif.

Théorie et explication

vous pouvez commencer par la boucle for avec un compteur compris entre 1 et la longueur d'une chaîne, puis appelez substr itération interne avec counter * -1 (qui convertira le compteur en valeur négative) et en longueur de 1.

Donc, pour la première fois, le compteur serait 1 et en le multipliant par -1, il deviendra -1

Donc substr('abcdefg', -1, 1); vous donnera g
et la prochaine itération substr('abcdefg', -2, 1); vous donnera f
et substr('abcdefg', -3, 1); vous obtiendrez e
etc ...

Code

$str = 'abcdefghijklmnopqrstuvwxyz';
for($i=1; $i <= strlen($str); $i++) {
    echo substr($str, $i*-1, 1);
}

En action: https://eval.in/583208

1
kamal pal

vous pouvez essayer ça ..

$string = "NASEEM";
$total_Word = strlen($string);      
for($i=0; $i<=$total_Word; $i++)
{
   echo substr($string,$total_Word-$i,1);
}
0
Naseem Ahmad

j'ai utilisé certaines fonctions intégrées mais sans fonction str_rev. 

<?php


$text = "red";

$arr = str_split($text);

$rev_text =  array_reverse($arr);

echo join(" ",$rev_text);


?>
0
Mirthful Nahid
   <?php
     $value = 'abcdefg';
     $length_value = strlen($value);
     for($i = $length_value-1; $i >=0 ;$i--){    
       echo $value[$i];
     }
   ?>
0
Siddharth Shukla
public function checkString($str){
    if(!empty($str)){ 
        $i = 0;
        $str_reverse = '';

        while(isset($str[$i])){ 
            $strArr[] = $str[$i];
            $i++;
        }
        for($j = count($strArr); $j>= 0; $j--){ 
            if(isset($strArr[$j])){
                $str_reverse .= $strArr[$j];
            }
        }
        if($str == $str_reverse){ 
            echo 'It is a correct string';
        }else{
            echo 'Invalid string';
        }
    }
    else{
        echo 'string not found.';
    }
}
0
Sanjay Verma

Essaye ça  

<?php
$str="abcde";
for($i=strlen($str)-1;$i>=0;$i--){
    echo $str[$i];
}
?>

sortie

edcba

0
Pavan Hukerikar

La solution suivante est très simple, mais elle fait le travail:

$string = 'Andreas';
$reversedString = '';

for($i = mb_strlen($string) - 1; $i >= 0; $i--){
    $reversedString .= $string[$i];
}

var_dump($reversedString) puis résultats: string(7) "saerdnA"

0
Andreas
//Reverse String Word by Word
$str = "Reverse string Word by Word";
$i = 0;
while ($d = $str[$i]) {
    if($d == " ") {
        $out = " ".$temp.$out;
        $temp = "";
    }
    else
        $temp .= $d;

    $i++;
}
echo $temp.$out;
0
Sagar Navale

Ceci est ma solution pour résoudre ce problème.

$in = 'This is a test text';
$out = '';
// find string length
$len = strlen($in);

// loop through it and print  it reverse
for ( $i = $len - 1; $i >=0;$i-- )
{
    $out = $out.$in[$i];
 }

echo $out;
0
Ihor