c++ Einmaleins mit Matrix erstellen

Sascha Moser

Grünschnabel
Hallo zusammen,

ich studiere nun im 2. Semester Maschinenbau und nun haben wir das Fach Informatik, für das wir 3 Testate schreiben müssen.
Ich habe noch nie mit c++ programmiert.

Ich soll nun ein c Programm schreiben dass eine Zahl zwischen 1 und 10 einliest und dann eine 1x1 Tabelle erstellt.
In der Vorlesung hatten wir bisher Kontrollstrukturen usw. Jedoch noch nichts mit Matrizen oder dergleichen.
Das Skript ist hierzu leider auch nicht unbedingt hilfreich.

Wie gehe ich jetzt hier vor?
Wie kann ich eine Matrix definieren und wie sieht dass dann mit den werten aus?

Im Grunde hätte ich das jetzt mit 2 for-Schleifen gelöst.

Hier ist mal mein bisheriger Code:

Code:
/*Semesterarbeit - Sascha Heigenmoser*/
/*Aufgabe 2.10 - Einmaleins*/

#include <stdio.h>


int main(void)
{
	int zahl;
	int Zähler;
	

do
{
	printf("Geben Sie Ihren Betrag in EUR ein\n");
	scanf("%d", &zahl);
}   
while ( (zahl<=0)||(zahl>10));



return 0;
}


Wäre echt super wenn ihr mir da helfen könntet.
Will die Funktion auf jeden Fall verstehen.

Vielen Dank

Sascha
 
Hi und Willkommen bei tutorials.de,

versteh die Aufgabe leider nicht ganz.

Unter einer 1x1-Tabelle versteh ich sowas:
http://www.profi-l.info/web/sites/default/files/2006-01-12-mathbuch_tabelle.jpg
(vom Prinzip her, eben wertmäßig im Programm).
Aber was hat die Zahl von 1-10 am Anfang damit zu tun?

Generell, wieviel sagen dir...
Array, mehrdimensionales Array, malloc
(nicht sicher ob malloc überhaupt nötig ist, kommt auf die Aufgabe drauf an)

PS: Weil du von C und C++ redest, womit soll das Programm sein?
 
Hallo Shell,

vielen Dank für deine Rückmeldung.

Das Programm soll in form einer Konsolenanwendung realisiert werden.
Der Benutzer soll eine Zahl von 1 bis 10 eingeben und die Abfrage soll so lange erfolgen bis die richtige Zahl im Intervall eingegeben wurde, darum die "do while Schleife" am Anfang.
dann soll eben anhand der eingegebenen Zahl die 1x1 Tabelle erstellt werden.
Zusätzlich dazu sollen dann jeweils alle Vertikalen und Horizontalen Spalten addiert werden.

ich habe mal die Aufgabenstellung angefügt als Bild.

Aufgabenstellung.JPG

Das mit der 1x1 Tabelle ist korrekt
Leider habe ich von Arrays und dergleichen noch nichts gehört.

Gibt es denn nicht die Möglichkeit eine Tabelle bzw. leere Matrix zu definieren und dann die werte mit 2 verschachtelten Schleifen zu berechnen und auszugeben?

Vielen Dank schon mal

Sascha
 
Jetzt versteh ich den Zusammenhang.

Zu "Tabelle/Matrix definieren": Sicher gibt es die Möglichkeit.
Aber sowas wie "Tabelle" (wenn man nicht grad eine grafische Tabelle meint)
ist ein zweidimensionales Array.
Noch nie mit sowas gearbeitet?
C++:
int array[10][10];
...
//oder
int *array;
array = (int *)malloc(10*sizeof(int));
...
//oder
int *array;
array = new int[10];
Wenn außer der Ausgabe/Summierung sonst nichts ist kommt man auch ohne dem aus,
nur ob das im Sinn vom Lehrer ist?

Übrigens weiß ich noch immer nicht, ob es jetzt C oder C++ sein soll.
 
Hallo,

also wir arbeiten in C++ :)

