Hjälp med Krypteringsuppgift!

Permalänk
Medlem

Hjälp med Krypteringsuppgift!

Som rubriken antyder behöver jag hjälp med ett projektarbete (i Programmering A) som ska skrivas i programmet Eclipse (använder Java). Uppgiften är att skapa ett krypteringsprogram genom att använda krypteringsmetoden Caesarrullning.

För er som inte vet Caesarrullning är:
Genom att förskjuta bokstäverna i alfabetet X antal steg få fram en ny bokstav.
För att sedan lösa krypteringen krävs alltså information om hur många "steg" som bokstaven förskjutits.
Exempel:
Jag väljer att förskjuta texten 4 steg
Jag vill kryptera: "Hej Kul"
Den krypterade texten blir då: "Lip Oxp"

Uppgiften:
Programmet ska visas i en meddelanderuta och fungera i tre steg
1: Input: Antal steg man vill förskjuta bokstäverna (hela svenska alfabetet)
2: Input: Texten man vill kryptera
3: Message: Den krypterade texten.

Skulle vara underbart med hjälp, har ärligt talat ingen aning om hur jag ska lösa detta. Först å främst vill jag ha idéer, men klara programförslag skulle vara guld värt och om man till och med kan stoppa in så att den skiljer på stora och små bokstäver skulle vara underbart.

Tack på förhand!

Permalänk
Medlem

Konvertera alla bokstäver till tal > lägg till antalet steg > konvertera tillbaka till bokstäver.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av thompa89
Konvertera alla bokstäver till tal > lägg till antalet steg > konvertera tillbaka till bokstäver.

Funderat på liknande lösning också, men blir en hel drös med tilldelningar (typ int a = 1 osv)
Och då måste jag få en hel massa substrings (vilket är lite över min nivå)
Steg ett är ju fantastisk enkelt (String, konvertera till värdetal)
Steg två: Konvertera samtliga bokstäver till siffror, addera värdesiffran från steg ett och konvertera tillbaka till krypterad text..

Finns det inget "simplare" sätt att göra det hela?

Permalänk
Medlem

Blir inte så många tilldelningar. Om du läser in en sträng så kan du plocka ut tecken ett och ett med strängfunktionen charAt(index). När du väl har en char så kan du behandla den som ett tal som motsvarar tecknets värde i ASCII tabellen ('A' = 65, 'B' = 66 ... 'Z' = 90, 'a' = 97, 'b' = 98 o.s.v.), så det är bara att lägga ihop med din förskjutning. Det enda fallet du behöver ha koll på är om resultatet överstiger Z (stort och litet), speciellt om du vill kunna använda Svenska tecken också eftersom Å, Ä och Ö inte ligger tillsammans med de övriga bokstäverna i tabellen. Sen kan du ta resultatet, casta det till en karaktär, och lägga in den i en ny krypterad sträng.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Thomas H
Blir inte så många tilldelningar. Om du läser in en sträng så kan du plocka ut tecken ett och ett med strängfunktionen charAt(index). När du väl har en char så kan du behandla den som ett tal som motsvarar tecknets värde i ASCII tabellen ('A' = 65, 'B' = 66 ... 'Z' = 90, 'a' = 97, 'b' = 98 o.s.v.), så det är bara att lägga ihop med din förskjutning. Det enda fallet du behöver ha koll på är om resultatet överstiger Z (stort och litet), speciellt om du vill kunna använda Svenska tecken också eftersom Å, Ä och Ö inte ligger tillsammans med de övriga bokstäverna i tabellen. Sen kan du ta resultatet, casta det till en karaktär, och lägga in den i en ny krypterad sträng.

Jo det är ju sant. Så alltså blir det 28 (är det så många bokstäver? :s) tal att hålla koll på..

Men ASCII - Vad är det?

Riktigt bra svar för övrigt! (Gav mig en hel del klarhet)

Permalänk
Medlem

Nedan följer två små metoder i C#. Borde gå att enkelt göra en java-version av nedanstående kodblock. Skrev och testade på 5min så detta kanske inte fungerar tillräckligt.

