"na na" <na@na.na> wrote
[8<8<8<]
> Du skal indlæse en tilfældig tekstfil, der indeholder et ukendt antal
> linjer, og længden på disse linjer kender du heller ikke.
> Når hele filen er blevet indlæst, lukker du filen, og udskriver de X
linjer
>
> Hvordan vil du helt præcist bære dig ad med det uden at bruge pointere...
Helt præcist :
<code>
#include <fstream>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <iterator>
#include <exception>
int main(int argc, char* argv[])
{
using namespace std;
try {
for(int i = 1; argc != i; ++i) {
ifstream file(argv[i]);
if(!file) {
cerr << "unable to open file: \"" << argv[i] << "\"";
continue;
}
// calculate the file size
file.seekg(0, ios::end);
const size_t file_size = file.tellg();
file.seekg(0, ios::beg);
// allocate the memory for the file content
vector<char> file_content(file_size+1);
// read the entire file into the buffer
file.read(&file_content[0], file_size);
file_content[file_size] = '\0';
// print the entire file
copy(file_content.begin(), file_content.end(),
ostream_iterator<char, char>(cout));
cout << endl;
}
}
catch(const exception& x) {
cerr << x.what() << endl;
return EXIT_FAILURE;
}
catch(...) {
cerr << "unexpected C++ exception detected" << endl;
return EXIT_FAILURE;
}
}
</code>
og hvis du gerne vil have det linie orienteret:
<code>
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <iterator>
#include <exception>
int main(int argc, char* argv[])
{
using namespace std;
try {
for(int i = 1; argc != i; ++i) {
ifstream file(argv[i]);
if(!file) {
cerr << "unable to open file: \"" << argv[i] << "\"";
continue;
}
vector<string> lines;
string line;
while(getline(file, line)) {
lines.push_back(line);
}
// print the entire file
copy(lines.begin(), lines.end(),
ostream_iterator<string, char>(cout, "\n"));
cout << endl;
}
}
catch(const exception& x) {
cerr << x.what() << endl;
return EXIT_FAILURE;
}
catch(...) {
cerr << "unexpected C++ exception detected" << endl;
return EXIT_FAILURE;
}
}
</code>
Du specificerer hvilke filer, der skal åbnes som kommandolinie parametre.
Programmerne er komplete med fejl håndtering etc.
Bemærk iøvrigt at programmer var nemme at skrive.
[8<8<8<]
> Hvis ikke det han laver er super simpelt (måske ligefrem primitivt) kan
han
> da ikke, før programkørsel, være sikker på hvor mange vertices han får
brug
> for, og så kommer pointerne på banen igen...
Brug
vector<Vertex>
>
>
>
> Jeg kunne nok blive ved i et godt stykke tid endnu, og komme på eksempler
> hvor der skal bruges pointere.
Kan bruges pointere.
[8<8<8<]
> Nej... Nu skal du ikke komme med en eller anden forklaring på at man da
bare
> bruger f.eks. en vector-container i stedet for, og index'erer ind i dette,
i
> stedet for at bruge pointere... Ehh... Gad vide om ikke vector'en internt
> benytter sig af pointere ;) *hint hint*
Det væsentlige er ikke hvordan et bibliotek er skrevet.
Det væsentlige er hvordan man skriver sin applikationskode.
[8<8<8<]
> OK... Jeg kommer lige ned på jorden igen (Ikke ophidset men kunne måske
godt
> lyde sådan)... Kan du ikke lige komme med et enkelt, eksempel på et
brugbart
> dagligdags-program, hvor der ikke er brug for pointere.
Her er et eksempel, hvor der stor set ikke bruges pointeresom jeg brugte i
en nyhedsgruppe forleden.
Nedenstående program får som kommandolinie option angivet navnet på nogle
filer, hvori der står en række regne-udtryk, som f.eks
1*2+3*4
adskilt med mellemrum.
Programmet parser udtrykket og beregner resultatet
Programmet processerer i høj grad tekst og skal kunne håndtere dynamisk
input.
Eneste begrænsning er mængden af tilgængelig hukommelse.
Programmet er skrevet i 100 % Standard C++ (med anvendelse af Spirit parser
biblioteket -
http://www.boost.org/libs/spirit/index.html), og vil derfor
kunne oversætte på alle platforme hvor der findes en Standard C++ compiler.
Bemærk at syntaxen er beskrevet på en form, der minder meget om EBNF.
Det er ikke et program der arbejder sprogmæssigt på et lavt niveau i
forbindelse med tekst processering.
Det er ikke et program der laver fuldstændigt trivielle opgaver.
Det er ikke et urealistisk program.
Det er ikke et program der anvender teknikker der skalerer dårligt
(performance mæssigt, vedligeholdelses mæssigt etc.).
Programmet er komplet med fejlhåndtering.
Programmet indholder ikke nogen explicit dynamisk hukommelse håndtering
eller pointer aritmetik i forbindelse med parsningen.
Det er ikke et program der er udviklet med lav programmør produktivitet.
Der er ingen risiko for problemer som memory-leak, dangling pointer, buffer
overrun etc.
<83 linier Standard C++ kode>
#include <iostream>
#include <fstream>
#include <stack>
#include <functional>
#include "boost/spirit/spirit.hpp"
using namespace std;
using namespace spirit;
stack<int> evaluation_stack;
struct do_push_int
{
typedef int arg_type;
void operator()(int n) const
{ evaluation_stack.push(n); }
};
template <class operation>
struct do_operation
{
void operator()(char const* /*begin*/, char const* /*end*/) const
{
const int rhs = evaluation_stack.top();
evaluation_stack.pop();
const int lhs = evaluation_stack.top();
evaluation_stack.pop();
evaluation_stack.push(operation()(lhs, rhs));
}
};
struct do_negate
{
void operator()(char const* /*begin*/, char const* /*end*/) const
{
const int lhs = evaluation_stack.top();
evaluation_stack.pop();
evaluation_stack.push(-lhs);
}
};
int main(int argc, char* argv[])
{
rule<> expression, term, factor, integer;
integer =
int_p[do_push_int()];
factor =
integer
| '(' >> expression >> ')'
| ('-' >> factor)[do_negate()];
term =
factor >>
* ( ('*' >> factor)[do_operation<multiplies<int> >()]
| ('/' >> factor)[do_operation<divides <int> >()]
);
expression =
term >>
*( ('+' >> term)[do_operation<plus <int> >()]
| ('-' >> term)[do_operation<minus<int> >()]
);
// Process each file specified on the command line
for(int i = 1; i != argc; ++i) {
ifstream file(argv[i]); // uses char pointer and pointer arithmetic
if(file) {
// Process each line in the file
string text;
while(file >> text) {
if(parse(text.c_str(), expression, space).full) {
cout << "Result: " << text << " = " << evaluation_stack.top()
<< endl;
evaluation_stack.pop();
}
else {
cerr << "Error: \"" << text << "\" is not a valid expression"
<< endl;
// flush the evaluation stack
evaluation_stack = stack<int>();
}
}
}
else {
cerr << "Error: Unable to open file: " << argv[i] << endl;
}
}
}
<83 linier Standard C++ kode/>
[8<8<8<]
> Min pointe er: Efter min mening, er pointere en så central del af C og
C++,
ja
> at man ikke kan undgå at bruge det tit...
Oftere end mange tror
> Jeg har efterhånden haft gang i en
> del forskellige projekter (lige fra de helt små, til de helt store), og
jeg
> tror ikke der er ét hvor jeg ikke har haft brug for pointere
Naturligvis.
Når man skrive
<code>
int main(int argc, char* argv[])
{
// ...
}
</code>
bruger man pointere.
Venlig hilsen
Mogens Hansen