Nein leider nicht, bisher hatten wir gerade mal Datentypen und Kontrollstrukturen.
So wie ich das verstehe kommt das erst im nächsten Semester, aber um den Lerneffekt zu erhöhen soll jeder studierende selber mal schauen wie er das hin bekommt.

um das Richtig zu verstehen, mit der Zeile:
Code:
 int array[10][10];
definiert man also eine Tabelle.
Diese ist doch aber jetzt "fest" und nicht Dynamisch oder? also dass sie sich dann, je nach dem welche Zahl der Benutzer eingiebt, von der Größe her anpasst? Also dann in etwa so:
Code:
int array[Z][S];
 
Wenn ihr mit C++ direkt anfangt sollte im Anfangspost vllt. cout und cin
statt printf und scanf verwendet werden.
Wenn ihr von count und cin noch nie was gehört habt,
aber printf/scanf beigebracht bekommen habt, sollte es wohl eher C sein :)

Zu den Arrays: [10][10] wäre Fixgröße, stimmt.
Variable Größen sind mit malloc und free möglich, aber bei zweidimensionalen "Tabellen"
(statt nur einer einzige Zeile beliebiger Länge) wirds etwas kompliziert,
vor allem fürs Verständnis.
Aber wenn ihr sowas im Unterricht noch nicht gemacht habt wird sich wohl keiner beschweren,
wenn man es ohne löst (hab mir nur gedacht, dass der Lehrer evt. eine Arraylösung erwartet
und was Anderes nicht akzeptiert wird)

Kurz noch was Anderes vorm Eigentlichen:
Im Code des Anfangsposts gibts ein int Zähler.
Deutsche Umlaute sollten/müssen in Variablennamen etc. vermieden werden
(womit kompiliert ihr denn, dass das akzeptiert wird?)

So, das Wesentliche: Zuerst mal die Tabelle ohne Summen
Die Zahl zw. 1-10 hast du erfolgreich eingelesen und auf Gültigkeit geprüft.
Für die Tabelle reichen, wie du schon schreibst, zwei for-Schleifen ineinander.
Die innere ist eine Zeile, die Äußere eben alle.
C++:
int i, j; //zwei ints mehr zum Zählen
for(i = 1; i <= zahl; i++)
{
    for(j = 1; j <= zahl; j++)
    {
        // i*j ausgeben
        printf("%d", i*j);
    }
    printf("\n"); //Eine Zeile durch, Zeilenwechsel
}
Wenn man das so ausführt ist es allerdings ein Durcheinander bei der Ausgabe,
weil die Zahlen nicht so schön tabellarisch untereinander stehen wie beim Bild.
Wenn man das %d vom printf mit zB. %4d ersetzt sagt man dem printf,
pro Zahl min. 4 Zeichen Platz zu brauchen (der Rest wird eben aufgefüllt mit Leerzeichen)

Denke, damit wäre die summenlose Tabelle fertig :)

Zu den Summen:
Die Zeilensummen rechts daneben könnte (nur könnte) man machen,
in dem man eine weitere Variable hat, am Zeilenanfang auf 0,
und den aktuellen Wert immer dazuaddiert.
Am Ende könnte man das eben als Summe ausgeben.

Die Spaltensummen wären mit der Einfach-Addiermethode aber ein Problem.
Die Tabelle wird ja zeilenmäßig durchlaufen.
Erste zeile von links nach rechts, zweite Zeile von links nach rechts...
zu dem Punkt, wo die Spaltensummen ausgegeben werden kommt man erst ganz am Schluss.
Man müsste also pro Spalte eine Variable zum Summieren bereithalten,
weil die ganzen Werte während der ganzen Tabelle vorhanden bleiben müssen.
Da die Spaltenanzahl ja änderbar ist etc....damit wäre man wieder bei den Arrays.
Also so nicht.

Als arraylose Möglichkeit bleibt eigentlich nur. die am Ende extra zusammenzurechnen
(und wenn man die schon irgendwie berechnet
kann man mit den Zeilensummen gleich das Selbe machen)

