Permalänk
Medlem

Palindrom program i C++

Jag har fått i uppgift att skiva ett program som kollar om en string är en palindrom eller inte(http://www.susning.nu/Palindrom).
Det ska klara palindromer som tex, ni talar bra latin.
Jag har tänkt att lättast blir om man gör om strängen till lowecase och tar bort alla whitespaces.
Problemet är när jag ska kolla stringen och skriva ut om det är en palindrom eller inte.
Skickar med koden jag har skrivit.

#include <string> #include <iostream> #include <cstdio> using namespace std; string lowerCase(string &s) { char *buf = new char[s.length()]; s.copy(buf, s.length()); for(int i = 0; i < s.length(); i++) { buf[i] = tolower(buf[i]); } string r(buf, s.length()); delete buf; return r; } string removeSpace(string str) { string copy; for(int i = 0; i < str.length(); i++) { if(str[i] != ' ') { copy += str[i]; } } return copy; } void palinCheck(string str) { int beg = 0; int end = str.length()-1; while(str[beg]==str[end]) { beg++; end--; } } void main() { string palin; string palincopy; cout << "Skriv en palindrom: "; getline(cin, palin); palincopy = lowerCase(palin); palin = removeSpace(palincopy); palinCheck(palin); }

Det vill inte visa tabbar korrekt så jag bifogar koden också.

Visa signatur

If a word in the dictionary were mispelled, how would we know?
Steven Wright

Permalänk
Glömsk

Fixade ditt inlägg så det ser bra ut.

Visa signatur

...man is not free unless government is limited. There's a clear cause and effect here that is as neat and predictable as a law of physics: As government expands, liberty contracts.

Permalänk

bool palinCheck(string str) { int beg = 0; int end = str.length()-1; for(int n=0;n<(str.length()/2);n++); { if(str[beg] != str[end]) return false; beg++; end--; } return true; }

EDIT: fixar din main också:

int main() { string palin; string palincopy; cout << "Skriv en palindrom: "; getline(cin, palin); palincopy = lowerCase(palin); palin = removeSpace(palincopy); if(palinCheck(palin)) cout << "Det är ett palindrom" << endl; else cout << "Det är inte ett palindrom" << endl; return 0; }

Permalänk
Medlem

För att forstätta där du lämnade det skulle jag gjort såhär...

void palinCheck(string str){ int cnt_len = 0, pal_len = str.length(); int beg = 0; int end = pal_len - 1; while (str[beg]==str[end]){ beg++; end--; cnt_len++; } if (cnt_len >= pal_len) // strängarna var lika cout << "Japp, det där var ett palindrom!"; else cour << "Najj... det där var inget palindrom, försök igen."; }

Nu kan du "optimera" det hela lite genom att istället för att skapa en till variabel vid namn "cnt_len" använda "beg", då de två faktiskt kommer ha samma värde vid loopens slut. Men jag skrev det sådär för att du skulle kunna se vad som hände lättare...

Permalänk
Medlem

Tackar för hjälpen...

Visa signatur

If a word in the dictionary were mispelled, how would we know?
Steven Wright

Permalänk
Medlem

bool isTruePalindrome(string _string, int _startPos, int _endPos) { return _startPos >= _endPost || // Basfall _string[_startPos] == _string[_endPos) && isTruePalindrome(_string, _startPos++, _endPost--) // Rekursivt anrop }

anrop, i main:

... ... if(isTruePalindrome(palin, 0, palin.length)) ....

Rekursion är fint Har inte testat ovanstående men det borde funka. Principen funkar iaf. Men det är klart, man skriver inte C++ för att få använda rekursion... var bara tvungen

Fast, den snyggaste lösningen, om än inte speciellt effektiv är väl ändå....

bool IsTruePalindrome(string _string)
{
return _string == reverse(_string);
}

Men det förutsätter att det finns en funktion reverse som returnerar sitt argument baklänges och att det går att jämföra hela strängar på datatypen string (minns inte).

Jaja, är lite för trött för att vara konstruktiv. Så ignorera mig, jag bara pladdrar.

Permalänk
Medlem

Istället för lowerCase kan du använda std::transform(palin.begin(), palin.end(), palinCopy.begin(), tolower). Ta bort mellanslag med std::remove_if och string::erase. Sen kan man kolla om det är ett palindrom med std::equal(palinCopy.begin(), palinCopy.end(), palinCopy.rbegin()), om man tagit bort mellanslag och andra skiljetecken. Sen ska det vara int main, inte void!

Permalänk
Glömsk

Lite hastigt:

bool palindrom(char *str) { char *p = str; char *s = str+strlen(str)-1; while(*p && *s) { while(*p==' ')p++; while(*s==' ')s--; if(tolower(*p++) != tolower(*s--)) return false; } return true; }

Du behöver inte hålla på och trolla med strängen utan det är bara pang på rödbetan här. palindrom("ni talar BRA       latIn") returnerar alltså true.

Visa signatur

...man is not free unless government is limited. There's a clear cause and effect here that is as neat and predictable as a law of physics: As government expands, liberty contracts.

Permalänk
Medlem

Som sagt, antalet lösningar för ett program begränsar bara fantasin...

Permalänk

Tävlingsdags igen? Minsta antalet tecken implementerat i C++?

Permalänk
Medlem

såhär kan man skriva det i haskell:

palin a = let fa = concat $ words $ map toLower a in fa == reverse fa

Permalänk
Medlem

Samma antal rader, snyggare men mer ineffektiv (men så långa palindrom brukar man inte ha så det skulle märkas nån skillnad):

bool palindrom(char *str) { char *p = str; char *s = str+strlen(str)-1; bool t = true; while(*p && *s) { while(*p==' ')p++; while(*s==' ')s--; t = t && tolower(*p++) == tolower(*s--) } return t; }

Om vi antar att vi inte har mellanslag i strängen går det att skoja till ännu lite mera

bool palindrom(char *str) { char *p = str; char *s = str+strlen(str)-1; while(*p && *s && tolower(*p++) == tolower(*s--)) {} return p >= s; }

Han inte tänka klart där innan jag råkade skicka inlägget men nån mer vaken borde kunna rätta till ev. fel... ni förstår kanske vad jag fiskar efter

edit

Om vi nu är inne på funktionella språk, min favoritspråkklass så blir det så här i SML:

fun pal s = s = (implode o rev o explode) s;

Vill man kunna hantera mellanslag samt stora/små bokstäver så blir det en aning längre:

fun pal s = let val strip = String.translate (fn c => if c = #" " then "" else str (Char.toLower c)); val s1 = strip s; in s1 = (implode o rev o explode) s1; end

Går att göra kortare men orkar inte nu... Eller jo... det gör jag. Men denna version gör samma sak fast med minskad läsbarhet:

val strip = String.translate (fn c => if c = #" " then "" else str (Char.toLower c)); fun pal s = (strip s) = (implode o rev o explode o strip) s;

Jag har tråkigt...

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Psionicist

while(*s==' ')s--;

Ajabaja! Kan bli otäckt om strängen börjar med mellanslag. C-strängar är bara nollterminerade i ena änden.