Forum: C++ filhantering för nybörjare

Forum huvudsida -> Programmering -> C++ filhantering för nybörjare

Sidor: 1

Till botten

Xynz 18:21 - 30:e November 2006 | Post #1
Medlem
Inlägg: 4


Skicka PM
Hejsan, jag har hållt på med Dev-C++ i några dagar och bestämde mig för att göra ett krypteringsprogram som krypterar tex "hej" till "7382047" till en .txt fil.

Detta är vad jag gjort än så länge



#include<iostream>
#include<string>
#include<fstream.h>

using namespace std;

int main()
{
ofstream file;

int A=7;
int B=23;
int C=16;
int D=39;
int E=86;
int F=51;
int G=97;
int H=45;
int I=66;
int J=103;
int K=148;
int L=112;
int M=128;
int N=153;
int O=136;
int P=170;
int Q=169;
int R=196;
int S=181;
int T=254;
int U=235;
int V=217;
int W=222;
int X=247;
int Y=289;
int Z=265;
int AA=272;
int AE=290;
int OE=308;





string val;
string text;
string filnamn;
int par;
par = 100;

cout << "\n\n" << "skriv in om du vill kryptera eller dekryptera" << "\n\n\n";

cout << "val: ";
cin >> val;

if (val == "kryptera")

{
while (par >= 0)

{

cout << "skriv in medelandet du vill ha krypterat(en bokstav sen enter osv): ";
cin >> text;

if (text == "a")

{

file.open ("dokument.txt");
file << A << endl;
file.close();
}
else if (text == "b")
{
file.open ("dokument.txt");
file << B;
file.close();

}

else if (text == "c")

{

file.open ("dokument.txt");
file << C;
file.close();

}

else if (text == "d")

{

file.open ("dokument.txt");
file << D;
file.close();

}

else if (text == "e")

{

file.open ("dokument.txt");
file << E;
file.close();

}

else if (text == "f")

{

file.open ("dokument.txt");
file << F;
file.close();

}

else if (text == "g")

{

file.open ("dokument.txt");
file << G;
file.close();

}

else if (text == "h")

{

file.open ("dokument.txt");
file << H;
file.close();

}

else if (text == "i")

{

file.open ("dokument.txt");
file << I;
file.close();

}

else if (text == "j")

{

file.open ("dokument.txt");
file << J;
file.close();

}

else if (text == "k")

{

file.open ("dokument.txt");
file << K;
file.close();

}

else if (text == "l")

{

file.open ("dokument.txt");
file << L;
file.close();

}

else if (text == "m")

{

file.open ("dokument.txt");
file << M;
file.close();

}

else if (text == "n")

{

file.open ("dokument.txt");
file << N;
file.close();

}

else if (text == "o")

{

file.open ("dokument.txt");
file << O;
file.close();

}

else if (text == "p")

{

file.open ("dokument.txt");
file << P;
file.close();

}

else if (text == "q")

{

file.open ("dokument.txt");
file << Q;
file.close();

}
else if (text == "r")

{

file.open ("dokument.txt");
file << R;
file.close();

}
else if (text == "s")

{

file.open ("dokument.txt");
file << S;
file.close();

}
else if (text == "t")

{

file.open ("dokument.txt");
file << T;
file.close();

}
else if (text == "u")

{

file.open ("dokument.txt");
file << U;
file.close();

}
else if (text == "v")

{

file.open ("dokument.txt");
file << V;
file.close();

}
else if (text == "w")

{

file.open ("dokument.txt");
file << W;
file.close();

}
else if (text == "x")

{

file.open ("dokument.txt");
file << X;
file.close();

}
else if (text == "y")

{

file.open ("dokument.txt");
file << Y;
file.close();

}
else if (text == "z")

{

file.open ("dokument.txt");
file << Z;
file.close();

}
else if (text == "å")

{

file.open ("dokument.txt");
file << AA;
file.close();

}
else if (text == "ä")

{

file.open ("dokument.txt");
file << AE;
file.close();

}
else if (text == "ö")

{

file.open ("dokument.txt");
file << OE;
file.close();

}


cin.get();

}

system ("pause");

}

return 0;
}