Zum Berechnen könnte man wieder eine eigene Schleife zum Summieren machen
Möglich, aber geht einfacher:
Sowas wie 1+2+3+4+5+6... kann man mit einer kleinen Formel berechnen (Gaußsumme):
(zahl+1)*zahl/2
(wobei mit zahl die Variable gemeint ist, also die höchste Zahl in der Summierung)

Einmal am Anfang ausrechnen, zB.in die Variable summe.
Die SUmme der ersten Zeile oder Spalte ist dann 1*summe, zweite Zeile/Spalte 2*summe...
mit der Schleifenvariable kombinieren, ausgeben, fertig.
 
Hallo Shell,

vielen Dank für diese ausführliche Nachricht.
Im Prinzip kann ich das komplette Programm mit for-Schleifen erschlagen.

also die orintf und scanf Anweisungen wurden uns als c++ Anweisungen verkauft :D
Programmieren tun wir auch in Visual C++ Express. Ist ja im Prinzip auch egal.
Cout und cin sind mir aber auch bekannt (Lehrbücher sei Dank :D)

Aber um auf das Thema zurück zu kommen.

Meine for-Schleifen sahen genau so aus wie deine, jedoch macht mir die Speicherung der Werte in einen Array echt Schwierigkeiten.

Ob jetzt der Prof. ausdrücklich Arrays verlangt kann ich gar nicht 100% sagen, aber ich denke er legt da großen Wert drauf und ich würds auch gern selber verstehen.

Mein Grundgedanke war jetzt, wenn ich die 2 for-Schleifen durchlaufen lasse, dass ich dann jeder "Zelle" in meinem Array den den richtigen Wert zuweise.

Die Summe der Horizontalen und Vertikalen kann ich ja dann auch mit ner entsprechenden Zeile auslesen bzw. berechnen lassen.

Wie greife ich denn im Allgemeinen auf eine Matrix/Array zu? und wie kann ich Werte zuweisen?

Wär super wenn du mir das evtl, sofern es möglich ist, in nem "Crash Kurs" erklären könntest :D

Besten Dank schon mal
 
@printf, scanf, C++:
Genaugenommen sind es (auch) C++-Anweisungen.

C++ ist (bis auf ein paar feine Ausnahmen) eine Obermenge von C,
also C mit neuen zuätzlichen Sprachkonstrukten (wie Klassen),
ohne aber das Bestehende zu ändern
if, for, while etc. sind in C und C++ komplett gleich, printf aus C funktioniert auch in C++...

Für Dinge wie Konsolenausgabe sind bei C++ weitere Funktionen etc. dazugekommen
(die die neuen C++-Sachen wirklich ausnutzen) (schon in C ist printf bei weitem nicht das Einzige)
cout wäre sowas. Benutzt die Streamklassen von C++, die es in C nicht gibt, daher C-untauglich,
gibt aber auch nicht bessere Konsolenausgaben als printf.

"Problem" der Sache ist, dass es für viele zum guten Ton gehört,
konsequent nur C oder nur neue C++-Möglichkeiten zu verwenden
(falls man die Wahl hat natürlich)
---
Attays eindimensional, fixe Größe
sind vom Prinzip her nur mehrere int/float/etc. in einem Variablennamen, durchnummeriert
Vergleichbar mit einer Tabellenzeile.

Anlegen, für zB. 100 int, Variablenname arr:
C++:
int arr[100];
(Durchmischen von verschiedenen Variablentypen ist so direkt nicht möglich.
Ein Array hat nur int oder nur float oder ...)

Zugriff auf die Werte geht prinzipiell wie mit einfachen int,
nur immer [] Klammern mit der Nummer dazwischen dabei
C++:
arr[27] = 0;
arr[35] = 1;
if(arr[27] == 1)
    printf("Kaputt :/");

