Forum: PC-Programmierung Ausgabe Stream als txt_datei


von Dennis (Gast)


Lesenswert?

Hallo alle Zusammen,

Programmiersprache: C++ (Visual Studio 2010)
Ich habe eigentlich einen kleinen Problem mit einem txtAusgabe.

Ich versuche einen Prog zu schreiben der einen txtDateiInput liesst und 
das Ergebnis in einen anderen txtDateiOutput ausgibt.

Es lauft fast alles richtig mit einen Ausnahme.

Ich will die Ausgabe (txtDateiOutput) wie folgenden formatieren:
ZB:
1
3 5 6 7 
2
 4 9 1
3
  3 11
4
   8
Die ausgabe sollte so eine Pyramide aussehen haben.

datei schreibe ich mit diesen befehl:
1
ofstream datei(zielDatei,ios::app);
2
copy(v.begin(),v.end(),ostream_iterator<int>(datei," "));
3
datei<<"\"; // neue zeile
4
5
cout << ""; // hilft nicht weiter
6
datei<<setw(2); hilft auch nicht weiter ...
hat jemenden eine Idee ?
Danke in voraus

von Karl H. (kbuchegg)


Lesenswert?

Dennis schrieb:

> hat jemenden eine Idee ?

Ich kenn zwar auch nicht alle Formatter der stream Library, aber:

Nicht alle Probleme kann man dadurch lösen, dass man einfach alles in 
einem Rutsch von A nach B kopiert. Irgenwann muss man auch mal die 
Bequemlichkeit von
1
 copy(v.begin(),v.end(),ostream_iterator<int>(datei," "));
über Bord werfen und das ganz ganz klassisch mit
1
   while( Zeile als String lesen )
2
     Länge feststellen
3
     entsprechende Anzahl an Leerzeichen ausgeben
4
     Zeile da drann hinten anhängend ausgeben
lösen, wenn die Formattierung der Eingabedatei das erlaubt. Wenn nicht, 
dann eben andere Vorgehensweise.

Nicht alle Probleme lassen sich mit 3 Zeilen STL Code lösen. Irgendwann 
muss man auch mal selber ran, und was programmieren anstatt nur 
vorgefertigte Teile zu kombinieren oder, der Herr sei mit uns, auch mal 
was berechnen.

von Robert L. (lrlr)


Lesenswert?

wenn in der Hausaufgabe steht: STL Code (was auch immer das ist)
dann wird man das so machen müssen, auch wenn es anders einfacher wäre 
;-)

von Karl H. (kbuchegg)


Lesenswert?

Robert L. schrieb:
> wenn in der Hausaufgabe steht: STL Code (was auch immer das ist)

Standard Template Library

> dann wird man das so machen müssen, auch wenn es anders einfacher wäre
> ;-)

Richtig.
Wenn das so in der Hausaufgabe steht, dann hat er aber auch in der 
Schule das Handwerkszeug gelernt, welches er verwenden kann.
Wir wissen ja auch nicht, was in seinem Beispiel v ist, wo er herkommt, 
wie er entsteht. Ich vermute zur Zeit, das es ein std::vector ist, ist 
aber nur eine Vermutung aus dem Bauch heraus. Wir wissen auch nicht, wie 
seine Eingabedatei aussieht, etc. etc.
Es könnte auch sein, dass er im Prinzip am Programm gar nicht viel 
ändern muss, und einfach nur vor der Ausgabe eine entsprechende Anzahl 
an Leerzeichen pro Zeile ausgeben muss (weil das std::copy eine einzelne 
Zeile ausgibt).

