Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Aug 2002

Nybörjarfråga C

Hej,

Jag försöker mig på att skriva en funktion som kastar om bokstäverna i en textsträng.

Problemet är att jag inte vet riktigt hur jag ska anropa funktionen. Om jag provar med tex putchar(StringReverse("kaffekopp")), klagar kompilatorn på typfel

#include <stdlib.h> #include <stdio.h> int strnLen(char *str){ char *p = str; while( *p != '\0') *p++; return p-str; } char *StringReverse(char *str){ int len = strnLen(str); char temp; char a; for(int i=0; i<len/2; i++){ a = str[len-i]; temp = str[i]; str[i] = str[len-i]; str[len-i] = temp; } return str; }

» Richard Simmons will make you his bitch...

Trädvy Permalänk
Medlem
Plats
i din garderob
Registrerad
Sep 2007

printf borde väl fungera.

Bilanaloger är som Volvo — varenda svenne kör med dem

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Apr 2004

Man kan också misstänka att kompilatorn ogillar att "kaffekopp" är konstant.

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Aug 2002

Hm, verkar kompilera nu iaf, men får ett segfault av någon anledning.

» Richard Simmons will make you his bitch...

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Nov 2001

Det där funkar inte, du måste reversa en konstant sträng till ett nytt minnesområde, alt. kopiera den dit först.

const char* src = "kaffekopp" char dst[512]; StringReverse(dst, src, 512); // tar stränglängd också så det inte overflowar.

eller

const char* src = "kaffekopp" char dst[512]; strncpy(dst, src, 512); StringReverse(dst);

Anledningen till detta är att kompilatorn lägger konstanter så som strängar i ett segment som är skrivskyddat. Det du sedan tillderar src är INTE strängen utan en pekare det, strängen i sig är fortfarande skrivskyddad.

void@qnet
teeworlds, stålverk80, evil schemer, c, c++
Languages shape the way we think, or don't.

Trädvy Permalänk
Medlem
Plats
/dev/null
Registrerad
Dec 2004

Tog bort mitt inlägg som innehöll felaktiga råd. Lyssna jdv på istället.

I am Thon, eat my spread!

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Aug 2002

Tack!

Nu funkar det.

» Richard Simmons will make you his bitch...

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Apr 2004
Citat:

Ursprungligen inskrivet av Ben_Dover
Nu funkar det.

Gör det verkligen det? Som det ser ut nu borde väl även den avslutande nollan behandlas av omkastningsfunktionen och följaktligen placeras först?

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Aug 2002
Citat:

Ursprungligen inskrivet av Elgot
Gör det verkligen det? Som det ser ut nu borde väl även den avslutande nollan behandlas av omkastningsfunktionen och följaktligen placeras först?

Det har du rätt i, jag tänkte inte på det. Som det ser ut nu måste jag sätta p att peka på dst[1] istället för 0.

Hur löser man det?

» Richard Simmons will make you his bitch...

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Apr 2004
Citat:

Ursprungligen inskrivet av Ben_Dover
Hur löser man det?

int len = strnLen(str) -1;

borde väl räcka?

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Aug 2002
Citat:

Ursprungligen inskrivet av Elgot

int len = strnLen(str) -1;

borde väl räcka?

» Richard Simmons will make you his bitch...

Trädvy Permalänk
Medlem
Plats
Hedesunda
Registrerad
Dec 2005

Jämför med C++ varianten som är lite enklare att impla, en av anledningarna att undvika C om man strängar dvs undvika onödiga ofrånkomliga buggar med (noll)pekare. Otestad kod.

CString StringReverse(CString csSource) { CString csReverse = csSource; int iLength = csSource.GetLength(); for(int iIndex=0; iIndex<iLength; iIndex++) { csReverse.SetAt(iLength-1-iIndex,csSource.GetAt(iIndex)); } return csReverse; } int main(int argc, char* argv[]) { CString csKaffekopp = "kaffekopp"; return printf("%s",StringReverse(csKaffekopp)); }

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Apr 2004

Om man har CString:ar och vill skriva ännu mindre borde det väl räcka med att anropa

csKaffekopp.MakeReverse();

Trädvy Permalänk
Medlem
Plats
Linköping
Registrerad
Jun 2007

Om man använder standard C++ så är det ännu enklare:

#include <iostream> #include <string> #include <algorithm> int main() { std::string kaffekopp = "kaffekopp"; std::reverse(kaffekopp.begin(), kaffekopp.end()); std::cout << kaffekopp << std::endl; }

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Nov 2001

Klart att dessa varianter är enklare att skriva och ger lite renare kod, men man lär sig inte så mycket av det (annat än att slå upp vilka funktioner som finns i standardbiblioteket). Och nu var det ju faktiskt C som efterfrågades.

void@qnet
teeworlds, stålverk80, evil schemer, c, c++
Languages shape the way we think, or don't.

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Aug 2002
Citat:

Ursprungligen inskrivet av jdv
Klart att dessa varianter är enklare att skriva och ger lite renare kod, men man lär sig inte så mycket av det (annat än att slå upp vilka funktioner som finns i standardbiblioteket). Och nu var det ju faktiskt C som efterfrågades.

Precis

För övrigt hittade jag ett snyggare sätt att kasta om bokstäverna i en sträng.

void StringReverse(char *Str){ if(*Str){ StringReverse(str+1); putchar(str); } }

» Richard Simmons will make you his bitch...

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Apr 2004

Det där skriver dock bara ut textsträngen baklänges.

Trädvy Permalänk
Medlem
Registrerad
Dec 2004
Citat:

Ursprungligen inskrivet av Ben_Dover
Precis

För övrigt hittade jag ett snyggare sätt att kasta om bokstäverna i en sträng.

void StringReverse(char *Str){ if(*Str){ StringReverse(str+1); putchar(str); } }

Ummm... snyggt? Absolut inte med tanke på att rekursionen troligen slår igenom stacken för strängar som är, säg, en miljon tecken långa (eller något i den stilen).

"Nothing is impossible because impossible itself says I M Possible..."

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jan 2007
Citat:

Ursprungligen inskrivet av Weeblie
Ummm... snyggt? Absolut inte med tanke på att rekursionen troligen slår igenom stacken för strängar som är, säg, en miljon tecken långa (eller något i den stilen).

Sen skriver den som sagt bara ut strängen; vilket troligtvis kommer vara ett problem mycket oftare. Det är inte särskilt ofta man vill reversera strängar med flera miljoner tecken (även om det kan hända). En uppenbar lösning är ju någon form av loop:

function reverse(char* in, char* out){ int l = strlen(in); for(int i=0;i<l;i++){ out[i] = in[l-i-1]; } }

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Aug 2002

Hm, finns det något sätt att komma runt problemet med ett ojämt antal tecken i strängen?

Tex om n=5 så blir resultatet att två bokstäver aldrig byter plats.

» Richard Simmons will make you his bitch...

Trädvy Permalänk
Hedersmedlem
Plats
Linköping
Registrerad
Apr 2004
Citat:

Ursprungligen inskrivet av Ben_Dover
Hm, finns det något sätt att komma runt problemet med ett ojämt antal tecken i strängen?

Tex om n=5 så blir resultatet att två bokstäver aldrig byter plats.

Vilken funktion kör du? Resultatet borde bli att mittenbokstaven inte byter plats med någon, men det vill man ju inte heller.