Was daran wichtig ist: Die Nummern beginnen bei 0.
Beim Anlegen gibt man die Anzahl der int an, die man haben will (nicht die höchste Nummer)
Und für Anzahl 4 wären die zulässigen Nummern [0], [1], [2] und [3]. Genau 4 Stück.
[4] gibts nicht (!). Verwenden davon liefert aber (meistens) keine Fehlermeldung,
sondern macht irgendwas seltsames unvorhersehbares.
Eventuell passiert gar nichts beim ersten Programmdurchlauf,
und beim zweiten bekommt man ein falsches Ergebnis, und beim dritten einen Absturz...
bei sowas das Problem finden kann uU. lang dauern
Beim arr[100] gehen die Nummern also von [0] bis [99]

Falls man das Array nach und nach "voller" macht muss man irgendwo
(zB. einem eigenen (separaten) int) mitspeichern, wie viel Plätze schon verbraucht sind.
Genau wie bei einzelnen int kann man beim Array nämlich nicht prüfen, ob man schon einen Wert in Nummer xy gespeichert hat. Da steht immer irgendein Wert drin,
nur ob es einer ist, den man da haben will oder einer, der von Anfang an da war...
---
Fixe Arrays mehrdimensional
Während oben eine "Tabellenzeile" war, ist jetzt hier ein Array aus Zeilen = ganze Tabelle
Einfach, indem man noch eine [] mit Größe dazutut:
C++:
int tabelle[4][10];
Macht 4 Zeilen mit je 10 int
Zeile 0-3, jede davon hat Element 0-9
C++:
tabelle[0][0] = 1*1;
tabelle[2][2] = 3*3;
tabelle[3][9] = 4*10;
...
Was zwar oben nicht steht, aber natürlich auch bei eindim. Arrays geht:
Die Indexnummern in den [] können natürlich auch von Variablen kommen.
C++:
int i, j;
for(...)
    tabelle[i][j] = (i+1)*(j+1); //+1 weil i von 0 losgeht, und man ja ein 1x1 will :)
...
Nur die Größe beim Anlegen muss eine fixe Zahl sein (variabel kommt unten gleich)

Man kann auch drei-, vier...dimensionale Array machen
C++:
int bla[2][2][2];
float blub[3][3][3][3][3][3][3];
...
Nur wie man sich das bildlich vorstellen kann (2dim = Tabelle) ...das hier gar nicht.
---
Eindimensional, variable Länge
Unterscheidet sich "nur" im Anlegen, verwendet wird es dann komplett gleich

a) Variable selbst
C++:
int *arr;
Ohne [größe], dafür der Stern.
Kann so noch nicht verwendet werden

b)
Eigentliches Anlegen
C++:
arr = (int *)malloc(8 * sizeof(int));
Die zwei "int" (und das bei Schritt a) können natürlich durch float etc. ersetzt werden
Die Größe ist hier 8, also 8 Stück int für arr.
Schaut hier zwar wieder fix aus, kann aber genausogut ein Variablenname dastehen,
von dem dann der Wert genommen wird.

c)
Jetzt muss überprüft werden, ob das Anlegen erfolgreich war.
Kann vorkommen, dass es nicht passt, zB. wenn man mehr anlegen wollte,
als der Computer speichern kann.
C++:
if(arr == NULL)
{
    //Fehler
    //zB. Ausgeben und Programm beenden
}

d)
Normal verwenden
arr[0], arr[9]...

e)
Und noch eine Neuheit: So angelegte dynamische Arrays müssen auch
wieder weggeräumt werden, geht nicht automatisch wie bei den Fixen.
Irgendwo zB. am Programamende, wenn man das Array jedenfalls nicht mehr braucht:
C++:
free(arr);

Eine Variable wie in a) kann auch mehrere malloc-free-Durchgänge haben
(hintereinander, nicht gleichzeitig)
---
Und mehrdimensionale dynamische Arrays:
(in "Höhe" und "Breite" der Tabelle beides variabel) (sonst einfacher):
Anlegen mit zwei (oder mehr) * statt einem.

Und die malloc-Sache wird schleifenlastig:
Zuerst legt man ein Array aus noch nicht angelegten Arrays (Zeilen) an,
von denen dan jedes in einer Schleife wieder ein malloc erfahren muss.
Ebenso beim free.