von Dennis (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wir wissen ja auch nicht, was in seinem Beispiel v ist, wo er herkommt,
> wie er entsteht

V ist einen Vector und ich lese die auch als Vector.
Ich will auf jeden Element des Vectors zugreifen und entsprechen 
leerzeichen anhängen.

von Dennis (Gast)


Lesenswert?

Was sagt ihr, wenn ich die Zahlen als Blöcke betrachte?

von Karl H. (kbuchegg)


Lesenswert?

Dennis schrieb:
> Karl Heinz Buchegger schrieb:
>> Wir wissen ja auch nicht, was in seinem Beispiel v ist, wo er herkommt,
>> wie er entsteht
>
> V ist einen Vector und ich lese die auch als Vector.
> Ich will auf jeden Element des Vectors zugreifen und entsprechen
> leerzeichen anhängen.

Schön.
Und was hindert dich jetzt daran, vor dem
1
copy(v.begin(),v.end(),ostream_iterator<int>(datei," "));

eine entsprechende (möglicherweise aus der Anzahl der Elemente im Vector 
errechnete) Anzahl an Leerzeichen auszugeben, so dass die nachfolgende 
Ausgabe der Vector-Elemente eben nicht am linken Rand anfängt, sondern 
entsprechend eingerückt?
Vielleicht gibts ja dafür wirklich einen guten Grund.

von Dennis (Gast)


Lesenswert?

Es tut mir leid, wenn ich euch störe mit meiner anfängliche Probleme 
aber ich bin einfach anfänger was C++ betrifft und möchte mich 
verbessern deswegen frage ich nach, wenn es lästig manchmal....

Problem ist ich lese Daten aus einem txtdatei dann überprüfe ich die und 
schreibe ich das Ergebnis in einen andere txtDatei, aber das Output muss 
formatiert werden.

Die Zahlen varieren sich zwischen einen stellige und drei stellige Zahl.
Damit es richtig formatiert werden (Pyramid),müssen die Zahlen als 
Blöcke betrachtet werden.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Ausgabe der Vector-Elemente eben nicht am linken Rand anfängt, sondern
> entsprechend eingerückt?
> Vielleicht gibts ja dafür wirklich einen guten Grund.


Derartige Spielchen mit Formatierungen sind eigentlich Dinge, die nach 
der allerersten Unterrichtsstunde C-Programmierung zum Standardrepertoir 
von Hausaufgaben gehört. Mehr als (in C) printf, ein paar for-Schleifen 
und die ersten Variablen braucht man nämlich dazu nicht, um eine 
Pyramide aus Sternchen ausgeben zu können. Bei dir sinds eben nicht 
Sternchen sondern die Werte in einem Vektor, und um die Werte 
auszugebenn benutzt du einen std::copy (was ja auch ok ist). Was 
allerdings nicht heißt, dass man die vorhergehenden Leerzeichen in einer 
Zeile nicht mittels einer banalen for-Schleife ausgeben kann - es sei 
denn, deine Hausaufgaben sagen was anderes.

1
3 5 6 7
^ kein Leerzeichen
1
 4 9 1
^ 1 Leerzeichen
1
  3 11
^ 2 Leerzeichen
1
   8
^ 3 Leerzeichen

In Summe
1
3 5 6 7
2
 4 9 1
3
  3 11
4
   8
sieht es wohl so aus, dass bei jeder folgenden Zeile einfach 1 
Leerzeichen mehr ausgegeben werden muss, ehe dann die eigentlichen Daten 
aus dem Vector kommen und die Zeile mit einem \n abgeschlossen wird.
1
  for( i = 0; i < n; i++ )
2
    cout << ' ';

gibt n Stück Leerzeichen aus.
Und dein n wird mit jeder Zeile die ausgegeben wurde um 1 größer.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:

>
1
>   for( i = 0; i < n; i++ )
2
>     cout << ' ';
3
>
>
> gibt n Stück Leerzeichen aus.
> Und dein n wird mit jeder Zeile die ausgegeben wurde um 1 größer.

Eine andere Möglichkeit besteht in der Verwendung eines std::string. 
Dort gibt es einen Konstruktor
1
string (size_t n, char c);
der einen entsprechenden String der Länge n, gefüllt mit dem Zeichen c 
erzeugt.

Ein
1
   cout << std::string( n, ' ' );
gibt also ebenfalls eine entsprechende Anzahl n an Leerzeichen aus.

von Dennis (Gast)


Lesenswert?

Es klappt nicht.....
wenn ich so einen ausgabe habe:
1
1   5   55   70   110   119   130   150   175   230   243   249 (n)
2
  39   22   15   3   46   2   7   56   4   25   13   30   44    (n-1)
3
     104   109   91   80   81   90   79  81   90   79   20      (n-2)
4
          185   199   170   166   147   148   190   155   158
5
               156   183   181   189   198   150   157   144   136
--> das ist aber keine richtige Pyramid
ich muss irgendwie anders vorgehen?
....

von Dennis (Gast)


Lesenswert?

ich entschuldige bei allen, die ich bei denen Kopfschmerzen verusacht 
habe...
Sorry ...

von Karl H. (kbuchegg)


Lesenswert?

Dennis schrieb:

> --> das ist aber keine richtige Pyramid
> ich muss irgendwie anders vorgehen?
> ....

Ja.
Analysieren, was das Problem ist.
Das Problem ist, dass in der Ausgabe "1" nun mal textuell gesehen kürzer 
ist als "150".
Also wäre es eine ziemlich gut Idee, wenn die Textrepräsentierungen 
ALLER Zahlen erst mal gleich lang sind. Da deine größten Zahlen 
3-stellig sind, ist es daher eine ziemlich gute Idee, dafür zu sorgen, 
dass ausnahmslos alle Zahlenausgaben 3-stellig gemacht werden.

Sieht man ja auch hier, in deinem initialen Beispiel
1
3 5 6 7 
2
 4 9 1
3
  3 11
4
   8
Die dritte Zeile passt nicht so recht. Woran liegt es? Es liegt daran, 
dass 11 eine Stell mehr braucht, weil es eine 2-stellige Zahl ist. Würde 
da 2 stehen (einstellige Zahl)
1
3 5 6 7 
2
 4 9 1
3
  3 2
4
   8
wärs wieder perfekt.
Nun ist das in diesem Beispiel trivial zu sehen, weil da nur eine 
einzige 2-stellige Zahl vorkommt. Sobald das aber mehrere pro Zeile 
sind, verschlimmert sich die Sache weiter.

Programmieren heißt auch Beispiele studieren, Beispiele analysieren, 
Problemkreise aus den Beispielen ableiten. Und sich dann natürlich für 
diese Problemkreise Lösungsmöglichkeiten überlegen.
Und: ganz wichtig - die Problemkreise, die du selbst nicht lösen kannst, 
auch kommunizieren können.

von Kaj (Gast)


Lesenswert?

Dennis schrieb:
> --> das ist aber keine richtige Pyramid

Das liegt an der "breite" der Zahlen.
Schau dir mal die Pyramide an, von oben nach unten...
in Zeile drei (beginnend mit 104) hast du mehrere Zahlen mit nur zwei 
Ziffern, die Zeile danach hat aber nur Zahlen mit drei Ziffern...
drei Ziffern brauchen logischer Weise mehr platz als zwei ziffern, und 
deswegen wird es keine richtige pyramide.
Du solltest die Formatierung nicht mit Leerzeichen sondern mit einer 
"festen breite" machen, dafür gibt es auch formatierungs möglichkeiten 
im printf()-Style.

Oder um dein Problem anders zu beschreiben:
du machst zwei Leerzeichen + drei Ziffern + zwei Leerzeichen = sieben 
Zeichen
zwei Leerzeichen + zwei Ziffern + zwei Leerzeichen = sechs Zeichen

Was du brauchst:
Nehme den Platz für (als Beispiel) acht zeichen (feste breite) und in 
diesen bereich kommen die Ziffern, also:
Platz für acht Zeichen - Anzahl Ziffern / 2 = Anzahl "Leerzeichen" 
rechts und Links von der Zahl.

Grüße

von Dennis (Gast)


Lesenswert?

Wie kann ich bitte 1 oder stellige Zahl zu 3 stellige zahl machen?

von Robert L. (lrlr)


Lesenswert?

indem du 2 Nullen oder 2 Leerzeichen voranstellst..

von Karl H. (kbuchegg)


Lesenswert?


von Dennis (Gast)


Lesenswert?

datei<<setfill('0')<<setw(3);
copy(v.begin(),v.end(),ostream_iterator<int>(datei,"   "));
datei<<"\n";

--> ergebnis:
1
000 1 33 83 104 110 124 163 185 
2
001 32 50 21 6 14 39 22 15 3 46 
3
033 82

0 wird nur am anfang der Zeile zugefügt

von Karl H. (kbuchegg)


Lesenswert?

Dennis schrieb:
> datei<<setfill('0')<<setw(3);
> copy(v.begin(),v.end(),ostream_iterator<int>(datei,"   "));
> datei<<"\n";
>
> --> ergebnis:
>
1
> 000 1 33 83 104 110 124 163 185
2
> 001 32 50 21 6 14 39 22 15 3 46
3
> 033 82
4
>
>
> 0 wird nur am anfang der Zeile zugefügt

Falsche Schlussfolgerung
1
#include <iostream>
2
#include <iomanip>
3
4
using namespace std;
5
6
int main()
7
{
8
  cout << setw( 3 ) << setfill( '0' ) << 10 << " " << 20 << " " << 30 << "\n";
9
  cout << 10 << " " <<  setw( 3 ) << setfill( '0' ) << 20 << " " << 30 << "\n";
10
  cout << 10 << " " << 20 << " " << setw( 3 ) << setfill( '0' ) << 30 << "\n";
11
12
}

und das Ergebnis sieht so aus:
1
010 20 30
2
10 020 30
3
10 20 030

also: 'am Anfang der Zeile' stimmt schon mal nicht.


Allerdings
http://stackoverflow.com/questions/405039/permanent-stdsetw
http://stackoverflow.com/questions/7248627/setting-width-in-c-output-stream
http://stackoverflow.com/questions/1532640/which-iomanip-manipulators-are-sticky
http://faculty.cs.niu.edu/~mcmahon/CS241/c241man/node83.html

Auch wenn es dir nicht gefallen wird: Ich würde das std::copy durch eine 
hundsordinäre Iterator-Schleife ersetzen. Dann ist es trvial vor der 
Ausgabe jedes Wertes sowohl die Leerzeichen einzufügen als auch die 
width jedesmal neu zu setzen.

von Dennis (Gast)


Lesenswert?

Ich habe das Problem so gelöst:

datei.fill('0');
for(size_t i= 0;i<v.size();++i)
{
 datei.width(3);
 datei<<v[i]<< "   ";
}


jetzt sind alle zahlen 3 stellig
nur ausgabe formatierung (pyramid Form)oh jeh

von Marcus (Gast)


Lesenswert?

Hi Dennis,

Gut weiter so .....
Jede hat klein angefangen nur nicht aufgeben

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.