Hej! Jag håller på med programmering A i skolan, men har kört fast på en uppgift. Man skulle skriva ett program där man först matar in en bokstav, sedan en mening, sedan ska programmer berätta hur många gånger den valda bokstaven förekommer i meningen. Koden än så länge: Hehe... jag kan garanterat säga att det inte är just vokalerna som försvinner... =) <quote> oj! SÅg inte ++i.. Jag provade att använda en While-loop och glömde då att tabort när jag sedan gjorde om den till en fort-sats. Men tack så mycket för alla tipsen :) Det löser sig nog nu. <b>>Jag föreslår att du skriver så här: Robert frågade mig en fråga över iMail, och för att andra ska kunna ta del av den så skriver jag svaret här. >> en bättre lösning hade troligtvis kunnat ske med hjälp av något ur <algorithm>-biblioteket. Fast just namnrymden std tycker jag att man gott kan öppna. Och speciellt som nybörjare då man kanske inte ens har lärt sig om namnrymder. Det finns annat som är viktigare att fokusera på i första programmeringskursen. Håller inte med. std innehåller mycket, och även om man nog hade undvikt en hel del namn själv är det svårt att hålla reda på allt. Jag brukar öppna namnrymder i main-filen, men inte i header och klass-filer. Eftersom det bara var en fyra-fem stycken av länkarna som tog upp namespace, och alla utom en höll med min princip, och eftersom de främsta inom C++ också samtycker så är det nog så att det är den mest utbredda åsikten. Varför finns namnrymder om det inte är meningen att man skall öppna dem? Vore det meningen att man alltid skulle skriva std::cout hade vi lika gärna klarat oss med metoden som brukar användas i C för att "simulera" namnrymder, dvs att skriva std_cout. Namnrymder har ju många fördelar framför en enkel namngivningsstandard: <quote>Med samma princip som du säger kunde man lika gärna ha struntat i att ha klasser också, och ha en namngivning där.</quote> <b>>Nej, klasser har en del annan funktionalitet (t.ex. arv) som inte namnrymder har.</b> <b>På precis samma sätt kan man simulera en namnrymd, men det finns inbyggt i C++, och min åsikt är då att man bör använda det.</b> <b>>Vad jag argumenterar för här är att namnrymder inte ger minsta lilla extra om man inte skall öppna dem utan alltid skriva t.ex. std::cout.</b> <b>Det är som att säga till barn som ska lära sig att gå i trafik att de ska strunta i trafikljusen. "Det är så många som slarvar ändå, och det spelar inte så stor roll, så länge man kollar hur bilarna åker."</b> <b>>Jag tycker snarare att det handlar om små barn som precis ska lära sig att gå. Du predikar om trafikljus medan barnen stapplande försöker ta sina första steg på en liten gräsplätt långt från farlig trafik. Själv tycker jag att de i första hand skall lära sig att gå. Men sedan, när de skall ut i trafiken, då är det viktigt att lära ut trafikvett. </b> <b>Hört talas om systemoberoende kod?</b> Jo, så sätt, men det är ju egentligen kompilatorns och länkarens uppgift att avgöra vad som skall länkas in och inte. Tycker inte du som jag att det är dags att avsluta den här debatten nu? Inga problem, hade själv tänkte föreslå det som nästa inlägg. Lite komiskt hur lång och invecklad tråden blev med tanke på att jag bara frågade en enkel fråga för och om programmering a på gymnasienivå :PVokaler försvinner
<code>#include <iostream.h>
void main()
{
char tecken, strang[50];
int antal, i;
cout << "Mata in tecken: ";
cin >> tecken;
cin.ignore();
cout << "Mata in string: ";
cin.getline(strang,sizeof(strang));
antal = 0;
for (i = 0; i < sizeof(strang); i++)
{
if (strang[i] == tecken)
{
++antal;
}
++i;
}
cout << endl << "Tecknet '" << tecken << "' förekommer " << antal << " gaonger i straengen '" << strang << "'." << endl;
}</code>
Det som händer är att den ger ett felaktigt antal, trots att när strängen skrivs ut blir den helt korrekt. När jag försökte loopa igenom strang[]:
<code>
for (i = 0; i < sizeof(strang); i++)
{
cout >> strang[i];
}
</code>
Så försvinner oftast alla vokaler, förutom kanske 1 eller 2, fast dom saknas som ovan nämnt inte när hela strängen väl skrivs ut.
Tack för hjälpen på förhand!
mvh RobertSv: Vokaler försvinner
Nåväl.
1. Byt ut <iostream.h> till <iostream> och skriv std::cin istället för cin, och std::cout istället för cout.
2. Det är den här förbannade jävla gymnasieprogrammeringen...
Du bör absolut inte använda char strang[50], utan std::string istället. Risken är dock stor att era lärare säger att ni inte får det. Säg då till vederbörande att det är en mycket dålig princip att gå efter och att ni i första hand bör lära er standardbiblioteket, och inte skräp som C-arrayer.
Ni lär er nästan ingenting på det, och det blir istället felbenäget.
3. Eftersom ni förmodligen inte får lov att göra det så kan jag ge ett svar ändå.
problemet ligger i att du skriver
for (i = 0; i < sizeof(strang); i++)
{
if (strang[i] == tecken)
{
++antal;
}
++i;
}
Vad gör for-loopen?
Den loopar i från 0 till sizeof(strang).
Men samtidigt har du ++i inuti loopen.
Vad det innebär är helt enkelt att du hoppar över varannat tecken. Ta bort det så bör det funka.
Sv: Vokaler försvinner
1. Byt ut <iostream.h> till <iostream> och skriv std::cin istället för cin, och std::cout istället för cout.
</quote>
Jag föreslår att du skriver så här:
<code>
#include <iostream>
using namespace std;
</code>
Då kan du fortsätta köra med bara cin och cout.
<quote>
2. Det är den här förbannade jävla gymnasieprogrammeringen...
Du bör absolut inte använda char strang[50], utan std::string istället. Risken är dock stor att era lärare säger att ni inte får det. Säg då till vederbörande att det är en mycket dålig princip att gå efter och att ni i första hand bör lära er standardbiblioteket, och inte skräp som C-arrayer.
Ni lär er nästan ingenting på det, och det blir istället felbenäget.
</quote>
I den litteratur (Gleerups) som används på den gymnasieskola där jag jobbar, används teckenfält (char ... []) i Programmering A och klassen string i Programmering B. Men egentligen borde nog ordningen vara den ombytta. I kursplanen för PA står dessutom inget om fält; det kommer inte förrän i PB. Ändå tar boken upp fält redan i PA.Sv: Vokaler försvinner
Sv: Vokaler försvinner
>#include <iostream>
>using namespace std;
>Då kan du fortsätta köra med bara cin och cout. </b>
Visst kan man göra så, men då är förlorar ju namnrymder hela sin poäng. Ger bara dåliga vanor att släppa upp hela namnrymden globalt. Att göra det inom funktionen är i så fall lämpligare, och hellre en enkel using.
Jag skulle alltså säga att antingen
#include <iostream>
int main()
{
using namespace std;
cout << "ABC";
}
eller
#include <iostream>
int main()
{
using std::cout;
cout << "ABC";
}
eller
#include <iostream>
int main()
{
std::cout << "ABC";
}
Sen angående teckenfält eller c-strängar. Tycker inte det borde finnas med överhuvudtaget i en gymnasieundervisning, eller åtminstone inte före grundläggande OO.
Det finns i stort sett aldrig behov av några typer av fält, vare sig c-strängar eller andra typer. Algoritmer, datastrukturer, oo och ett sunt användande av bibliotek borde värderas mycket högre, och det kan göras helt och hållet utan inblandning av sådana grundläggande, felbenägna typer.
Sv: Vokaler försvinner
Hur man löser problemet med string istället gör man till exempel på följande vis:
#include <iostream>
void main()
{
char tecken;
std::string strang;
int antal;
std::cout << "Mata in tecken: ";
std::cin >> tecken;
std::cin.ignore();
std::cout << "Mata in string: ";
std::cin >> strang;
antal = 0;
for (std::string::iterator i = strang.begin(); i != strang.end(); i++)
{
if (*i == tecken)
{
++antal;
}
}
std::cout << std::endl << "Tecknet '" << tecken << "' förekommer " << antal << " gaonger i straengen '" << strang << "'." << std::endl;
}
Detta är bara en modifierad version av grundprogrammet, en bättre lösning hade troligtvis kunnat ske med hjälp av något ur <algorithm>-biblioteket.
Sv: Vokaler försvinner
<code>
antal = std::count(strang.begin(), strang.end(), tecken);
</code>Sv: Vokaler försvinner
Sv: Vokaler försvinner
Då tycker jag det är bättre att hålla en allmän attityd där man hela tiden bevarar namnrymder så gott det går.
Det är ju knappast ett stort problem att komma ihåg att det man använder från standardbiblioteket ska ha en liten std:: framför, det behövs ingen fokus på namnrymder - det är ju ingen större skillnad på om man ska komma ihåg att skriva cout för att skriva ut text, och då använda >> eller om man ska skriva std::cout och använda >>.
Att släppa upp hela globalt är iaf i mitt tycke helt onödigt.
Har aldrig varit med om att någon som faktiskt har börjat med att skriva på det sättet har haft några problem för det, snarare tvärtom.Sv: Vokaler försvinner
Några länkar till coding-styles i c++, vissa av dem motsäger varandra så det finns ingen riktig "rätt" väg.
http://www.possibility.com/Cpp/CppCodingStandard.html
http://www.parashift.com/c++-faq-lite/coding-standards.html
http://www.chris-lott.org/resources/cstyle/
http://www.shift-right.com/openrepo/codingstandard.htm
http://directory.google.com/Top/Computers/Programming/Languages/C%2B%2B/Style/
http://iq0.com/notes/deep.nesting.html
http://www.research.att.com/~bs/bs_faq2.html
http://www.rt.e-technik.tu-darmstadt.de/~mali/DOC/tide/convent.html
/RobertSv: Vokaler försvinner
Det jag mest blir förvånad över är hur lata programmerare verkar vara; hur svårt är det egentligen att skriva ett std:: framför de raderna som tillhör standardbiblioteket?
Använder man dessutom andra bibliotek så bör man ju oavsett använda principen där, eller tycker ni att man ska släppa upp allt överallt?
Hade man inte sett ett behov av att göra ett standard-namespace så hade man inte gjort det...Sv: Vokaler försvinner
Sv: Vokaler försvinner
För det första är det en rimlig del av språket, och det gör att man mer eller mindre tvingar en användare att hantera namnrymder, något man rakt av kan strunta i genom en namngivning.
För det andra så är omdöpning av namnrymder utmärkta hjälpmedel i vissa situationer; "conditional compilation", t.ex. (kommer inte på någon vettig översättning, jag e bakis)
Sen är det ju omöjligt att använda namn som finns i två namnrymder och släppa upp båda två, vilket också ger ett bra "stopp" för den mänskliga faktorn.
Med samma princip som du säger kunde man lika gärna ha struntat i att ha klasser också, och ha en namngivning där.
Att släppa upp namnrymder är väl inget fel i sig, men att göra det i den globala är att helt underminera hela konceptets existens.Sv: Vokaler försvinner
Nej, klasser har en del annan funktionalitet (t.ex. arv) som inte namnrymder har.
<quote>det gör att man mer eller mindre tvingar en användare att hantera namnrymder, något man rakt av kan strunta i genom en namngivning.</quote>
Så som det fungerar i C++ kan man ändå strunta i namnrymder.
<quote>Sen är det ju omöjligt att använda namn som finns i två namnrymder och släppa upp båda två, vilket också ger ett bra "stopp" för den mänskliga faktorn.</quote>
Men, säger du inte här att det är bra att öppna två namnrymder in i en gemensam namnrymd (den globala)?
Det här skulle inte ge några problem om man konsekvent körde med "prefixnamnrymder" (C-stil).
"conditional compilation" = villkorlig kompilering
(jag är nykter)Sv: Vokaler försvinner
Jovisst, men allt det går att simulera, även polymorfism och liknande. (t.ex. med lite "trevliga" switch-satser varstans, eller med void-pekare och typ som argument). Men det är väldigt mycket trevligare att ha det inbyggt i språket. På precis samma sätt kan man simulera en namnrymd, men det finns inbyggt i C++, och min åsikt är då att man bör använda det.
<b>>Så som det fungerar i C++ kan man ändå strunta i namnrymder.</b>
Ja, delvis, genom att göra precis som du föreslår. Skillnaden är att då att man faktiskt _måste_ skriva namnrymden ska öppnas, och då har man redan blivit tvingad till det.
<b>>Men, säger du inte här att det är bra att öppna två namnrymder in i en gemensam namnrymd (den globala)?</b>
Nej, det jag säger är att om man öppnar två namnrymder med gemensamma namn så blir det krångel. Det är en fördel eftersom man blir hindrad från att göra dumheter när man gör en sån sak som att släppa upp två namnrymder. Men samtidigt så finns det troligtvis en bättre lösning utan att släppa upp dem.
<b>>Det här skulle inte ge några problem om man konsekvent körde med "prefixnamnrymder" (C-stil).</b>
Nä, det stämmer, men jag förstår inte din poäng.
<b>>"conditional compilation" = villkorlig kompilering</b>
Jepp. Men det finns i mitt tycke inget bättre verktyg för en villkorlig kompilering mellan t.ex. en win32- och en linux-source än just namnrymder.Sv: Vokaler försvinner
Jag håller med om att man bör använda namnrymder. Vad jag argumenterar för här är att namnrymder inte ger minsta lilla extra om man inte skall öppna dem utan alltid skriva t.ex. std::cout.
<b>Skillnaden är att då att man faktiskt _måste_ skriva namnrymden ska öppnas, och då har man redan blivit tvingad till det.</b>
Förstår inte vad du menar.
<b>Men det finns i mitt tycke inget bättre verktyg för en villkorlig kompilering mellan t.ex. en win32- och en linux-source än just namnrymder.</b>
Kan du ge exempel? Kan du komma från preprocessordirektiv såsom #if?Sv: Vokaler försvinner
Jag säger inte att man aldrig ska öppna en namnrymd, däremot säger jag att man inte ska öppna namnrymder i den globala.
Men det är inte det jag reagerar på mest, utan på att du skrev att man som nybörjare inte ska befatta sig med namnrymder. Det är tillräckligt många som slarvar redan, och om folk inte lär sig det rätt från början så finns det inga skäl att tro att de kommer göra det sen.
Det är som att säga till barn som ska lära sig att gå i trafik att de ska strunta i trafikljusen. "Det är så många som slarvar ändå, och det spelar inte så stor roll, så länge man kollar hur bilarna åker."
<b>>>Skillnaden är att då att man faktiskt _måste_ skriva namnrymden ska öppnas, och då har man redan blivit tvingad till det.
>Förstår inte vad du menar.</b>
Om du skriver "using namespace std;" så hanterar du namnrymder, menade jag bara.
<b>>Kan du ge exempel? Kan du komma från preprocessordirektiv såsom #if?</b>
Inte helt, men det blir ytterst lite.
Ex:
namespace Win32
{
void funktion1();
void funktion2();
}
namespace Linux
{
void funktion1();
void funktion2();
}
//ovanstående utspridda över flera filer, osv.
#if _WIN32
namespace OP Win32;
#else
namespace OP Linux;
#endif
void enfunktion ()
{
OP::funktion1();
OP::funktion2();
}
På det här viset kan du skriva alla tre delarna separat, och den enda #if du behöver är den som döper om namnrymderna. Och naturligtvis kan man använda olika using inuti "enfunktion".
Sv: Vokaler försvinner
Jag tycker snarare att det handlar om små barn som precis ska lära sig att gå. Du predikar om trafikljus medan barnen stapplande försöker ta sina första steg på en liten gräsplätt långt från farlig trafik. Själv tycker jag att de i första hand skall lära sig att gå. Men sedan, när de skall ut i trafiken, då är det viktigt att lära ut trafikvett.
Angående ditt exempel:
Varför ha med funktioner för både Windows och Linux i samma program? Man brukar vilja ha funktioner för antingen Windows eller Linux i ett program. Om du endast har för avsikt att ha med funktionerna för ett av operativsystemen finns det ingen anledning att använda namnrymder eftersom det inte uppstår någon namnkollision. Sv: Vokaler försvinner
Analogin börjar ju minst sagt spåra ur. Det är inte svårt att flytta in using namespace inuti funktioner, och folk som inte lär sig ett sunt förhållande till namnrymder kommer ha väldigt mycket svårare att lära sig det senare också, det var det som var min poäng.
<b>>Varför ha med funktioner för både Windows och Linux i samma program? Man brukar vilja ha funktioner för antingen Windows eller Linux i ett program. Om du endast har för avsikt att ha med funktionerna för ett av operativsystemen finns det ingen anledning att använda namnrymder eftersom det inte uppstår någon namnkollision. </b>
Va?!
Hört talas om systemoberoende kod?
Jag vill kunna skicka programmet till någon med ett annat operativsystem och kunna byta ett stort antal funktioner mycket enkelt. Eller byta en del debugkod mot releasekod. Det jag då gör är att jag skriver all kod separat i sina egna namnrymder.
En funktion som vill göra något (lista alla filer i en katalog, t.ex.) anropar en annan funktion som gör det och bryr sig inte det minsta om hur det går till för ett enskilt os.
T.ex.
void f()
{
std::vector<std::string> vs;
vs=OS::ListDirs();
//...
}
Jag skickar alltid med hela programkoden, alltid samma kod, oavsett os. Sen kan alla kompilera koden oavsett os.Sv: Vokaler försvinner
Självklart har jag det. Och det är bra att du skickar med kod för flera system. Men min fråga är om du länkar in alla dessa systems kod i programmet. Tar du inte bara med den kod som hör till det aktuella systemet?Sv: Vokaler försvinner
Systemoberoende var ju bara ett exempel, överhuvudtaget byten mellan olika delar av kod är enkel och smidig på det sättet, och det ger dessutom en tydlig markering om vad koden betyder.Sv: Vokaler försvinner
Jag tror att vi kan konstatera att...
* vi är överens om att namnrymder är bra
* det kan vara okej att öppna dem lokalt (t.ex. att släppa ut matematikfunktioner i ett block med mycket beräkningar)
* vi är oense om "globalt öppnande"
- jag anser att std är okej att öppna upp helt
- du anser inte att det är okejSv: Vokaler försvinner
Tror dock att det är ganska bra med såna här diskussioner, dels för egen del, men även för andra som läser det.
Man kan säga det som att det blir fler än två som deltar i diskussionen, men inte aktiva.Sv: Vokaler försvinner