Was noch "schöner" ist: Wenn eins der mallocs daneben geht (aus Speichermangel etc.)
muss man die bisher allokierten Sachen noch freen.
Nur genau die, für die es schon geklappt hat.

Deswegen einfach mal Code.
C++:
int zeilenanzahl, spaltenanzahl; //Werte geben, dann geht der Rest ohne Änderungen

int i; //Für Schleife

//Variable
int **array;


//Anlegen
array = (int **)malloc(zeilenanzahl * sizeof(int *));
if(array == NULL) {
    printf("Fehler\n");
    return; //Programmende
}

for(i = 0; i < zeilenanzahl; i++)
{
    array[i] = (int *)malloc(spaltenanzahl * sizeof(int));
    if(array[i] == NULL) //Bisher angelegte Zeilen und Ganzes löschen
    {
         for(--i; i >= 0; i--)
             free(array[i]);
         free(array);
         printf("Fehler\n");
         return;
    }
}


//VERWENDEN
//array[..][...]


//Löschen
for(i = 0; i < zeilenanzahl; i++)
    free(array[i]);
free(array);
---
So, für Genaueres leider grad keine Zeit (sowieso schon wieder so lang geworden :)),
speziellere Erklärungen gerne später, wenn Fragen sind.
Sonst steht hier in Kap. 11, 12 und 14 auch recht viel:
http://openbook.galileocomputing.de/c_von_a_bis_z/
(auch die anderen Kapitel sind nicht schlecht :))
 
Hallo shell,

entschuldige bitte die späte Rückmeldung.
Erst mal besten Dank für deine ausführliche Erklärung, hat mir schon sehr geholfen.
Ich habe jetzt auch noch mal mit meinem Prof gesprochen und wir hatten auch nun endlich das Thema Arrays! :D
Zwar war das Thema nur auf 2 Vorlesungen beschränkt, dennoch habe ich jetzt meine Tabelle soweit hinbekommen ;-)

Sogar ohne Dynamische Arrays! ;)

Nur stehe ich jetzt vor einem weiteren bzw. neuen Problem, und zwar die Spalten und Zeilensummen.
Ich bekomme es ums verrecken nicht hin.

zuerst speichere ich meine berechneten Tabellenwerte in das entsprechende Array (mit 2 verschachtelten For-Schleifen) und gebe diese wieder mit 2 verschachtelten for-Schleifen aus. In diesem Schritt habe ich versucht die Zeilenwerte zu berechnen und auszugeben, jedoch ohne erfolg, die Werte stimmen einfach nicht :(

hier mal mein Code



Code:
# include <stdio.h>

int tabelle [11][11];
int zahl;

int main (void)
{
	do
	{
	printf("Einmaleinstabelle\n");
	printf("Geben Sie eine Zahl zwischen 1 und 10 ein\n");
	scanf("%d", & zahl);
	}
	while ((zahl <= 0)||(zahl > 10)) ;
	printf("Einmaleinstabelle bis: %d\n", zahl);

	// Werte berechnen und in Tabelle speichern
	int i, j;
	for (i = 1; i <= zahl; i++)
	{
		for (j = 1; j <= zahl; j++)
		{
			tabelle[i][j] = i*j;
		}
	}

	
	//Tabelle Ausgeben
	int a, b, colsum = 0;
	for (a=1; a<=zahl; a++)
	{
		for(b=1; b<=zahl; b++)
		{
			printf("%4d", tabelle[a][b]);
			colsum += tabelle[a][b];
		}
				
	printf("|");
	printf("%d", colsum);
		}
	printf("------------------------------------------\n");

	return 0;
}

was mache ich falsch? Liegt es vllt daran, dass meine int variablen a und b bei 1 beginnen?

viele Grüße

Sascha
 
Hallo,
du solltest nachdem du die Zeilensumme berechnet hast auch deine Variable wieder auf 0 setzen.
Sonst addierst du nur laufend auf. Auch solltest du nach der Ausgabe der Zeilensumme ein "\n" setzen, damit die nächste Ausgabe auch in der nächsten Zeile landet.
Ansonsten funktioniert das Programm bei mir.

Grüße
 
Zurück