char als int - speicherzugriffsfehler

sim4000

sim4000

Lebende Foren Legende
guten Tag.

Wir haben in der Schule jetzt seit 2 Wochen in C++ die Caesar-verschlüsselung. Dazu sollen wir ein Programm schreiben, was eine statistische analyse mit dem chiffrierten Text macht. Dazu sollen wir Zeichen für zeichen zählen. Und zwar folgender maßen:
Jedes einzelne Zeichen des Textes wird in einen int ungewandelt (ASCII). Dieser Wert hat ein gleichnamiges Feld in einem Array. Dieses wird dann mit ++ um 1 erhöht. Damit weiss man denn am ende welches Zeichen in dem Text am meisten vor kommt.
Nun zu meinem Problem:
Bei der Umwandlung kommen auch negative werte herraus. Dann kann natürlich nicht das passende Feld gefunden werden, und es gibt einen fehler.
Ich habs bissher so gemacht:
Code:
   char c;
   int integer;
   unsigned array[255];
   while(eingabe >> c) {
      integer = (int)c;
      array[integer] = array[integer] + 1;
   }
Aber es kommen wie schon gesagt immer mal wieder negative Werte vor, die nicht zugeordnet werden können. Hat wer ne idee wie mans noch anders machen kann?

Mfg, sim4000.
 
Klappts nicht auch ohne den integer?
Code:
#include <iostream>
using namespace std;

int main ()
{
	char c;
	unsigned array[256];
	for (int i = 0; i < 255; i++) {
		array[i] = 0;
	}
	while(cin >> c) {
		array[c] = array[c] + 1;
	}
	for (int i = 0; i < 255; i++) {
		if (array[i] != 0) {
			cout << (char)i << array[i] << endl;
		}
	}
};
Soweit ich sehe läuft das bei mir..
 
Das problem ist nur, ich brauche den int-wert zum zurück rechnen.
Caesar-verschlüsselung ist doch jeden buchstaben um einen wert zu verschieben.
Und um die Nachricht zu endschlüsseln, brauche ich die int-werte der buchstaben.

Und in dem Struktogramm von meinem Lehrer was er uns gegeben hat, ist das so erklährt. In der Klausur muss es auch so sein.

Mfg, sim4000.
 
Wie wäre es mit Modulo?

Code:
char c;
int integer;
unsigned array[255];
while(eingabe >> c) {
   integer = (int)c;
   integer = (integer + 256) %  256;
   array[integer] = array[integer] + 1;
}

So dürften keine negativen Werte mehr vorkommen.
 
Wie bereits erwähnt, werden die Buchstaben in ihren Wert in der ASCII-Tabelle umgewandelt. Es kann also garnicht negativ werden, wenn es echte ASCII-Zeichen sind. Vielleicht solltest Du die Chars angeben, die negative Integer erzeugen.
 
Hi,

hab jetzt nicht alles gelesen, aber das hier ist meine Lösung:
Code:
#include <stdio.h>

int main(int argc, char *argv[]) {
  char *code;
  unsigned int letters[255];
  int i;
  for (i=0;i<255;i++) letters[i] = 0;

  printf("Enter the code: ");
  scanf("%s",code);

  i = 0;
  while (code[i]!=0) {
    letters[code[i]]++;
    i++;
  }
  for (i=0;i<255;i++) {
    if (letters[i]>0) printf("%c (%X): %i\r\n",i,i,letters[i]);
  }
  return 1;
}

EDIT: Also erstmal um den meist benutzen Buchstaben zu bekommen.
 
Zuletzt bearbeitet:
Obwohl bei mir eine Zugriffsverletzung (Access Violation) nach der Eingabe aufgetreten ist, dieser fehler wird anscheinend durch meine msvcrt.dll verursacht bzw. tritt dort auf :/
Nö, es wird wohl eher daran liegen, dass der Code Murks ist.
Wenn man eine unbestimmte Menge von Zeichen (gets) einfach so auf gut Glück irgendwohin (char *code) in den Speicher schreibt kann das gar nicht gut gehen.
Man braucht schon Platz wo die Daten hinkommen sollen.
Entweder man legt die Grösse vorher fest (char code[123]) und schreibt dann da auch nicht mehr rein als geht (fgets(code,123,stdin)) oder man macht es mit malloc zur Laufzeit, aber irgendwo muss man dafür unbenutzten Speicher herbekommen..
 
Aber es kommen wie schon gesagt immer mal wieder negative Werte vor, die nicht zugeordnet werden können. Hat wer ne idee wie mans noch anders machen kann?

Mfg, sim4000.

Wie schon Xanti meinte, sollte c nie negativ werden. Kann es sein, dass der Text Umlaute o.ae. enthaelt? Dann versuche es doch mal mit unsigned char statt mit char. Wenn Du ein 'ae' (Umlaut) in ein char einliest, wird das sicher negativ, weil es die oberen 128 bit belegt.

