Guten Abend!
Kann mir bitte jemand den folgenden Quelltext für eine Parity-Funktion
in C, mit verständlichen Worten und Schritt für Schritt erklären? Ich
bin noch ziemlicher Anfänger und bin in C noch extem unsicher.
Ich bedanke mich schon im Voraus für eine hilfreiche Antwort!!!
Grüße
Dominik
Quelltext:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
unsigned char data=0x7F;
unsigned char mask= 0x01;
unsigned char counter= 0;
unsigned char i;
for (i= 0; i< 7; i++)
{
if(mask&data)
counter++;
mask<<=1;
}
if(counter%2)
data|=(1<<7);
printf("counter=%d, data=0x%x\n", counter, data);
system("pause");
return 0;
}
Dominik M. schrieb:> Kann mir bitte jemand den folgenden Quelltext für eine Parity-Funktion> in C, mit verständlichen Worten und Schritt für Schritt erklären? Ich> bin noch ziemlicher Anfänger und bin in C noch extem unsicher.
Kannst du ein bischen konkreter werden.
Welche Teile verstehst du und welche Teile verstehst du nicht.
AN und für sich ist die Funktionalität nicht schwer zu verstehen.
Die einzig 'ungewöhnlichen Funktionen' die du mglw. nicht kennst sind &
und <<=
das erste: & ist eine binäre verundung. dabei werden einfach die bits
an den jeweils korrespondierenden Stellen einer UND Operation unterzogen
bit 1 bit 2 ergebnis
---------------------------
0 0 0
0 1 0
1 0 0
1 1 1
das Ergebnisbit ist nur dann 1, wenn bit1 UND bit2 1 sind.
Hast du also 2 Zahlen in Binärschreibweise
Zahl1 10001011
Zahl2 00011010
dann wendest du einfach die UND Operation auf jede Spalte an. Das
Ergebnis ist
Ergebnis 00001010
und die andere Operation ist <<=
Die besteht aus 2 Teilen, so wie auch += oder *=
Auf der einen Seite die Operation selber und auf der anderen Seite dem
=, welche die Operation als Kurzschreibweise nach dem Muster
a op= b <===> a = a op b
kennzeichnet
(op ist die Operation, also bei +: a += b <==> a = a + b)
dh. die eigentliche Frage lautet: was macht <<
Und das macht genau das, wonach es aussieht: es verschiebt die
Binärrepresentierung der Bits einer Zahl nach links:
a << b verschiebt das Bitmuster von a um b Stellen nach links wobei
von rechts 0 Bits nachrücken
10001011 << 1 ergibt also 00010110
10001011 << 2 ergibt also 00101100
10001011 << 3 ergibt also 01011000
10001011 << 4 ergibt also 10110000
10001011 << 5 ergibt also 01100000
usw.
% ist die Modulo Operation, welche den Rest berechnet. So wie in: Eine
Muter hat 14 Äpfel und 3 Kinder. Wenn jedes Kind gleich viele ganze
Äpfel bekommt, wieviele bleiben der Mutter übrig
14 % 3 ----> 2
Der Mutter bleiben 2 Äpfel übrig.
Ach. Du kommt ja noch ein ODER vor.
a |= b ist wieder die Kurzschreibweise für a = a | b
und ein binäres ODER funktionert wie ein binäres UND, nur halt mit ODER
bit 1 bit 2 ergebnis
----------------------------
0 0 0
0 1 1
1 0 1
1 1 1
Das ergebnisbit ist genau dann 1, wenn enweder bit1 ODER bit2 ODER beide
1 sind.
Mit den Zutaten solltest du das selbst entschlüsseln können. Hilfreich
ist auch in einem Debugger den Code durchzusteppen und deine Analysen
mit dem zu vergleichen, das dein Computer tatsächlich macht.
Dominik M. schrieb:> Ich schreibe mit dem Programm Dev-C++.
Hast du auch die neuste Version?
Im Sommer sind nach 6 Jahren Stillstand ein paar neue Versionen
rausgekommen.
Dominik M. schrieb:> Ich weiß aber nicht ob dieses> einen Debugger beinhaltet.
Auf dem Bild auf Wikipedia kann man ein Debug-Menü sehen.
In mask ist nur ein Bit gesetzt (am Anfang das erste). Diese Maske wird
bitweise verundet mit dem Datenbyte data (wie oben beschrieben). Wenn
das Ergebnis ungleich 0 ist, ist das entsprechende Bit in data gesetzt.
Danach schiebst du das gesetzte Bit in mask um eine Stelle weiter.
Guten Abend,
ich habe den Quellcode (für mich) etwas verständlicher gestaltet. Was
ist die eigentliche Aufgabe dieser PARITY-Funktion (Vergleich-Funktion)?
Die gesetzten Bits werden gezählt und wenn dabei eine ungerade Anzahl
heraus kommt, wird das achte Bit gesetzt um eine gerade Anzahl von
gesetzten Bits zu bekommen!?
Das heißt es werden nur 7 Bits kontrolliert und das achte Bit als
Kontrollbit verwendet!?
Richtig? Für was soll das gut sein?
Sorry für die etwas Laienhafte Schreibweise aber ich bin noch fast ganz
am Anfang. :-)
//PARITY - Funktion
#include <stdio.h>
int main(void)
{
unsigned char data=0x46;
unsigned char mask=0x01;
unsigned char counter=0;
unsigned char i;
for (i=0; i<7; i++)
{
if(mask&data)
{
counter++;
}
mask=mask<<1;
}
if(counter%2) //erfüllt,wenn counter durch 2 ohne Rest nicht teilar ist
{
data=data|(1<<7); //An der 7 Stelle von data, wird ein Bit gesetzt
}
printf("counter=%d, data=0x%x\n\n", counter, data);
system("pause");
return 0;
}
naja, du überträgst halt irgendwelche Daten, und zusätzlich zu den Daten
überträgst du, daß die Quersumme dieser Daten grade (oder ungrade) ist.
Der Empfänger liest die Daten ein, bildet sich selber die Quersaumme,
und vergleicht die selbst ermittelte Quersumme mit der Übermittelten
Quersumme.
Sollte es Abweichungen geben, so ist das ein Indiz frü einen Fehler.
Genauer: Wahrscheinlich ist ein Einzelfehler aufgetreten.
Die Paritätsprüfung ist allerdings nur ein mäßig guter Prüfmechanismus.
Wenn nämlich 2 Bit "kippen" (als anstelle einer 0 eine 1 übertragen
wird, bzw. anstelle einer 1 eine 0), dann siehst du das mit dieser
Quersumme halt NICHT mehr. Ein Doppelfehler wird also nicht erkannt.
Wenn du eine sehr sichere Datensituation haben möchtest, mußt du dann zu
ECC (Error correction code) greifen.
ALLERDINGS ist das eine Frage des Aufwandes: In mäßig moderaten
Umgebungen ist möglicherweise schon das Auftreten eines Einzelfehles
recht unwahrscheinlich, und ein simples ""Parity check" reicht schon
aus.
Ich merk gerade, dass ich deine (Dominik M.) Frage falsch verstanden
habe. Du wolltest wissen "was mach ich jetzt mit dieser Paritätsinfo".
Sorry für das Missverständnis.
@ Karl Heinz Buchegger
Das ist doch kein Problem. Ich bin sehr froh, dass ich Hilfe von euch
bekomme!
@ Forum
Ich werde jetzt versuchen, diese Sender- und Empfängerkontrolle zu
programmieren. Bin mir sehr unsicher, wie ich anfangen soll. Ich werde
versuchen, es mit einer Sender- und Empfängerfunktion umzusetzen.
Teile deine jetzige Funktionalität in 2 Teile auf:
Eine Funktion die die Parität berechnet.
Eine 2-te Funktion, die für eine gerade Parität sorgt.
Der Sender sendet dann immer Datenbytes die eine gerade Parität haben.
Der Empfänger benutzt die erste Funktion um die Parität des empfangenen
Bytes festzustellen. Die muss daher logischerweise gerade sein, denn der
Sender hat ja dafür gesorgt, dass das so ist. Wenn es je vorkommt, dass
der Empfänger ein Byte mit ungerader Parität empfängt, gab es
offensichtlich einen Übertragungsfehler.
Die Umkehrung gilt allerdings nicht (wie WV schon ausgeführt hat). Nur
weil die Parität stimmt, bedeutet das nicht, dass es keinen
Übertragungsfehler gegeben hat.
Ich habe ein Programm mit Sender- und Empfängerfunktion geschrieben. An
die Senderfunktion, wird eine Hexzahl übergeben. In dieser wird die
Hexzahl auf "gerade" oder "undgerade" geprüft. Wenn "ungerade" dann wir
ein PARITY - Bit an der 7 Stelle gesetzt. Diese neue Hexzahl mit PARITY
- Bit, wird jetzt an die Empfängerfunktion übergeben.
Wie kann ich jetzt in der Empfängerfunktion auf EVEN oder ODD prüfen?
Mein Verständnisproblem, liegt bei EVEN und ODD. Die Überprüfung auf
"gerade" oder "ungerade", funktioniert ja wie in der Senderfunktion.
//PARITY - Funktion (Sender, Empfänger)
#include<stdio.h>
/***********************************************************************
*******/
unsigned char send(unsigned char);
void receive(unsigned char);
/***********************************************************************
*******/
int main(void)
{
unsigned char data=0x07;
unsigned char y;
y=send(data);
receive(y);
system("pause");
return 0;
}
/***********************************************************************
*******/
unsigned char send(unsigned char x)
{
unsigned char mask=0x01;
unsigned char counter=0;
unsigned char i;
for(i=0; i<7; i++)
{
if(x&mask)
{
counter++;
}
mask=mask<<1;
}
if(counter%2)
{
x=x|(1<<7);
}
return x;
}
/***********************************************************************
*******/
void receive(unsigned char y)
{
printf("Die uebertragene Hexzahlt lautet: 0x%x\n\n", y);
}
/***********************************************************************
*******/
Lies dir noch mal durch, was Karl Heinz Buchegger am 15.11.2011 um
16:43 schreib.
Du brauchst also eine Funktion, die die Parität berechnet und dann 0
oder 1 zurückgibt. Die kann z.B parity() heißen.
Und dann brauchst du noch eine Funktion die eine bestimmte Parität
erzeugt.
Die kann z.B parity_even() heißen. Diese ruft parity() auf und erzeugt
immer eine Gerade Parität
In der Senderoutine rufst du parity_even() auf und in der
Empfangsroutine rufst du parity() auf. Diese muss dann als Ergebnis even
zurück geben.
Damit du mit dem empfangenen Zeichen arbeiten kannst, musst du
allerdings noch die Paritätsinformation löschen.
Dominik M. schrieb:> Wie kann ich jetzt in der Empfängerfunktion auf EVEN oder ODD prüfen?
Indem du dieselbw Parity Berechnung beim Empfänger wieder machst. Dort
muss EVEN rauskommen.
> Mein Verständnisproblem, liegt bei EVEN und ODD. Die Überprüfung auf> "gerade" oder "ungerade", funktioniert ja wie in der Senderfunktion.
EVEN <===> gerade
ODD <===> ungerade
sind einfach nur die englischen Ausdrücke dafür.
trenn dir da den Teil, der die Parity berechnet (und nur die Parity
berechnet!) in eine eigene Funktion raus und schon drängt sich die
Lösung für den Empfänger förmlich auf.
Das hat jetzt aber nichts mit C zu tun.
Das ist in anderen (prozeduralen) Programmiersprachen genau so.
Da kann es aber sein das die Unterscheidung zwischen Zeichen und Zahl
stärker ist.
Oder das du nicht so einfach an die einzelnen Bits rankommst.
Dafür ist C ein bisschen kryptischer zu schreiben.
Dominik M. schrieb:> Wenn ihr wüsstet, wie schwer für mich das Lernen von C ist*g*
Das ist schon klar.
Du musst gleichzeitig eine Programmiersprache, Algorithmen und die
"Taktik des Programmierens" lernen. Und wenn dann die Aufgabenstellung
etwas realer wird, muss man auch davon etwas verstehen (wer ein Programm
zum Fliesenlegen schreibt, muss wissen nach welchen Regeln das vor sich
geht - wie ein Fliesenleger).
Das ist nicht einfach und am Anfang stürzt alles auf dich ein. Aber es
wird mit der Zeit besser. Neben dem Beherrschen seines Handwerkszeugs
ist Erfahrung alles.
Dominik M. schrieb:> Muss die Sende-Funktion, die um das PARITY - Bit erweiterte Zahl, an die> Empfangs-Funktion senden
Ja.
Die Empfangsfunktion muss also die Parity-Information (nach dem
überprüfen) wieder raus nehmen.
Dominik M. schrieb:> oder nur das PARITY - Bit
Nur ein Bit zu übertragen gibt zuviel Overhead.
Da würde man eher eine Checksumme bilden und die dann am Schluss
übertragen.-> CRC
Ok! Es muss aber auch noch vereinbart werden, auf was anschließend
geprüft werden soll (EVEN/ODD) oder? Macht man das mit der
Präprozessoranweisung #define, welche global gesetzt wird?
Wichtig ist, dass Sender und Empfänger die selben Einstellungen
benutzen.
Ob du das jetzt im Code fest "verdrahtest" oder über #defines machst
oder über Variabeln einstellbar machst, hängt davon ab, wie viel Aufwand
du treiben willst.
Die Übermittlung der Einstellungen wird meist in gedruckter Form (auch
PDF) erledigt.
Meine send - Funktion gib den um das Parity erweiterten Wert zurück.
Wenn ich zum Test, diesen Wert in der main - Funktion mit printf
ausgeben möchte, bekomme ich nur aa angezeigt. Wenn ich den Wert direkt
in der send - Funktion ausgebe, funktioniert es. Das heißt, der Fehler
muss in der Wertrückgabe liegen. Was kann das sein?
Dominik M. schrieb:> muss in der Wertrückgabe liegen. Was kann das sein?
Du hast einen Fehler in deinem Programm.
Mehr kann man ohne aktuellen Code nicht sagen.
Dominik M. schrieb:> Sind folgende Anweisungen gleichwertig?>> send_data=send_data&(0<<7);>> send_data=send_data&~(1<<7);
Nein.
Versuch mal eine 0 nach links zu verschieben. Was erhältst du?
Dominik M. schrieb:> 0?>> Die zweite Anweisung bedeutet, dass ich das Bit an der Stelle 7 mit 1> über UND verknüpfe und anschließend negiere oder?
Reihenfolge!
Das ist nicht das was dort steht. Dort steht:
send_data = send_data & ~(1<<7);
(siehst du, wie ein paar Leerzeichen gleich mal die Lesbarkeit enorm
verbessern?)
Da steht nicht
Dominik M. schrieb :
> send_data=send_data&~(1<<7); ...> ... bedeutet, dass ich das Bit an der Stelle 7 mit 1> über UND verknüpfe und anschließend negiere oder?
Sondern, dass der Wert 1 um 7 Stellen nach links verschoben, negiert und
anschließend mit send_data UND verknüpft wird.
Die Reihenfolge ist anders.
Dominik M. schrieb:> Die Leerzeichen> sind angenehm für das Auge.
Die Leerzeichen hatte ich bei dem Beispiel auch schon drin :)
Dominik M. schrieb:> Kann bitte jemand das Programm versuchen und mir Bescheid geben ob die> Umsetzung richtig ist?
Du musst auch lernen, wie man selber seinen Code testet.
Probiers doch einfach aus. So viele Bytewerte gibts ja dann auch wieder
nicht
int main(void)
{
unsigned char corrected;
unsigned int i;
parity = ODD; //Auswahl ob EVEN- oder ODD-Überpruefung
for( i = 0; i < 0x100; ++i ) {
corrected = send( (unsigned char)i );
printf( "Byte 0x%.2X, nach Parity 0x%.2X\n", i, corrected );
}
system("pause");
return 0;
}
Das haut dir jetzt alle 256 möglichen Bytes durch die Funktion durch und
erstellt eine Tabelle mit unkorrigiertem Wert und korrigiertem Wert. Und
die checkst du durch. Wenn da keine Fehler drinnen sind, dann ist deine
send Funktion korrekt.
Dominik M. schrieb:> Danke für den Hinweis aber ich bin leider noch nicht in der Lage für> solche Spielchen. *g*
Welche Spielchen?
Eine for-Schleife und ein printf?
Dann fehlt es weiter als ich bisher gedacht habe.
Was dann?
2 stellige Hex-Zahlen auf Binär wandeln? Das geht nach Schema
0 0000 8 1000
1 0001 9 1001
2 0010 A 1010
3 0011 B 1011
4 0100 C 1100
5 0101 D 1101
6 0110 E 1110
7 0111 F 1111
Dein Programm wirft zb aus
1
Byte0x39,nachParity0x39
ist das korrekt?
0x39 (das 0x steht für Hex) hat das Bitmuster 0011 1001
(einfach jede Ziffer in der Tabelle suchen. 3 hat 0011. 9 hat 1001.
Zusammen haben sie also 0011 1001)
zähle die Einsen, sind 4 Stück.
Eingestellt war ODD Parity, also eine ungerade Anzahl. 4 ist nicht
ungerade, also ist das falsch. Da hätte das Bitmuster 1011 1001
rauskommen müssen. In Hex Schreibweise ist das B9. Das Programm hätte
ausgeben müssen
Mein Programm gibt folgendes aus:
data: 0x39 => der zu übergebende Wert
send_data: 0xB9 => 0x39 bekommt parity-Bit an der 7 Stelle, damit eine
ungerade Anzahl von 1en entsteht (wegen ODD-Vereinbarung)
receive_data: 0x39 => nach dem Senden, wird das parity-Bit wieder
entfernt
data = receive_data => Übertragung OK!?
Dominik M. schrieb:> Mein Programm gibt folgendes aus:>> data: 0x39 => der zu übergebende Wert>> send_data: 0xB9 => 0x39 bekommt parity-Bit an der 7 Stelle, damit eine> ungerade Anzahl von 1en entsteht (wegen ODD-Vereinbarung)>> receive_data: 0x39 => nach dem Senden, wird das parity-Bit wieder> entfernt>> data = receive_data => Übertragung OK!?
na dann passt es doch.
Du bist jetzt in der Beweispflicht, dass dein Prograqmm korrekt ist. Für
EINEN bestimmten Bytewert hast du das gezeigt. Aber eine Schwalbe macht
noch keinen Sommer, das wäre zu einfach
alle ungerade Zahlen sind Primzahlen
Beweis: 5 ist ungerade und 5 ist prim
Äääääähm
Deiner Beweispflicht kannst du nachkommen, in dem du entweder
1) zeigen kannst, dass dein Programm aus rein programmiertechnischen
Überlegungen heraus korrekt sein muss
2) oder aber, in dem du zeigst, dass für alle überhaupt möglichen
Eingaben immer das richtige Ergebnis rauskommt
Wenn du 1) nicht machen kannst, dann geht bei deinem Programm zumindest
2). EIn Byte kann 256 mögliche Werte annehmen. Bei dir nur 128, weil ja
1 Bit für das Parity Bit gebraucht wird. VOn 0 bis 127. Also jagst du
diese 128 Werte in einer Schleife in deine Funktion rein und siehst
nach, was jeweils rauskommt. Wenn du für alle Werte zeigst, dass sie
richtig sind, hast du damit auch gezeigt, dass deine Funktion per
Definition richtig ist.
Ja, sagt ja auch keiner was dagegen.
Wenn nur 8 Bit da sind, und eines davon das Parity Bit sein soll, dann
bleiben nur 7 Nutzbits. Das ist unmittelbar logisch nachvollziehbar.
Aber darum geht es ja auch gar nicht (oder reden wir aneinander vorbei?)
Die Frage ist ja: Dieses Parity Bit - wird das immer korrekt gesetzt
oder war das nur Zufall, das es in dem einen Beispiel funktioniert hat,
das du getestet hast?
Bei uns liegt ein Verständnisproblem vor. lach
Ich verstehe dieses Programm so: (Beispiel ODD)
Ein Wert soll übermittelt werden; Die send-Funktion überprüft die Anzahl
der 1en von dem zu übermittelnden Wert; Laut Vereinbarung "ODD", soll
diese ungerade sein oder werden; Der um das parity-Bit erweiterte Wert,
wird anschließend in der receive-Funktion wieder von dem parity-Bit
"befreit"; Wenn der zu übermittelnde Wert "data", dem Wert aus der
receive-Funktion "receive_Data"entspricht, dann ist die Übermittlung
korrekt verlaufen;
Man könnte noch eine Fehlermeldung ausgeben, wenn die Übermittlung nicht
funktioniert hat (z.B. wenn bei der Vereinbarung "ODD" keine ungerade
Anzahl von 1en in der receive-Funktion ankommt)
Für die Vereinbarung "EVEN" gilt genau das Gegenteil.
Dominik M. schrieb:> Bei uns liegt ein Verständnisproblem vor. *lach*
Seh ich auch so.
Ich stelle ja gar nicht in Frage, dass dein Programm so funktioniert.
Aber als dein Kunde musst du dir von mir die Frage gefallen lassen: Und
wie beweisen sie, dass das Programm bei jedem Bytewert die richtige
Parität einstellt?
Die Frage hast du dir ja auch gestellt:
> und mir Bescheid geben ob die Umsetzung richtig ist?
mit anderen Worten: Ist das Programm korrekt oder nicht.
Das ist jetzt die entscheidende Frage.
Für 128 Werte kannst du es.
- Druck die 128 Werte wie beschrieben aus.
- Schreib die Hex->Bin Tabelle darunter.
Und vergleiche "per Hand" und mit deinem Kopf.
Das kann der Kunde auch selber überprüfen wenn er es nicht glaubt.