Das Problem Spezifikation sagt (mehr oder weniger):
Ich habe eine rekursive Funktion zu machen, bekam die 2 Zeiger erhalten:
- Zeiger 1 zum Index [0].
- Zeiger 2 in der Mitte der Zeichenfolge.
Ich muss überprüfen, ob der erste Teil von 0 bis Mitte gleich dem zweiten Teil von Mitte bis Ende ist, wie: ADAMADAM
.
Als Übung in Rekursion ist das in Ordnung; Um die Funktionalität zu implementieren, ist die Rekursion übertrieben (Iteration ist in Ordnung).
Es gibt Verwirrung (Mehrdeutigkeit) über die Schnittstelle zu der Funktion - der Wortlaut der Frage scheint zwei char *
Werte, aber der Code verwendet einen Zeiger auf eine ganze Zahl als zweites Argument. Das ist einzigartig. Ein ganzzahliger Wert könnte sinnvoll sein, ein Zeiger auf eine ganze Zahl jedoch nicht.
Wir müssen sorgfältig die Bedingungen definieren. Unter der gegebenen Beispielzeichenfolge (char str1[] = "ADAMADAM";
) könnten die zwei Zeiger char *p1 = &str1[0]; char *p2 = &str1[0] + strlen(str1)/2;
sein - was p1
Punkte zu dem ersten A
und p2
zu dem dritten A
bedeutet. Betrachten Sie einen alternativen String: char str2[] = "MADAMADAM";
; Die äquivalente Formel würde p1
zeigt auf den ersten M
und p2
zeigt auf der zweiten M
verlassen.
Angenommen p1
und p2
im Gleichschritt erhöht werden, dann gilt:
- Die Saiten unterschiedlich sind, wenn an irgendeinem Punkt vor
*p2
'\0'
entspricht, *p1 != *p2
.
- Wenn
*p2
'\0'
gleich, dann sind die Saiten gleich.
- Per Definition
p1
und p2
Punkt auf dem gleichen Array, so sind pointer Unterschiede legitim.
- Ferner muss
p1
weniger als p2
nützlich zu sein; p1
gleich p2
bedeutet, dass die Strings identisch trivial sind.
- Es ist ein starkes Argument, dass die ‚Mitte der Zeichenkette‘ Kriterium bedeutet, dass entweder
p2[p2 - p1] == '\0'
oder p2[p2 - p1 + 1] == '\0'
(für gerade und ungerade Saitenlängen beziehungsweise). Das heißt, der Abstand zwischen den beiden Zeigern gibt an, wo das Ende der Zeichenfolge sein muss. Das bedeutet, dass die Verwendung von p1 = &str[0]
und p2 = &str[2]
(auf einer der Beispielzeichenfolgen) fehlschlagen sollte, da das Ende der Zeichenfolge nicht an der richtigen Stelle ist. Und wenn die Zeichenfolge "AMAMAMAM"
war, sollte die Verwendung von &str[0]
und &str[2]
fehlschlagen, weil das Ende der Zeichenfolge nicht an der richtigen Stelle ist; dito &str[0]
und &str[6]
.
- Dieses "starke Argument" ist jedoch auch eine Designentscheidung. Es wäre möglich, einfach zu verlangen, dass die Teilkette von
p2
bis EOS (Ende der Kette) die gleiche ist wie die Kette von p1
für die gleiche Länge. In diesem Fall würde die Verwendung von &str[0]
mit entweder &str[2]
oder &str[6]
(oder tatsächlich mit dem normalen &str[4]
) auf "AMAMAMAM"
gut funktionieren.
Die Verwendung einiger dieser Beobachtungen führt zu diesem Code. Wenn Sie wirklich unter der Anweisung sind, const
nicht zu verwenden, entfernen Sie einfach die const
Qualifier, wo sie erscheinen. Der Code funktioniert genauso.
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
static bool identical_halfstrings(const char *p1, const char *p2)
{
assert(p1 <= p2);
assert(strlen(p1) >= strlen(p2) + (p2 - p1));
if (*p2 == '\0')
return true;
if (*p1 != *p2)
return false;
return identical_halfstrings(p1+1, p2+1);
}
int main(void)
{
const char *strings[] =
{
"ADAMADAM",
"MADAMADAM",
"nonsense",
};
enum { NUM_STRINGS = sizeof(strings)/sizeof(strings[0]) };
for (int i = 0; i < NUM_STRINGS; i++)
{
const char *p1 = strings[i];
const char *p2 = strings[i] + strlen(strings[i])/2;
printf("[%s] ([%s]) = %s\n", p1, p2,
identical_halfstrings(p1, p2) ? "TRUE" : "FALSE");
}
return 0;
}
Die zweite Behauptung stellt sicher, dass p1
und p2
auf demselben String verweisen -, dass es keine Null-Byte ist zwischen den Stellen, an von p1
spitz und p2
.
Testfall Ausgabe:
[ADAMADAM] ([ADAM]) = TRUE
[MADAMADAM] ([MADAM]) = TRUE
[nonsense] ([ense]) = FALSE
Nur für das Protokoll, eine iterative Version der gleichen Funktion ist:
static bool identical_halfstrings(const char *p1, const char *p2)
{
assert(p1 <= p2);
assert(strlen(p1) >= strlen(p2) + (p2 - p1));
while (*p2 != '\0')
{
if (*p1++ != *p2++)
return false;
}
return true;
}
es die gleiche Ausgabe für die Beispieldaten erzeugt.
Warum haben Sie dies als 'C++' markiert? – PaulMcKenzie
Warum übergeben Sie einen Zeiger auf 'int' zu' CheckString() '? Und 'i ++' ist wahrscheinlich nicht das, was du willst. –
Hallo David, ty für Antwort ... das ist, was ich gefragt wurde ... von 2 Zeigern. – Alex