Problem att läsa siffror från txt-fil (c++)

Permalänk

Problem att läsa siffror från txt-fil (c++)

Hej.
Jag har lite problem med ett projekt i C++.
Problemet är sådant att jag skulle vilja läsa ett antal siffror från en .txt-fil, vilka sedan skall jämföras med ett lösenord som användaren skriver in. Stämmer lösenordet så får användaren tillgång till programmet, stämmer det inte så får denne inte tillgång.

Observera att det här inte är ett skolprojekt, utan jag programmerar bara för att jag tycker det är kul.
Här är så långt som jag har kommit:

int funktion_pass() { double a; double b; char *filename = "banksettingsconfig.txt"; ifstream file_in(filename); ofstream file; if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { if (a == 000000) { return 0; } else { cout << "Enter your password: "; cin >> b; if (a == b) { cout << "Password accepted\n"; cin.get(); return 0; } else { cout << "Wrong password\n"; cout << "Terminating...\n"; int funktion_exit(); return 0; } } } return 0; } int funktion_exit() { return 0; }

Det här är en funktion som jag döpt till "Funktion_pass" och är alltså bara en liten del av hela programmet.

Problemet jag har är att även om man skriver in fel lösenord så är det bara att trycka på enter för att ändå få tillgång till programmet.
För att råda bukt på det hela så skapade jag en ny funktion, "Funktion_exit". Det enda den gör är att avsluta programmet. Trots detta så får jag det inte att fungera.

Jag har en liten aning om att det kanske kan vara raden "While (file_in >> a)" som ställer till det för mig, men jag har ingen aning om vad jag kan göra för att få bort den.
Själva kod-biten som läser från filen har jag bara kopierat från en sida (www.cplusplus.com) så egentligen har jag ingen aning om vad den gör.
Som ni kanske också ser så är jag inte en avancerad programmerare. Därför skulle det hjälpa oerhört om svaren ni ger inte heller innehåller så avancerad kod. Håll det enkelt!

Här kommer hela programmet om ni vill ha lite mer inblick i problemet:

#include <iostream> #include <math.h> #include <fstream> #include <ctime> #include <string> using namespace std; using std::cout; using std::cin; int funktion_main(); int funktion_in(); int funktion_out(); int funktion_status(); int funktion_first(); int funktion_pass(); int funktion_exit(); int funktion_main() { char choice; do { cout << "What do you want to do?\n"; cout << "1. Insert money.\n"; cout << "2. Withdraw money.\n"; cout << "3. Check status.\n"; cout << "4. Exit.\n"; cin >> choice; switch (choice) { case '1': funktion_in(); break; case '2': funktion_out(); break; case '3': funktion_status(); break; case '4': return 0; default: cout << "Wrong number.\n"; return 0; } } while (choice != '4'); return 0; } int funktion_in() { double a; double b; double c; char *filename = "banksettings.txt"; ifstream file_in(filename); ofstream file_out; if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { cout << "You currently have " << a << " kronor on your account.\n"; cout << "How much would you like to insert?\n"; cin >> b; c = a + b; cout << "You now have " << c << " Kronor on your account.\n"; file_out.open ("banksettings.txt"); file_out << c; file_out.close(); cin.get(); cin.get(); return 0; } } int funktion_out() { double a; double b; double c; char *filename = "banksettings.txt"; ifstream file_in(filename); ofstream file_out; if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { cout << "You currently have " << a << " kronor on your account.\n"; cout << "How much would you like to withdraw?\n"; cin >> b; if (a - b < 0) { cout << "You don't have that amount of money on your account.\n"; cout << "You do, however, have " << a << " kronor on your account.\n"; cin.get(); cin.get(); return 0; } else { c = a - b; cout << "You now have " << c << " Kronor on your account.\n"; file_out.open("banksettings.txt"); file_out << c; file_out.close(); cin.get(); cin.get(); return 0; } } } int funktion_status() { double a; char *filename = "banksettings.txt"; ifstream file_in(filename); if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { cout << "You currently have " << a << " kronor on your account\n"; } cin.get(); cin.get(); return 0; } int funktion_first() { int array_one[6]; ofstream file; ofstream file_2; cout << "Preparing for first time use...\n"; file.open ("banksettings.txt"); file << "0\n"; file.close(); cout << "Do you want to choose a password to secure your account?\n"; cout << "If yes, type it below. If no, type zero six times (000000).\n"; cout << "Your password must consist of six numbers.\n"; cout << "\n"; cout << "Password: \n"; cin >> array_one[0], array_one[1], array_one[2], array_one[3], array_one[4], array_one[5]; cout << "Your password is: " << array_one[0], array_one[1], array_one[2], array_one[3], array_one[4], array_one[5]; cout << "\n"; cout << "Saving password...\n"; file_2.open ("banksettingsconfig.txt"); file_2 << array_one[0], array_one[1], array_one[2], array_one[3], array_one[4], array_one[5]; file_2.close(); cout << "Done.\n"; cin.get(); cin.get(); funktion_main(); return 0; } int funktion_pass() { double a; double b; char *filename = "banksettingsconfig.txt"; ifstream file_in(filename); ofstream file; if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { if (a == 000000) { return 0; } else { cout << "Enter your password: "; cin >> b; if (a == b) { cout << "Password accepted\n"; cin.get(); return 0; } else { cout << "Wrong password\n"; cout << "Terminating...\n"; int funktion_exit(); return 0; } } } return 0; } int funktion_exit() { return 0; } int main() { int a; cout << "IS THIS THE FIRST TIME YOU ARE USING THIS FILE?\n"; cout << "PRESS '1' IF YES AND '2' IF NO.\n"; cin >> a; if (a == 1) { funktion_first(); funktion_main(); cout << "terminating...\n"; } else { funktion_main(); cout << "terminating...\n"; } return 0; }

