Kreditkartenvalidierung



  • Hey Leute ich brauche eure Hilfe!
    Ich bin erst seit einigen Wochen mit der Programmierung in Ansi C beschäftigt.
    Hab davon auch fast gar keine Ahnung.
    Nun sollen wir als erste Aufgabe ein Programm schreiben was Kreditkartennummern prüft.
    Es funktioniert soweit nur bei falschen KKN zeigt es nicht die gewünschte Ausgabe an.

    Hier der Code vllt. kann mir jemand helfen.

    Edit* ich denke der Fehler liegt im letztem Abschnitt des Codes.
    bei der letzten Verzweigung wird nie die "else" Anweisung ausgeführt

    #ifdef _MSC_VER
    #define _CRT_SECURE_NO_WARNINGS
    #endif
    #define MIN 13
    #define MAX 16
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    
    int main() // Definition der Variabeln
    {
    	int flag, i, gesamtsumme, ziffer, mod;
    	char A[] = "Kreditkartennummer eingeben bitte                                        "; //String zur Aufnahme der Kreditkartennummer
    	char X[] = "00000000000000000000";		//String der der Nullen vor der Eingabe einfügt 
    	do                                          //annehmende Schleife für Eingabeprüfung
    	{
    		printf("Bitte geben Sie Ihre Kreditkartennummer ein:\n");
    		flag = 0;
    		gets(A);
    		if (!(strlen(A) >= MIN && strlen(A) <= MAX))   //solange eingabe falsche länge besitzt wird die schleife wiederholt
    			flag = 1;
    		else
    		for (i = 0; i < strlen(A); i++)      //zählschleife Stellen der Kreditkarte werden nacheinander geprüft
    		if (!(A[i] >= 48 && A[i] <= 57))     //falsche zeichen laut ascii code schleife wird wiederholt
    			flag = 1;
    
    	} while (flag);
    	X[20 - strlen(A)] = '\0';   // 0 Terminierung 
    	strcat(X, A);               //verketten von eingabe und bufferstring
    	gesamtsumme = 0;
    	for (i = 19; i >= 0; i--){      // jede Stelle von rechts wird durchlaufen, zählschleife dekrementiert i 
    		mod = i % 2;                //modulo 2 an jeder stelle
    		if (mod == 0){             //wenn rest 0
    			ziffer = (X[i] - '0') * 2;  //dann ziffer an der Stelle mal 2
    			if (ziffer > 9){          //Wenn Zahl größer 9, 
    				ziffer = ziffer - 9;		//dann wird 9 abgezogen
    			}
    			else{ ziffer = ziffer; }      //wenn nicht bleibt die mit 2 multiplizierte Ziffer  
    		}
    		else
    		{
    			ziffer = X[i] - 48;
    		}gesamtsumme = gesamtsumme + ziffer;
    	}
    
    //Prefixabfrage mittels Zeiger
    
    	int laenge_Karte, Anzahl_Zeilen_K;
    	int K_Prefix, index_zeiger;
    	char Karte[20] = "";
    	strcpy(Karte, A);
    	char Karten_Buffer[] = " Dient jeweils zur Aufnahme des entsprechenden Prefix der Karte... und genau mit der Anzahl Zeichen aus K[i][2]     ";
    	// Array zum Abegen der KK-Holder
    	char Holder[][20] = {
    		{ "Visa" },
    		{ "MASTERCARD" },
    		{ "AMEX" },
    		{ "Discover" },
    		{ "JBC" },
    		{ "Diners Club" }
    	};
    	int K[][4] = {
    		/*Kartenprefix,Stellenanzahl,Prefixlänge,Index in A[][] */
    		{ 41, 16, 2, 0 },
    		{ 41, 13, 2, 0 },
    		{ 51, 16, 2, 1 },
    		{ 52, 16, 2, 1 },
    		{ 53, 16, 2, 1 },
    		{ 54, 16, 2, 1 },
    		{ 34, 15, 2, 2 },
    		{ 37, 15, 2, 2 },
    		{ 36, 14, 2, 5 },
    		{ 38, 14, 2, 2 },
    		{ 6011, 16, 4, 3 },
    		{ 3, 16, 1, 4 },
    		{ 300, 14, 3, 5 },
    	};
    
    	Anzahl_Zeilen_K = sizeof(K) / sizeof(int) / 4;	// Ermittelung der Zeilenanzahl in K
    	index_zeiger = Anzahl_Zeilen_K + 2;				// index_zeiger wird in A[index_zeiger] gesetzt, falls er verändert wurde
    	laenge_Karte = strlen(Karte);					// Kartenlänge bereitstellen
    	for (i = 0; i < Anzahl_Zeilen_K; i++) {
    		strcpy(Karten_Buffer, Karte);			// Buffer mit Karte füllen
    		Karten_Buffer[K[i][2]] = '\0';            // Prefix erzeugen in Abhängigkeit von K[i][2]
    		K_Prefix = atoi(Karten_Buffer);			// Typ von char Array nach int
    		if (K_Prefix == K[i][0] && laenge_Karte == K[i][1])
    		{
    			index_zeiger = K[i][3];				// hier prüfen und schleife bei Erfolg verlassen
    			break;
    		}
    	}
    	if (index_zeiger < 99)
    		printf("Die eingegebene Kreditkarte mit der Kennung %s\nist vom Holder: %s \n", Karte, Holder[index_zeiger]);
    	else
    		printf("Die eingegebene Kreditkarte mit der Kennung %s\nist keinem Holder bekannt!\n", Karte);
    
    system("Pause");
    return 0;
    }
    


  • wie kommst du denn auf die bedingung für die if-Abfrage?

    if (index_zeiger < 99)

    soweit ich das programm überblickt habe wird dein index_zeiger immer kleiner 99 sein egal ob ein holder gefunden wurde oder nicht.



  • Anzahl_Zeilen_K = sizeof(K) / sizeof(int) / 4; // das ist Müll
    


  • vielen dank für die schnellen antworten. 🙂

    dann werde ich die prefixerkennung doch selber machen, umständlich über switch case. meine kenntnisse reichen einfach noch nicht weit genug.
    (finde es auch irgendwie bisschen überzogen nach 4 wochen als maschinenbaustudent so etwas können zu müssen)

    die komplette prefixabfrage ist vom unseren dozenten und er meinte wir sollen die
    ruhig mit einbauen(z.b nur noch variablen/feldnamen anpassen).

    aber jetzt weiß ich wenigstens das der dozent nicht nur menschlich voll daneben ist sondern anscheinend auch nicht die korifee der c programmierung ist als die er sich immer darstellt. 🙄



  • Wutz schrieb:

    Anzahl_Zeilen_K = sizeof(K) / sizeof(int) / 4; // das ist Müll
    

    wieso ist das müll?

    sizeof(K) gibt mir die größe des 2-dimensionalen arrays in byte
    sizeof(int) gibt mir die größe eines ints in byte

    dann ist doch sizeof(k) durch sizeof(int) die anzahl der elemente im array.
    und wenn ich das durch die anzahl der spalten teile (also durch 4) bekomme ich die anzahl der zeilen.

    ich bin auch noch neu in C und sehe daher nicht den fehler. vielleicht könntest du mich da noch etwas aufklären?

    @ bonniesranch:
    du musst nur die letzte if-abfrage ändern. dann funktioniert es. welche werte kann denn index_zeiger annehmen wenn die karte zu einem der insitute passt?
    welchen wert hat index_zeiger wenn kein institut passt?



  • Sowas als Lehrkörper seinen Schülern anzubieten, ist grausame Augenkrätze.
    Die Anzahl der Elemente eines Arrays in C zu ermitteln, ist schon sei Urzeiten bekannt:

    size_t anzahl = sizeof(array) / sizeof(*array);
    oder meinetwegen
    size_t anzahl = sizeof(array) / sizeof(array[0]);
    oder
    size_t anzahl = sizeof array / sizeof *array;
    

    Das klappt im Gegensatz zur Lehrervariante immer, für jedes Array von jedem Elementtyp.
    Wenn MSVC gegeben und auf Nichtportabilität Wert gelegt wird (bei den allermeisten Lehrkörpern der Fall), verwendet man einfach _countof aus (MSVC)stdlib.h.



  • bonniesranch schrieb:

    die komplette prefixabfrage ist vom unseren dozenten und er meinte wir sollen die
    ruhig mit einbauen(z.b nur noch variablen/feldnamen anpassen).

    Tja, da hast du Pech gehabt mit deinem Lehrstoffvermittler. Du wirst nichts Vernünftiges lernen.

    Ich würde sowas z.B. anbieten:

    /* separierbare Funktionalitäten gehören in eine Funktion ausgelagert; sowas nennt man auch Programmdesign */
    
    const char* gibPrefix(const char *nr) /* Kreditkartennummer wird übergeben, Herausgeber wird rückgeliefert */
    {
        const char *Holder[] = {
             "Visa" ,
             "MASTERCARD" ,
             "AMEX" ,
             "Discover" ,
             "JBC" ,
             "Diners Club"
        };
        const char *K[][2] = {
            { "41",  "0" },
            { "41",  "0" },
            { "51",  "1" },
            { "52",  "1" },
            { "53",  "1" },
            { "54",  "1" },
            { "34",  "2" },
            { "37",  "2" },
            { "36",  "5" },
            { "38",  "2" },
            { "6011",  "3" },
            { "3",  "4" }, /* hier kann ja wohl was nicht stimmen, 3 ist diesbzgl. nicht eindeutig */
            { "300",  "5" }
        };
    
        int x=sizeof K/sizeof*K;
    
        while( x-- )
          if( !strncmp(nr,*K[x],strlen(*K[x])) )
            return Holder[atoi(K[x][1])];
    
        return "";
    }
    

    Außerdem braucht ihr nicht jeder einzeln hier aufschlagen:
    http://www.c-plusplus.net/forum/321791-full



  • danke für die erklärung wutz.

    Wutz schrieb:

    { "3", "4" }, /* hier kann ja wohl was nicht stimmen, 3 ist diesbzgl. nicht eindeutig */

    du hast in deinem array nicht die länge der KKN mit dabei. deshalb ist 3 mehrdeutig. wenn die länge der KKNs dabei ist, dann ist es eindeutig, weil dann nur nummern die mit 3 anfangen und 16 stellen haben von JCB sind.

    Wutz schrieb:

    Außerdem braucht ihr nicht jeder einzeln hier aufschlagen:
    http://www.c-plusplus.net/forum/321791-full

    das problem bei den threads ist doch nicht das selbe. die aufgabenstellung ist auch nur ähnlich. beim anderen thread war ja z.b. gar nicht teil der aufgabe das kreditkarteninstitut zu ermitteln. aber gerade das ist ja hier das problem vom TE



  • Tja, da hast du Pech gehabt mit deinem Lehrstoffvermittler. Du wirst nichts Vernünftiges lernen.

    das Gefühl habe ich auch langsam 😕

    @bluebird: ich habe den Wert bei der letzten Prüfung auf <14 gestellt, da der
    index_zeiger ja maximal auf Zeile 13 zeigen kann.

    Ein paar testläufe führten zum gewünschten Ergebnis. Ich denke ich lasse es jetzt so..
    Auch wenn die Lösung mit Sicherheit nicht sauber ist.

    trotzdem vielen dank für eure lösunsmöglichkeiten und hilfe! 🙂 🙂 👍


Anmelden zum Antworten