Det jag nu behöver hjälp med är att för varje ny bokstav som skrivs in raderas de gamla siffrorna i dokumentet och det funkar ej att skriva flera bokstäver på samma rad, då krypteras bara den första.

Jag har även börjat fundera på dekrypteringen men där har jag ingen aning om hur jag ska fixa det. så de får bli ett senare problem.

-------------------------
Ingen signatur!



ozamosi 19:47 - 30:e November 2006 | Post #2
Administratör
Inlägg: 1129


Skicka PM
Gå till cppreference.com. Där finns länken C++ I/O, som vi givetvis klickar på. Vi klickar vidare på open, eftersom det är det vi använder för att öppna filen. Där får vi se att det finns ett vafritt argument, mode. Genom att klicka på länken i beskrivningen får vi se http://cppreference.com/io_flags.html#mode_flags - den översta av flaggorna är ios::app, vilket låter precis som vad vi vill ha.

Jag vet inte om det räcker med ios::app, eller om man måste skriva ios::app|ios::out - du får testa själv, eller vänta på att någon som vet svarar.

-------------------------
Ljusblå



Xynz 16:12 - 1:a December 2006 | Post #3
Medlem
Inlägg: 4


Skicka PM
Tackar, Nu funkar det iaf mer eller mindre. Kan fortfarande inte skriva flera bokstäver på samma rad, Vill gärna ha tips på hur man fixar det med. Typ något sätt att ta "text" stringen och jämföra den med alla "if" satserna en efter en?

Vill även fortfarande ha tips på dekryptering ifall någon har en idé


-------------------------
Ingen signatur!



Nissebosselasse 02:23 - 2:a December 2006 | Post #4
Medlem
Inlägg: 490


Skicka PM
Jag vet inte hur mycket C++ du har hållit på med, men här kommer lite tips (du får säga stopp om det låter som rappakalja).

Först lite allmänna tips som kan vara bra att följa redan från början:
  • using namespace std; - Den raden stjälper mer än den hjälper dig. Hur mycket har du läst om namnrymder (namespace)? Din kod blir lättare att följa om du deklarerar/definierar med fullständiga namn (t.ex. ofstream fil blir std::ofstream fil, string namn blir std::string namn). Detta gäller även cout och cin (eftersom de finns i namnrymden std); de skrivs därför som std::cout och std::cin (läs mer här: http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5)
  • När du inkluderar filer i C++, ska du utesluta .h - #include <fstream.h> blir således #include <fstream> (läs mer här: http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.4).
  • Kommentera din kod! Om två veckor, en månad, tre månader har du huvudet fullt av andra grejer, och kommer knappt ihåg hur du tänkte vid det här tillfället! Dessutom hjälper det andra att sätta sig in i din kod snabbare.

Jag antar att du vill ersätta varje bokstav i en mening med ett specifikt tal? Alla "A" blir 7, alla "B" blir 23, o.s.v.? Du skulle då kunna skapa en "karta", som kopplar ihop en bokstav med en siffra (eller ett annat tecken). På så vis slipper du deklarera och definiera en variabel för varje möjlig kombination (och som du säkert själv märkte när du skrev in det här, så blir det ganska jobbigt efter ett tag med så många variabler!). Så istället för att lägga in en massa int BOKSTAV = SIFFRA, så lägger du bara till bokstaven (och siffervärdet som ska motsvara bokstaven) i den här "kartan". Hur man kan göra detta kommer sen.

Vad bör då programet göra? Du vill:
  • Läsa in en mening (textsträng) från användaren
  • Ersätta varje bokstav i meningen med ett specifikt tal
  • Skriva resultatet ("krypteringen") till en textfil