Ausserdem kannst Du mit char genauso rechnen wie mit int, der Kompiler macht da nur bei der Ausgabe einen Unterschied.
 
Also. Im moment siehts so aus:
Code:
void caesar::analysis(void) {
   char c;
   int integer;
   unsigned array[256];
   while(eingabe >> c) {
      integer = (int)c;
      integer = (integer + 256) %  256;
      array[integer] = array[integer] + 1;
   }
   cout << endl;
};
Das mit dem unsigned char und mit dem modolo hab ich probiert, leider ohne erfolg. Zum Thema sonderzeichen: Es sollen wirklich alle zeichen verarbeitbar sein. Man muss halt alle Zeichen verschlüsseln, endschlüssen (die beiden funzen schon) und knacken (da bin ich grad) können.

Lg, sim4000.
 
Hi,

Ich dachte scanf speichert einen String und der würde doch eigentlich mit 0 enden. Deswegen while (code!=0), also bei mir geht das Zeichen zählen. Ich hab es allerdings mit C und nicht mit C++ kompiliert.
 
Was ist denn 'eingabe' fuer ein stream bei Dir?
Und was fuer eine negative Zahl bekommst Du, koenntest Du das mal angeben?
Ein unsigned char kann nur Werte zwischen 0 und 255 annehmen, d.h., wenn Du 'c' als 'unsigned char' deklarierst, _KANN_ nichts Negatives dabei rauskommen. Ich vermute daher, dass der Fehler muss woanders liegt.
 
Hat jetzt nix direkt mit dem Problem zu tun, ich wollte aber nur noch etwas zu Modulo sagen: es ist keine injektive (eindeutige) Abbildung, deswegen absolut ungeeignet für diese Aufgabe, da die Umkehrabbildung in diesem Fall nicht existiert.
 
Hat jetzt nix direkt mit dem Problem zu tun, ich wollte aber nur noch etwas zu Modulo sagen: es ist keine injektive (eindeutige) Abbildung, deswegen absolut ungeeignet für diese Aufgabe, da die Umkehrabbildung in diesem Fall nicht existiert.

Nicht unbedingt, das kommt auf die Wertemenge drauf an. U.U. kann die modulo-Funktion dann bijektiv sein. Was dann allerdings in diesem Fall nur unnoetigen Rechenaufwand bedeutet.
 
Nicht unbedingt, das kommt auf die Wertemenge drauf an. U.U. kann die modulo-Funktion dann bijektiv sein.

Lasse mich da gerne korrigieren, aber IMHO hat die Wertemenge keinen Einfluß darauf, ob man eine Funktion als injektiv oder bijektiv oder sonstwas bezeichnet.

Eine Funktion ist injektiv oder halt eben nicht.
 
@rikola

Yep, hast recht. Wenn man keine große Ahnung von Algebra hat, sollte man die Klappe halten. ;)

Auch die Aussage, "nicht injektiv -> keine Umkehrfunktion" ist Quatsch. Diese kann schon existieren, ist aber nicht surjektiv auf dem ursprünglichen Def.-Bereich. Z. B. Quadrat und Wurzel...

edit: @supersucker

bijektiv = injektiv+surjektiv. Und für surjektiv ist der Wertebereich schon wichtig. ;)
 
Zuletzt bearbeitet:
Lasse mich da gerne korrigieren, aber IMHO hat die Wertemenge keinen Einfluß darauf, ob man eine Funktion als injektiv oder bijektiv oder sonstwas bezeichnet.

Eine Funktion ist injektiv oder halt eben nicht.

Dann korrigiere ich Dich gerne, mich selber aber auch gleich mit. Werte-und Bildmenge sind wichtig.
Code:
f: R->R, f(x) = x^2
diese Funktion ist weder surjektiv noch injektiv, also erst recht nicht bijektiv,
Code:
f: R^+ -> R^+, f(x) = x^2
dagegen schon.

Code:
f: R-> R^+, f(x) = x^2
ist nicht injektiv, jedoch surjektiv, und
Code:
f: R^+ -> R, f(x) = x^2
muesste injektiv, jedoch nicht surjektiv sein.
 
Für die Injektivität ist der Wertebereich egal. Zur Notation: bei mir ist

Code:
f: X -> Y

X der Definitionsbereich, Y der Wertebereich.
 
Ich hatte auch negative Zahlen bei meiner Zählung. Ich hab dan mit der 1. for-schleife mal alle Elemente auf 0 gesetzt. Ich weiß nicht wie C das macht, aber wenn man nix den Variablen zuweißt, kann es sein dass dann einfach die Daten benutzt werden die an der Stelle im Speicher schon stehen?
 
Zurück
Oben