public string Kryptera(string Klartext, int steg) { StringBuilder krypteradText = new StringBuilder(); foreach (char c in Klartext) { //gör om char till ett tal och addera x steg int charAsInt = Convert.ToInt32(c) + steg; //gör om talet till en character char newChar = Convert.ToChar(charAsInt); krypteradText.Append(newChar); } return krypteradText.ToString(); } public string Dekryptera(string krypteradText, int steg) { StringBuilder dekrypteradText = new StringBuilder(); foreach (char c in krypteradText) { //gör om character till ett tal och hoppa x antal steg int charAsInt = Convert.ToInt32(c) - steg; //gör en ny char efter vi tagit x antal steg tillbaka char decrypterChar = Convert.ToChar(i); dekrypteradText.Append(decrypterChar); } return dekrypteradText.ToString(); }

Visa signatur

Sony Vaio FE21M

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av FrMod

Men ASCII - Vad är det?

Nästa gång du träffar på din lärare så ge honom en rejäl pungspark. Eller så tilldelar du dig själv den pungsparken om det är så att du skolkat så mycket att du inte lärt dig vad ASCII är.
Det finns liksom några grejjer man ska kunna innan man börjar programmerare och teckenstandarden ASCII är en.

Permalänk
Medlem

ASCII tabellen är helt enkelt en tabell som datorn har internt som översätter tal till olika tecken (och tillbaka). En fördel med typen char som finns i bl.a. Java och C/C++ är att den egentligen är ett tal. Om du skriver ut den så översätts den egentligen bara automatiskt till ett tecken med hjälp av ASCII tabellen. Det innebär i sin tur att du kan behandla char variabler precis som en int. t.ex. om du skriver så här:

char tecken = 'f'; //(Notera ' istället för " när du hanterar char) System.out.println((char)(tecken-1) + ", " + tecken + ", " + (char)(tecken+1));

så kommer programmet skriva ut "e, f, g". Detta eftersom tecken kommer översättas till ett tal som motsvarar 'f', vilket är 102, och tecken-1 blir då 101. I utskriften så gör jag en typecast för att tala om att jag vill tolka talet som en char, annars skulle utskriften bli "101, f, 103". Du kan även behandla tal som char, så det går också att skriva så här:

int tal = 102; System.out.println((char)tal);

som då skulle skriva ut "f". Det enda du behöver ha koll på egentligen är att göra om talet till en char ibland genom att casta det. Du behöver egentligen inte ens veta vilket tal som motsvarar vilket tecken, eftersom du kan använda t.ex. 'a' i koden för att få det motsvarande talet.

Lite övning på att använda char typen och ASCII, samt att hålla koll på specialfallen (den krypterade bokstaven går utanför det Engelska alfabetet), är nog allt du behöver för den här uppgiften.

Permalänk
Medlem

Okej, tack så mycket. Ska följa ditt råd och träna lite på det här, alternativt börja experimentera direkt..

Iallafall, väldigt bra info, tack!

Permalänk
Medlem

public String kryptera(String s, int steg)
{
String returstring=new String();
for (int i=0; i<=s.length()-1;i++)
returstring+=(char)((int)(s.charAt(i)+steg));
return returstring;
}

Den hoppar visserligen inte tillbaka till a från ö, men va fan, lite utmaning måste du la få.

Visa signatur

Varför får inte rika bli rikare? Varför är det så farligt att va rasist? Vad är vitsen med att ha minst en särskrivning per mening? Hur kan man med att ge sig själv ett oseriöst intryck genom att skriva dåligt? 100% av alla mac-ägare kan inte ha fel.

Permalänk
Medlem

hmm, största problemet nu är ju att lösa hur man ska komma från "vanliga" alfabetet (A-Z) till våra svenska Å, Ä och Ö... förslag någon?

Permalänk
Medlem

sök på ASCII-tabell är mitt tips.

Permalänk
Medlem

Jag hade undvikit ASCII-approachen från början, den ställer till med problem så fort man rör sig utanför det amerikanska alfabetet. Du skulle ju kunna sätta upp en array med alfabetet som du sedan använder för att "översätta" de tecken som finns med. Eller nåt.

Permalänk
Medlem

Såhär skulle jag ha gjort..

  • Skapa en statisk abcSträng = "abcdefghijklmnopqrstuvwxyzåäö"

  • Skapa även en StringArray, output. Det är denna som din text sparas i

  • Loopa igenom texten som ska krypteras, spara aktuell bokstav i en char [ch]

  • Kör en indexOf(lowercase [ch]) på din abcSträng. Spara detta värde i en int [i]

  • Om [i] != -1 så...

  • * Lägg till rullningen till int-värdet

  • * Om int-värdet är större än längden av din abcSträng, dra ifrån len abcSträng (enklast och bäst gjort med modulus-operatorn)

  • * Ta ut bokstav [i] ur abcSträng. Gör om till uppercase om [ch] var uppercase

  • * Appenda denna bokstav till output

  • Om [i] var -1 så lägg till [ch] till output

Det ser kanske krångligt ut men där har du hela uppgiften klar..

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Teknocide
Såhär skulle jag ha gjort..

  • Skapa en statisk abcSträng = "abcdefghijklmnopqrstuvwxyzåäö"

  • Skapa även en StringArray, output. Det är denna som din text sparas i

  • Loopa igenom texten som ska krypteras, spara aktuell bokstav i en char [ch]

  • Kör en indexOf(lowercase [ch]) på din abcSträng. Spara detta värde i en int [i]

  • Om [i] != -1 så...

  • * Lägg till rullningen till int-värdet

  • * Om int-värdet är större än längden av din abcSträng, dra ifrån len abcSträng (enklast och bäst gjort med modulus-operatorn)

  • * Ta ut bokstav [i] ur abcSträng. Gör om till uppercase om [ch] var uppercase

  • * Appenda denna bokstav till output

  • Om [i] var -1 så lägg till [ch] till output

Det ser kanske krångligt ut men där har du hela uppgiften klar..

Grejen är den att vi jobbar inte statiska strängar och sånt...
kanske lite överkill, men kan någon skriva ut ett liknande program som jag kan modifiera lite istället, förstår själva principen men har verkligen inte kunskapen för att klara det helt själv..

Tack för samtliga svar för övrigt

Permalänk
Medlem

Med statisk sträng menade jag en sträng som inte kommer att förändras. Det var fel uttryckt av mig, konstant hade kanske passat bättre. I praktiken räcker det med en helt vanlig sträng!

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Teknocide
Med statisk sträng menade jag en sträng som inte kommer att förändras. Det var fel uttryckt av mig, konstant hade kanske passat bättre. I praktiken räcker det med en helt vanlig sträng!

Så i mitt program skulle det vara
String s1 = 'ABCDEFGHIJKLMONPQRSTUVXYZÅÄÖ'
Och sedan input,
Få fram positionen i string s1 och sedan plussa på antal steg

eller?

Permalänk
Medlem

Små bokstäver om du följer mitt exempel; 'A' är inte lika med 'a'. Sen får du se till att ha dem i rätt ordning också

edit: och glöm inte 'w'

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Teknocide
Små bokstäver om du följer mitt exempel; 'A' är inte lika med 'a'. Sen får du se till att ha dem i rätt ordning också

edit: och glöm inte 'w'

angående små/stora kan man ju få programmet att ignorera det, så den delen är inget problem..

men annars var det rätt tänkt?

Permalänk
Medlem

Tanken är att du jämför bokstav för bokstav i insträngen med alfabetet.

Vi tar 'Glass!' som exempel. Ponera följande:

Vi rullar med 3
Sträng abc = 'abcd...åäö'
[list="1"][*]Första bokstav = 'G'
[*]Hämta positionen av 'g' (mao. lowercase 'G') ur sträng abc (= 6)
[*]Lägg till "rullvärdet" 3 = 9
[*]Hämta position 9 ur sträng abc (= 'j')
[*]Eftersom bokstav var uppercase gör vi om vår rullade bokstav till uppercase
[*]Lägg till 'J' till utsträngen[/list=1]

Detta repeteras tills tecknet '!' påträffs. Eftersom detta tecken inte finns med i sträng abc går det inte att rulla och läggs sålunda till i utsträngen direkt.

Vi har nu strängen 'Jodvv!'

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem

Försökte mig också på en lösning i C#... mycket enkel att använda i Java.

// Ger "onippi tb jncppi"
krypteraText("kjelle på fjälle'", 4, false);
// Ger "kjelle på fjälle"
krypteraText("onippi tb jncppi", 4, true);

string alfabetet = "abcdefghijklmnopqrstuvwxyzåäö"; string krypteraText(string krypteraDetta, int steg, bool avkryptera) { string resultat = string.Empty; foreach (char c in krypteraDetta) { if (alfabetet.IndexOf(c) < 0) // Okänt tecken resultat += c.ToString(); else if (avkryptera) resultat += avkrypteraBokstav(c, steg).ToString(); else resultat += krypteraBokstav(c, steg).ToString(); } return resultat; } char krypteraBokstav(char bokstav, int steg) { return alfabetet[(alfabetet.IndexOf(bokstav) + steg) % alfabetet.Length]; } char avkrypteraBokstav(char bokstav, int steg) { int index = alfabetet.IndexOf(bokstav) - steg + alfabetet.Length; return alfabetet[index % alfabetet.Length]; }

Permalänk
Medlem

Den verkar plocka bort alla stora bokstäver och tecken den inte känner igen, t ex skiljetecken..

edit och superofftopic: vill också börja koda C# nu. Finns det några CLI-verktyg med i VS Express? Det känns enklare att börja i den änden..

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Teknocide
Den verkar plocka bort alla stora bokstäver och tecken den inte känner igen, t ex skiljetecken..

edit och superofftopic: vill också börja koda C# nu. Finns det några CLI-verktyg med i VS Express? Det känns enklare att börja i den änden..

Hm, jag redigerade den lite. Nu ger den tillbaka alla tecken den inte känner igen istället. Det är nog bättre!

Absolut, det enklaste är att skapa upp ett nytt projekt, välj C# och "Console Application" för ett gammalt hederligt CLI-projekt. I objektet Console finns IO som ReadLine och WriteLine etc. Jag rekommenderar att du drar in 2010an om du ska installera C# Express: http://go.microsoft.com/fwlink/?LinkID=167872

Permalänk

Jag drog ihop en enkel i C.

#include <stdio.h> #include <string.h> #define DATA_DECRYPT 0x01 #define DATA_ENCRYPT 0x02 void data_crypto(char *data, int padding, short event) { for (char *i = data; *i != 0; i++) (event == DATA_ENCRYPT ? (*i += padding) : (*i -= padding)); } int main(int argc, char **argv) { if (argc == 1) { printf("BLEH!\n"); return 0; } char *data = argv[1]; printf("%s\n", data); data_crypto(data, 4, DATA_ENCRYPT); printf("%s\n", data); data_crypto(data, 4, DATA_DECRYPT); printf("%s\n", data); return 0; }

Permalänk
Medlem

Du kommer ju inte lära dig mycket om du inte gör uppgiften själv

Permalänk

Eftersom du har fått svar i flera olika språk svarar jag i ett språk du garanterat INTE har nytta av i Programmering A. Språket i fråga heter Haskell, läs och njut!
Jag har tyvärr ingen erfarenhet alls av Java, men tankesättet bör gå att applicera på Java.
Observera att den här "krypterar" alla tecken.

-- Den här biten krypterar respektive dekrypterar varje enskild char c med intervallet k. (+.), (-.) :: Char -> Int -> Char c +. k = chr ((ord x + k) `mod` 256) c -. k = chr ((ord x - k + 256) `mod` 256) -- Den här går över alla tecken i en sträng (egentligen ser Haskell en sträng som en lista av -- chars, men men) och applicerar funktionen +. respektive -. på varje enskilt tecken. encryptString, decryptString :: Int -> String -> String encryptString k s = map (+. k) s decryptString k s = map (-. k) s

Visa signatur

Workstation: Dell Latitude E5400, WinXP/Ubuntu 9.10. 4 GB RAM, 250GB, P8700 @ 2.53GHz
HTPC: MythBuntu, 2GB RAM, 1TB, Atom dual core @ 1.6 GHz, Sanyo PLV-Z700
Server #1: Ubuntu, 2 GB RAM, 4*143 GB 10K RAID0 +2*73GB 15K RAID1. Intel Xeon dual core @3.2 GHz

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av zyber_zero

-- Den här biten krypterar respektive dekrypterar varje enskild char c med intervallet k. (+.), (-.) :: Char -> Int -> Char c +. k = chr ((ord x + k) `mod` 256) c -. k = chr ((ord x - k + 256) `mod` 256)

Vänligen korta ner raden med den långa kommentaren till två rader, forumets layout är inte så bra på att hantera långa rader i code-block...

Du kör med samma logik som jag gjorde ovan. Men gör du mod 256 för att char-uppsättningen har 256 poster? Krypteras i så fall skiljetecken såsom t.ex. kommatecken och mellanslag? Och hur hanteras åäö där, blir ett ö till ett stort A eller? (om intervallet är 1)

Permalänk

Ursäkta - Jag kör med ett greasemonkeyscript som breddar forumet för mig...

mod 256 används för att det inte ska bli överslag, så precis som du säger för att charuppsättningen har 256 uppslag. Då vet man att även om man försöker lägga till 128 och man står på tecken med inten 200 så kommer inte programmet att flippa för att man försöker använda sig av ett tal som "inte finns".
Allt blir krypterat. Ett ö blir tecknet som motsvaras av 247 - alltså inte A.

Visa signatur

Workstation: Dell Latitude E5400, WinXP/Ubuntu 9.10. 4 GB RAM, 250GB, P8700 @ 2.53GHz
HTPC: MythBuntu, 2GB RAM, 1TB, Atom dual core @ 1.6 GHz, Sanyo PLV-Z700
Server #1: Ubuntu, 2 GB RAM, 4*143 GB 10K RAID0 +2*73GB 15K RAID1. Intel Xeon dual core @3.2 GHz

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av zyber_zero
Allt blir krypterat. Ett ö blir tecknet som motsvaras av 247 - alltså inte A.

Yes, jag såg det, och det är ju inte önskvärt beteende kanske? Ett ö ska ju bli ett a om intervallet är 1. Skiljetecken ska inte krypteras heller, ett kommatecken kanske blir till ett semikolon men enligt Caesarrullning så krypterar man bara bokstäver i alfabetet. Så du får kanske tänka om lite! Man kan inte använda teckentabellen rakt av tyvärr.

Däremot kan du använda teckentabellens positioner a-ö och köra mod 29 istället, som jag gjorde. Fast jag tog inte mina tecken från teckentabellen utan gjorden en string (är en array av chars även i C#) som innehöll dem.

Permalänk

Slängde ihop en lösning med Linq:

string msg = "Hej Kul! ÅÄÖ"; string msg2 = "Lin Oyp! bcd"; string alfa = "ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖabcdefghijklmnopqrstuvwxyzåäö"; var hepp = msg.ToCharArray().Select(c2 => alfa.Contains(c2) ? alfa[(alfa.IndexOf(c2) + 4) % alfa.Length] : c2); var hepp2 = msg2.ToCharArray().Select(c2 => alfa.Contains(c2) ? alfa[(alfa.IndexOf(c2) - 4 + alfa.Length) % alfa.Length]: c2); foreach (char o in hepp) { System.Diagnostics.Debug.Write(o.ToString()); } //Ger "Lin Oyp! bcd" foreach (char o in hepp2) { System.Diagnostics.Debug.Write(o.ToString()); } //Ger "Hej Kul! ÅÄÖ"

Visa signatur

www.uu.se - some kind of university | www.hirr.org.uk - ain't no mountain high enough | www.bajenfans.se