Den första punkten har du i princip redan gjort.
  1. #include <string>
  2. #include <fstream>
  3. #include <iostream>
  4. int main () {
  5. // Texten vi vill kryptera
  6. std::string text;
  7. std::cout << "Skriv in meddelandet du vill kryptera: ";
  8. std::cin >> text;


Jag tänkte smälla in punkt tre redan här, faktiskt. Du öppnar och stänger filen för varje bokstav, men det är inte nödvändigt. När du skapar instanser av std::ofstream (eller std::ifstream), så kommer de stänga filerna automatiskt när de förstörs (t.ex. vid programmets avslut).
Så vi öppnar filen för skrivning:
  1. // Filen vi vill skriva till
  2. std::ofstream utfil ("dokument.txt");
  3. // Kolla om vi kunde öppna/skapa filen
  4. if (!utfil.is_open ()) {
  5. // Det kunde vi inte, avsluta?
  6. return 0;
  7. }

Du bör alltid kolla om det verkligen gick att öppna/skapa filen. Detta gör du med medlemsfunktionen is_open, som returnerar sant om det gick (logiskt nog... Smiley ).

Då ska vi göra den andra punkten (ersätta varje bokstav med ett specifikt tal). Det är egentligen här vår "karta" kommer in, men jag tänkte börja med en enklare variant först, och ta kartexemplet sist.
Vi ska alltså loopa igenom vår textsträng, bokstav för bokstav. Man kan göra det här på två sätt (säkerligen fler). Vi gör det på enklast möjliga med ett heltal:
  1. // Loopa igenom textsträngen
  2. for (int i = 0; i < text.length (); ++i) {
  3. // Ta ut bokstaven vid aktuell position i loopen
  4. char c = text[i];
  5. // Variabeln c innehåller nu bokstaven


För enkelhetens skull tänkte jag vi kunde använda ASCII-värdet (det siffervärde som motsvarar bokstaven) som "kod". ASCII-värdet för bokstaven A är 65, 66 för B, 67 för C o.s.v. Vi vill nu skriva dessa tal till vår fil, som vi öppnade tidigare.
  1. // Vi vill ha ut siffran, så vi "kastar om" värdet
  2. // till ett heltal (int)
  3. int o = static_cast<int> (c);
  4. // Skriv talet (ASCII-värdet, inte bokstaven som det motsvarar)
  5. // till filen, samt ett mellanslag
  6. utfil << o << " ";
  7. }

(Här finns mer info om "omkastning": http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=134&rl=1).
Anledningen till att vi dessutom skriver dit ett mellanslag, är för att vi ska kunna ta ut siffran om vi vill dekryptera texten. Till exempel: om vi hade krypterat texten "ABC" så skulle vi fått siffrorna 65, 66, 67 (ASCII-värdena för resp. bokstav). Om vi skriver siffrorna efter varandra till filen, så ser det ut så här:
  • 656667
När vi då ska läsa in texten för att dekryptera, hur vet vi att första talet är 65? Det kan lika gärna vara 6, 656, 6566, 65666, eller 656667. Om vi skriver ut ett mellanslag efter varje siffra, får vi istället:
  • 65 66 67
Då framgår det bättre att talen är 65, 66 och 67.

Här är hela källkoden än så länge:
  1. #include <string>
  2. #include <fstream>
  3. #include <iostream>
  4. int main ()
  5. {
  6. // Texten vi vill kryptera
  7. std::string text;
  8. std::cout << "Skriv in meddelandet du vill kryptera: ";
  9. std::cin >> text;
  10. // Filen vi vill skriva till
  11. std::ofstream utfil ("dokument.txt");
  12. // Kolla om vi kunde öppna/skapa filen
  13. if (!utfil.is_open ()) {
  14. std::cout << "Kunde inte öppna dokument.txt!" << std::endl;
  15. return 0;
  16. }
  17. // Loopa igenom textsträngen
  18. for (int i = 0; i < text.length (); ++i) {
  19. // Ta ut bokstaven vid aktuell position i loopen
  20. char c = text[i];
  21. // Variabeln c innehåller nu bokstaven
  22. // Vi vill ha ut siffran, så vi "kastar om" värdet
  23. // till ett heltal (int)
  24. int o = static_cast<int> (c);
  25. // Skriv talet (ASCII-värdet, inte bokstaven som det motsvarar)
  26. // till filen, samt ett mellanslag
  27. utfil << o << " ";
  28. }
  29. return 0;
  30. }

Observera dock att std::cin >> text bara läser till första mellanslaget (eller radslut).

Skriv in lite olika bokstäver, och titta sedan i filen "dokument.txt", så ser du hur det är uppbyggt.

Nu vore det bra om vi kunde testa och se om vi kunde dekryptera vårt meddelande också! Här gäller det bara att tänka tvärtom:
  • -ppna vår fil
  • Läsa in ett tal, och omvandla det till rätt bokstav
  • Skriva resultatet ("krypteringen") till skärmen

,,n en gång för enkelhetens skull, börjar jag om med en ny fil. I ett riktigt projekt hade vi lagt krypterings- och dekrypteringsrutinen i varsin funktion istället.
Vi börjar med att öppna filen:
  1. #include <iostream>
  2. #include <fstream>
  3. int main () {
  4. // Filen vi ska läsa från
  5. std::ifstream infil ("dokument.txt");
  6. // Kolla så att det gick att öppna den
  7. if (!infil.is_open ()) {
  8. std::cout << "Kunde inte öppna dokument.txt!" << std::endl;
  9. return 0;
  10. }


Vi ska läsa från filen tills den tar slut, alltså skapar vi en loop som avbryts när just detta inträffar. Vi läser heltal från filen (vilket var just det vi skrev till den i första början - vilken planering!).
Dessutom klämmer vi in sista punkten här också, nämligen att omvandla siffran till en bokstav, samt skriva ut det på skärmen:
  1. // Läs tills filen tar slut
  2. int tal = 0;
  3. while (infil >> tal) {
  4. // Variabeln tal håller nu ASCII-värdet, gör om det till en bokstav
  5. char c = static_cast<char> (tal);
  6. // Skriv det till skärmen
  7. std::cout << c;
  8. }
  9. return 0;
  10. }


Sådärja. Jag vet jag skrev att jag tänkte ta med ett kartexempel också, men det får vänta (känns som om det här meddelandet är tillräckligt långt).
Idé:
  • Som det är nu så skrivs ju bara ASCII-värdet till filen, men eftersom variabeln o (se första kodexemplet) är en siffra, så kan du ju utsätta den för allehanda matematiska formler för på att så vis göra "krypteringen" än mer svårare att knäcka. Kom bara ihåg att i dekrypteringsfunktionen göra det motsatta (t.ex., om du minskar o med två vid krypteringen, så måste du komma ihåg att öka siffran du läser in från filen med två, för att få fram rätt värde)
  • Avsluta alltid din main-funktion med ett att returnera ett värde, t.ex. return 0; (allmänt råd)

Testa dig fram, och fråga om något är oklart.

----

EDIT: Indy? Kan du ändra så att [ source=cpp] inte visar kodorden med turkos färg? Antingen har jag starr, eller så är det omöjligt att se de orden med den färgkombinationen...

-------------------------
http://pushingcows.se
Gula Nallen

Senast redigerad 02:25 - 2:a December 2006


Xynz 18:44 - 14:e December 2006 | Post #5
Medlem
Inlägg: 4


Skicka PM
Hejsan, Har varit iväg i några dagar. Det är därför jag inte svarat. Din kod funkade fint och jag har redan fixat en helt ok program nu det där med omkastning fattade jag inte riktigt innan men länken var bra och tror jag fattat det nu =)

Tack så mycket för hjälpen

-------------------------
Ingen signatur!



Xynz 19:19 - 16:e December 2006 | Post #6
Medlem
Inlägg: 4


Skicka PM
EDIT: fixade det själv

-------------------------
Ingen signatur!

Senast redigerad 19:24 - 16:e December 2006


Sidor: 1

Forum huvudsida -> Programmering -> C++ filhantering för nybörjare
Atom feed

Du får inte posta i den här tråden | Till toppen