Tack på förhand.

/Calle

Permalänk
Hedersmedlem

Det största problemet är att du inte bryr dig om huruvida lösenordet är rätt eller inte. Förslagsvis byter du ut

return 0;

när lösenordet är fel mot

return 1;

och gör sedan olika saker där funktionen anropas (anropar du den någonstans, för övrigt) beroende på vad som returneras.

Permalänk

Så om jag gör så här:

int funktion_pass() { double a; double b; int c; char *filename = "banksettingsconfig.txt"; ifstream file_in(filename); ofstream file; if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { if (a == 000000) { c == 1 return c; } else { cout << "Enter your password: "; cin >> b; if (a == b) { cout << "Password accepted\n"; cin.get(); c == 1 return c; } else { cout << "Wrong password\n"; cout << "Terminating...\n"; c == 2 return c; } } } return 0; }

Och sedan i en annan del av koden kollar vilket värde "Funktion_pass" returnerade, kan jag då göra en if-sats som antingen släpper in en i programmet eller säger att lösenordet är fel?

Tex:

if (c == 1) { funktion_main; } else if (c == 2) { cout << "Wrong password. Try again.\n"; funktion_pass; }

/Calle

Permalänk
Hedersmedlem

Man skulle till exempel kunna ha något i stil med:

int main() { /* yadda yadda yadda */ if(funktion_pass() == 1) { cout << "ok" << endl; //gör något bra här } else { cout << "Wrong password" << endl; return 1; //avslutar programmet } /* yadda yadda yadda */ return 0; }

Permalänk

Elgot, du hade rätt; jag anropade inte funktionen någon stans.
Nu är i alla fall det löst och jag har även fixat lite andra saker (det du visar ovan).
När jag körde programmet igen efter förändringarna så tyckte jag först det fungerade, men icke sa Nicke. Efter man har skrivit in lösenordet så står det "Password accepted", precis som det ska. Trycker man sedan enter så anropas tydligen "funktion_pass" igen. Helkonstigt eftersom jag bara anropar den en gång. Man skriver då in sitt lösenord igen och efter det kommer man in i programmet. Alltså när man har fått skriva in sitt lösen två gånger.
Går det att råda bukt på det här konstiga fenomenet?
De funktioner som är relevanta är:
funktion_pass();
funktion_main();
funktion_first();
main();
här kommer hela koden igen:

#include <iostream> #include <math.h> #include <fstream> #include <ctime> #include <string> using namespace std; using std::cout; using std::cin; int funktion_main(); int funktion_in(); int funktion_out(); int funktion_status(); int funktion_first(); int funktion_pass(); int funktion_main() { char choice; do { cout << "What do you want to do?\n"; cout << "1. Insert money.\n"; cout << "2. Withdraw money.\n"; cout << "3. Check status.\n"; cout << "4. Exit.\n"; cin >> choice; switch (choice) { case '1': funktion_in(); break; case '2': funktion_out(); break; case '3': funktion_status(); break; case '4': return 0; default: cout << "Wrong number.\n"; return 0; } } while (choice != '4'); return 0; } int funktion_in() { double a; double b; double c; char *filename = "banksettings.txt"; ifstream file_in(filename); ofstream file_out; if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { cout << "You currently have " << a << " kronor on your account.\n"; cout << "How much would you like to insert?\n"; cin >> b; c = a + b; cout << "You now have " << c << " Kronor on your account.\n"; file_out.open ("banksettings.txt"); file_out << c; file_out.close(); cin.get(); cin.get(); return 0; } } int funktion_out() { double a; double b; double c; char *filename = "banksettings.txt"; ifstream file_in(filename); ofstream file_out; if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { cout << "You currently have " << a << " kronor on your account.\n"; cout << "How much would you like to withdraw?\n"; cin >> b; if (a - b < 0) { cout << "You don't have that amount of money on your account.\n"; cout << "You do, however, have " << a << " kronor on your account.\n"; cin.get(); cin.get(); return 0; } else { c = a - b; cout << "You now have " << c << " Kronor on your account.\n"; file_out.open("banksettings.txt"); file_out << c; file_out.close(); cin.get(); cin.get(); return 0; } } } int funktion_status() { double a; char *filename = "banksettings.txt"; ifstream file_in(filename); if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { cout << "You currently have " << a << " kronor on your account\n"; } cin.get(); cin.get(); return 0; } int funktion_first() { int array_one[6]; ofstream file; ofstream file_2; cout << "Preparing for first time use...\n"; file.open ("banksettings.txt"); file << "0\n"; file.close(); cout << "Do you want to choose a password to secure your account?\n"; cout << "If yes, type it below. If no, type zero six times (000000).\n"; cout << "Your password must consist of six numbers.\n"; cout << "\n"; cout << "Password: \n"; cin >> array_one[0], array_one[1], array_one[2], array_one[3], array_one[4], array_one[5]; cout << "Your password is: " << array_one[0], array_one[1], array_one[2], array_one[3], array_one[4], array_one[5]; cout << "\n"; cout << "Saving password...\n"; file_2.open ("banksettingsconfig.txt"); file_2 << array_one[0], array_one[1], array_one[2], array_one[3], array_one[4], array_one[5]; file_2.close(); cout << "Done.\n"; cin.get(); cin.get(); return 0; } int funktion_pass() { double a; double b; char *filename = "banksettingsconfig.txt"; ifstream file_in(filename); ofstream file; if (!file_in) { cout << "There was a problem opening file " << filename << " for reading." << endl; return 0; } cout << "Opened " << filename << " for reading." << endl; while (file_in >> a) { if (a == 000000) { return 1; } else { cout << "Enter your password: "; cin >> b; if (a == b) { cout << "Password accepted\n"; cin.get(); cin.get(); return 1; } else { cout << "Wrong password\n"; cout << "Terminating...\n"; return 2; } } } return 1; } int main() { int a; cout << "IS THIS THE FIRST TIME YOU ARE USING THIS FILE?\n"; cout << "PRESS '1' IF YES AND '2' IF NO.\n"; cin >> a; if (a == 1) { funktion_first(); funktion_pass(); if(funktion_pass() == 1) { cout << "Entering program...\n"; funktion_main(); cout << "terminating...\n"; return 1; } else if(funktion_pass() == 2) { funktion_pass(); return 1; } } else if(a == 2) { funktion_pass(); if(funktion_pass() == 1) { cout << "Entering program...\n"; funktion_main(); cout << "terminating...\n"; return 1; } else if(funktion_pass() == 2) { funktion_pass(); return 1; } return 0; } }

Hoppas ni har tid och ork att gå igenom en sån här lång bit kod.
/Calle

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av t0t4l str3
Efter man har skrivit in lösenordet så står det "Password accepted", precis som det ska. Trycker man sedan enter så anropas tydligen "funktion_pass" igen. Helkonstigt eftersom jag bara anropar den en gång.

Nja, faktum är att du anropar funktionen två gånger i main():

funktion_pass(); if(funktion_pass() == 1)

Resultatet av det första anropet används dock inte utan en ny "beräkning" krävs för att jämföra med 1. Alternativa lösningar är att spara det första resultatet och jämföra med detta:

int q =funktion_pass(); if(q == 1)

eller att helt enkelt strunta i det första anropet:

if(funktion_pass() == 1)

Permalänk

Ursäkta för sent svar, men det fungerade ypperligt.

Jag håller nu på med ett nytt program som krypterar en mening, men jag får inte den heller att fungera korrekt.

#include <iostream> #include <algorithm> using namespace std; using std::cout; using std::cin; int before_encrypt(); void encrypt(char sentence); void encrypt(char sentence[29]) { reverse (sentence, sentence + strlen (sentence)); for( int i=0; sentence[i] != '\0'; ++i ) ++sentence[i]; return 0; } int before_encrypt() { char sentence[29]; cout << "Write your sentence here: \n"; cin >> sentence; encrypt(sentence[29]); cout << "The encrypted version of your sentence is: " << sentence; return 0; } int main() { int answer; cout << "Would you like to encrypt or decrypt a text file?\n"; cout << "Press '1' to encrypt and '2' to decrypt.\n"; cout << "Press '3' to exit.\n"; cin >> answer; if (answer == 1) before_encrypt(); else if (answer == 2) return 0; }

(obs. main-funktionen är inte riktigt klar)

Det jag vill att programmet ska göra är följande:
1. Fråga om man vill kryptera eller dekryptera en mening (har inte gjort dekryptionsdelen än)
2. Ta in meningen och skicka den till funktionen encrypt (från before_encrypt)
3. göra om meningen så den blir baklänges.
4. Kryptera meningen mha. Caesar-chiffer (a blir b, h blir i, c blir d osv.)
5. Skriva ut den nya meningen på skärmen.
När jag "bygger" applikationen får jag det här felet:

1>------ Build started: Project: Encryption, Configuration: Debug Win32 ------ 1>Compiling... 1>Encryption.cpp 1>Linking... 1>LINK : warning LNK4067: ambiguous entry point; selected 'mainCRTStartup' 1>Encryption.obj : error LNK2019: unresolved external symbol "void __cdecl encrypt(char)" (?encrypt@@YAXD@Z) referenced in function "int __cdecl before_encrypt(void)" (?before_encrypt@@YAHXZ) 1>I:\Users\XXXX\Documents\Visual Studio 2008\Projects\Encryption\Debug\Encryption.exe : fatal error LNK1120: 1 unresolved externals 1>Build log was saved at "file://i:\Users\XXXX\Documents\Visual Studio 2008\Projects\Encryption\Debug\BuildLog.htm" 1>Encryption - 2 error(s), 1 warning(s) ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Jag brukar inte få sådana här linker-fel och jag vet inte vad de beror på. I vanliga fall brukar man kunna se ungefär vad som är fel och var felet ligger, men nu fattar jag ingenting.

Hoppas någon förstår!
/Calle

Permalänk
Medlem

du har char sentence som input i encrypt, char är bara ett tecken inte en sträng, du behöver en array av tecken, eller pekare. Man skickar inte heller in sentence[24] som input som i detta fall skiljer sig från din definition, skicka med char* samt antal tecken eller nått, ev kan man loopa och leta efter närmaste 0 som terminerar strängen omdet är säkert den finns där. Varför inte använda string som är vanligare i C++?

Sen blir det fel på main som du sa inte var klar, return 0 blir om answer==2, main måste avslutas med return ... på alla möjliga vägar och inte endast om answer==2. Nästan bättre du använder tomma paranteser så programmet gör det man tänkt göra.

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av t0t4l str3

void encrypt(char sentence);

Här deklarerar du en (oanvänd) funktion som tar ett tecken som argument. Skippa eller uppdatera så att den tar en char-pekare istället.

Citat:

Ursprungligen inskrivet av t0t4l str3

void encrypt(char sentence[29]) { reverse (sentence, sentence + strlen (sentence)); for( int i=0; sentence[i] != '\0'; ++i ) ++sentence[i]; return 0; }

[/i]
"char sentence[29]" bör ändras till "char sentence[]" eller "char* sentence" för att beteckna en char-pekare. Det är dessutom inte (vanligtvis) tillåtet att returnera något i en void-funktion. Byt ut "return 0;" mot "return;" eller, ännu hellre, skippa det helt.

Citat:

Ursprungligen inskrivet av t0t4l str3

encrypt(sentence[29]);

"sentence[29]" är ett enskilt tecken (som dessutom ligger precis utanför det minne som har allokerats åt de 29 tecknen i "sentence". Ändra till
encrypt(sentence);

Citat:

Ursprungligen inskrivet av t0t4l str3
1>Encryption.obj : error LNK2019: unresolved external symbol "void __cdecl encrypt(char)" (?encrypt@@YAXD@Z) referenced in function "int __cdecl before_encrypt(void)" (?before_encrypt@@YAHXZ)

Det här betyder vanligen att det inte gick att hitta någon funktion som passar det du försöker skicka in (i det här fallet från "before_encrypt"). I "before_encrypt" använder du en funktion som tar ett tecken som argument och du har mycket riktigt deklarerat förekomsten av en sådan funktion högst upp i filen. Det finns dock ingen implementation av den.

Permalänk

Tack för svaren!
Ska ändra else if satsen i main till bara else. Glömde det sist.
Ska även ändra så att void-funktionen inte returnerar något.
Det knepiga blir då det här med pekare.
Jag har läst lite här: http://cplusplus.com/doc/tutorial/pointers/ om pekare men jag förstår inte det till hundra procent.
Försökte även göra applikationen med referenser, men tydligen så fungerar det bara med tal. Eller?
Dalton Sleeper, anledningen till att jag inte använder string är att jag inte vet hur man får ut enskilda bokstäver ur en sträng, samt att jag inte vet om det kommer att fungera med min for-loop.
OK. provar igen med era tips.

#include <iostream> #include <algorithm> using namespace std; using std::cout; using std::cin; int before_encrypt(); void encrypt(char* sentence); void encrypt(char* sentence) { reverse (sentence, sentence + strlen (sentence)); for( int i=0; sentence[i] != '\0'; ++i ) ++sentence[i]; } int before_encrypt() { char sentence[29]; cout << "Write your sentence here: \n"; cin >> sentence; encrypt(sentence); cout << "The encrypted version of your sentence is: " << sentence; return 0; } int main() { int answer; cout << "Would you like to encrypt or decrypt a text file?\n"; cout << "Press '1' to encrypt and '2' to decrypt.\n"; cout << "Press '3' to exit.\n"; cin >> answer; if (answer == 1) { before_encrypt(); return 0; } else return 0; }

Det verkar fungera bra. Att det kunde vara så enkelt.
Nu är bara problemet att hur jag än gör så stängs programmet efter att jag har skrivit in min mening. Det kvittar om jag så sätter in tio st. "cin.get()", det avslutas ändå. Hur ska jag göra?
/Calle

Permalänk
Medlem

Du behöver inte ha return 0 på båda patharna:

cin >> answer; if (answer == 1) { before_encrypt(); } // här kan du sätta cin.get() eller system("pause") eller cin >> answer eller nått fint så programmet stannar innan return. return 0;

Edit: cin.get() fungerar inte, har aldrig kört med det tidigare heller :S
Edit2:

int before_encrypt() { char sentence[29]; cout << "Write your sentence here: \n"; cin >> sentence; encrypt(sentence); cout << "The encrypted version of your sentence is: " << sentence; return 0; }

Här har du returvärde vilket du inte behöver, om du inte tänkt lägga till nått mer förstås, nu fungerar det att köra med void:

void before_encrypt(){ ... //utan return 0 }

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av Dalton Sleeper
Edit: cin.get() fungerar inte, har aldrig kört med det tidigare heller :S

Jodå, problemet är bara att det blir kvar en radbrytning eller liknande i bufferten när man använder retur för att avsluta inmatningen av meningen. Använd
cin.ignore(1);
för att avlägsna den, eller kör två
cin.get();
efter varandra.

Citat:

Ursprungligen inskrivet av t0t4l str3
Dalton Sleeper, anledningen till att jag inte använder string är att jag inte vet hur man får ut enskilda bokstäver ur en sträng, samt att jag inte vet om det kommer att fungera med min for-loop.

Man kan göra som du gör nu.
string s = "ujujuj";
char s2 = s[0]; // 'u'
char s3 = s[1]; //'j'

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Elgot
Jodå, problemet är bara att det blir kvar en radbrytning eller liknande i bufferten när man använder retur för att avsluta inmatningen av meningen. Använd
cin.ignore(1);
för att avlägsna den, eller kör två
cin.get();
efter varandra.

Se där, man lär sig nått nytt varje dag att det kan ligga kvar radbrytning vet jag, dock var det senast jag använde C vilket var ett tag sen, visste inte att problemet fortfarande fanns kvar med cin...

Permalänk
Hedersmedlem
Citat:

Ursprungligen inskrivet av Dalton Sleeper
Se där, man lär sig nått nytt varje dag att det kan ligga kvar radbrytning vet jag, dock var det senast jag använde C vilket var ett tag sen, visste inte att problemet fortfarande fanns kvar med cin...

Det är väl inte nödvändigtvis ett problem; kanske vill man att användaren även skall kunna mata in radbrytningar? Om så inte är fallet, och man inte vill använda ovanstående, kan man med fördel använda getline.