Permalänk

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; }

Visa signatur

» Well, tough titties...

Permalänk
Medlem

printf borde väl fungera.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Hedersmedlem

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

Permalänk

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

Visa signatur

» Well, tough titties...

Permalänk
Medlem

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.

Visa signatur

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

Permalänk
Medlem

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

Visa signatur

I am Thon, eat my spread!

Permalänk

Tack!

Nu funkar det.

Visa signatur

» Well, tough titties...

Permalänk
Hedersmedlem
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?

Permalänk
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?

Visa signatur

» Well, tough titties...

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av Ben_Dover
Hur löser man det?

int len = strnLen(str) -1;

borde väl räcka?

Permalänk
Citat:

Ursprungligen inskrivet av Elgot

int len = strnLen(str) -1;

borde väl räcka?

Visa signatur

» Well, tough titties...

Permalänk
Vila i frid

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)); }

Permalänk
Hedersmedlem

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

csKaffekopp.MakeReverse();

Permalänk
Medlem

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; }

Permalänk
Medlem

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.

Visa signatur

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

Permalänk
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); } }

Visa signatur

» Well, tough titties...

Permalänk
Hedersmedlem

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

Permalänk
Medlem
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).

Visa signatur

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

Permalänk
Medlem
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]; } }

Permalänk

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.

Visa signatur

» Well, tough titties...

Permalänk
Hedersmedlem
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.