Array in einer if Funktion zuweisen



  • Hallo,
    Was will ich machen?

    Nach Auswertung des Wertes "int candidateSector", soll ein Array in eine Funktion gegeben werden.

    Mein Problem

    Ich schaffe es nicht sector in Abhängigkeit von candidateSector zu initieren oder zuzuweisen.

    Ich habe einige Sachen ausprobiert, aber ich finde keinen richtigen Ansatz mehr, wie ich dieses Vorhaben umsetzen könnte. Was für Möglichkeiten gibt es?

    int candidateSector = isCandidateSector(candidateCell);
        if (candidateSector == 0){int sector[VALUES] = {0,1,2,9,10,11,18,19,20};}
        else if (candidateSector == 1){int sector[VALUES] = {3,4,5,12,13,14,21,22,23};}
        else if (candidateSector == 2){int sector[VALUES] = {6,7,8,15,16,17,24,25,26};}
        else if (candidateSector == 3){int sector[VALUES] = {27,28,29,36,37,38,45,46,47};}
        else if (candidateSector == 4){int sector[VALUES] = {30,31,32,39,40,41,48,49,50};}
        else if (candidateSector == 5){int sector[VALUES] = {33,34,35,42,43,44,51,52,53};}
        else if (candidateSector == 6){int sector[VALUES] = {54,55,56,63,64,65,72,73,74};}
        else if (candidateSector == 7){int sector[VALUES] = {57,58,59,66,67,68,75,76,77};}
        else if (candidateSector == 8){int sector[VALUES] = {60,61,62,69,70,71,78,79,80};}
        while (i < NUM_VALUES){
            if (trialValue == sample[sector[i]]){
                solved = FALSE;
                }
            i++;
            }
    


  • C_Newbe schrieb:

    Nach Auswertung des Wertes "int candidateSector", soll ein Array in eine Funktion gegeben werden.

    Ergibt keinen Sinn. Du kannst ein Array bzw. dessen Adresse an eine Funktion übergeben, du kannst es in einer Funktion zuweisen, du kannst ein Array von Funktionszeigern halten - aber ein Array in eine Funktion geben?

    C_Newbe schrieb:

    int candidateSector = isCandidateSector(candidateCell);
        if (candidateSector == 0){int sector[VALUES] = {0,1,2,9,10,11,18,19,20};}
        else if (candidateSector == 1){int sector[VALUES] = {3,4,5,12,13,14,21,22,23};}
        else if (candidateSector == 2){int sector[VALUES] = {6,7,8,15,16,17,24,25,26};}
        else if (candidateSector == 3){int sector[VALUES] = {27,28,29,36,37,38,45,46,47};}
        else if (candidateSector == 4){int sector[VALUES] = {30,31,32,39,40,41,48,49,50};}
        else if (candidateSector == 5){int sector[VALUES] = {33,34,35,42,43,44,51,52,53};}
        else if (candidateSector == 6){int sector[VALUES] = {54,55,56,63,64,65,72,73,74};}
        else if (candidateSector == 7){int sector[VALUES] = {57,58,59,66,67,68,75,76,77};}
        else if (candidateSector == 8){int sector[VALUES] = {60,61,62,69,70,71,78,79,80};}
        while (i < NUM_VALUES){
            if (trialValue == sample[sector[i]]){
                solved = FALSE;
                }
            i++;
            }
    

    Bist du sicher, dass du verstanden hast, wie C funktioniert? Mit deinem int sector[VALUES] deklarierst du jedes Mal ein neues Array. Was du willst, ist aber, dass dein Array je nach Wert, den du von isCandidateSector zurückbekommst, bestimmte Werte aufweist.

    (Die Kopie brauchst du im übrigen nur, wenn diese konstant bleiben sollen und du noch in das Array schreiben willst - ansonsten tut es auch ein Zeiger auf das jeweilge Array wunderbar und erspart dir das Kopieren von Daten).

    Mein Ansatz:

    #include <string.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <stdio.h>
    
    #define VALUES 9
    
    /*Sowas packt man in eine globale Struktur.*/
    static const int all_sectors[][VALUES] =
    {
            { 0, 1, 2, 9,10,11,18,19,20},
            { 3, 4, 5,12,13,14,21,22,23},
            { 6, 7, 8,15,16,17,24,25,26},
            {27,28,29,36,37,38,45,46,47},
            {30,31,32,39,40,41,48,49,50},
            {33,34,35,42,43,44,51,52,53},
            {54,55,56,63,64,65,72,73,74},
            {57,58,59,66,67,68,75,76,77},
            {60,61,62,69,70,71,78,79,80}
    };
    
    /*Wenn auf die Werte nur read-only zugegriffen wird, geht's auch anders.*/
    #define NEED_ARRAY NEED_ARRAY
    
    int main(void)
    {
    #if defined(NEED_ARRAY)
            int sector[VALUES];
    #else
            int*sector;
    #endif
    
            size_t i;
            uint8_t candidate;
    
            /*Wir simulieren hier mal Rueckgabewerte von isCandidateSector*/
            srand(time(NULL)); 
            candidate = rand() % VALUES;
    
            /*Eigentlicher Kopiervorgang.*/
    #if defined(NEED_ARRAY)
            memcpy(&sector,&all_sectors[candidate],sizeof(sector));
    #else   
            sector = (int*)(all_sectors + candidate);
    #endif
    
            /*Pruefen, ob das auch geklappt hat.*/
            for(i = 0;i < VALUES;i++)
                    printf("%d: %lu|%d\n",candidate,i,sector[i]);
    
            return 0;
    }
    


  • Es ist eine if-Anweisung.

    Du definierst in jedem if Block eine neues Array sector, das aber am Ende des Blocks nicht mehr existiert, da der Scope zu Ende ist.



  • Ich bin mir ganz sicher, dass ich C nicht verstanden habe 😃
    Deshalb lerne ich es und komme hier her wenn ich wirklich nicht weiter weiß.

    Was ich bisher im Zusammenhang mit diesem Problem gelernt habe ist:

    Gebe ich in eine Funktion ein Array, dann wird die Adresse der ersten Stelle übergeben

    Arrays kann man nicht aus Funktionen zurückgeben, weil nur die Adresse der ersten Zeile des Arrays übergeben wird, und diese eben im Stackframe dann verschwindet

    Da diese Aufgabe mir dient C besser zu verstehen und zu lernen probiere ich gerade mittels der mir gelernten Werkzeuge dieses Problem zu lösen. Z.B. war ich mir nicht sicher ob "Scoping" auf if-funktionen auch zutrifft, daher hatte ich das ebenfalls mal ausprobiert. Ich hatte auch probiert die sectoren jeweils einzeln außerhalb der if funktion zu deklarieren und dann später einer neuen Variable zuzordnen. Nunja das ging auch nicht.

    Sowohl static const als auch multidimensionale arrays hatte ich noch nicht. Ich verstehe allerdings schon, was der Sinn hinter der Idee ist und wie sie funktioniert. Ich werde sicher mir das über diese Mechanic einrichten, wird sicher am einfachsten sein.

    Was mich interessieren würde ist, wäre es auch ohne multidimensionales Array möglich gewesen? Ich möchte ja gerne die Aufgaben im Rahmen der vermittelten Kenntnisse lösen (was normalerweise bei der Aufgabe auch gefordert ist).

    Danke schonmal für die Hilfe! 👍



  • Da du mehrdimensionale Arrays noch nicht kennts, wären alle anderen Tricks jenseits deines Wissens.

    Es geht mit mehreren Funktionen. Ist nicht schön.

    void set_sector_0 (int sector[VALUES]) 
    { int daten[VALUES] = {0,1,2,9,10,11,18,19,20};
    
      memcpy(sector, daten, sizeof(daten));
    }
    

    Habt ihr schon die switch -Anweisung kennen gelernt?

    Und static und const sind erstmal nur Feinheiten und für die Funktion des Arrays nicht wichtig.



  • Ja die switch Anweisung kenne ich. Sie ist nicht Spezifikation des Kurses. Ich hatte schon drüber nachgedacht es darüber zu probieren.

    Ich werde dann erstmal mit dem multidimensionalen Array fahren und das ausprobieren. Wofür wäre denn das static const gut? Ich weiß ja, dass man die Werte in einem Array auch in einer Funktion ändern kann. Würde das somit verhindert werden, wenn ich die Arrays als Konstanten definieren möchte?



  • C_Newbe schrieb:

    Wofür wäre denn das static const gut?

    static sorgt dafür, dass eine globale Variable ihren Scope nur im gegenwärtigen Modul hat. Wenn du irgendwann mal fette Bibliotheken mit zig kleineren Modulen baust, die irgendwie Abhängigkeiten zueinander haben, willst du die Schnittstelle so sauber wie möglich halten.

    In diesem Fall würde das static verhindern, dass wenn du eine weitere Lib/Objektdatei zum Programm dazulinkst, welche ebenfalls das Symbol all_sectors kennt, es zu einem Namenskonflikt kommt. Außerdem sagt es dem Compiler, da das Objekt nur innerhalb des Moduls vorkommmt, dass er spezielle Optimierungen darauf anwenden darf - oder direkt ganz auflösen, wenn er das als schneller erachtet.

    C_Newbe schrieb:

    Ich weiß ja, dass man die Werte in einem Array auch in einer Funktion ändern kann. Würde das somit verhindert werden, wenn ich die Arrays als Konstanten definieren möchte?

    Werte in einem static -Array zu ändern geht. const ist verboten.

    Das stimmt natürlich nicht ganz. const ist nur eine Compilersperre, die kannste in C aber umgehen (ich werde jetzt nicht sagen, wie :)). Architekturen, die Read-Only-Mappings kennen, geben dann halt eine Access Violatio/Segfault/Whatever zur Laufzeit aus. Architekturen, die RO nicht kennen, lassen dich eventuell dann sogar in Felder schreiben, die du const deklariert hast.

    Der Vorteil ist dennoch, dass es dir hilft, dumme Programmierfehler zu vermeiden. Lieber zu viel als zu wenig beschränken. Gilt zwar auch nicht immer, aber das ist dennoch besser, ins Blaue hinein zu programmieren.



  • Nachtrag:

    Diese Bedeutung von static gilt NUR für globale Symbole. Sobald du static auf Symbole in Funktionen anwendest, ist die Bedeutung eine vollkommen andere (Variabel wird über alle Aufrufe dieser Funktion im Speicher gehalten, auch bei paralleler Ausführung, was ohne Locks katastrophal für Multi-tTreading-Programme ist).



  • dachschaden_off schrieb:

    Nachtrag:

    Diese Bedeutung von static gilt NUR für globale Symbole. Sobald du static auf Symbole in Funktionen anwendest, ist die Bedeutung eine vollkommen andere (Variabel wird über alle Aufrufe dieser Funktion im Speicher gehalten, auch bei paralleler Ausführung, was ohne Locks katastrophal für Multi-tTreading-Programme ist).

    oh danke für diesen Nachtrag!
    Meine Idee war nämlich die Variable nur global für die Funktion zu machen in der ich die Variable auch eben brauche. Da weiß ich schonmal, dass es diese fundamentale unterschiedliche Bedeutung gibt. Super ich habe eine Menge gelernt!

    Ich setze mich mal ran und schaue ob es so funktioniert wie ich mir das überlegt habe.

    Danke schon Mal! 😃



  • C_Newbe schrieb:

    Meine Idee war nämlich die Variable nur global für die Funktion zu machen in der ich die Variable auch eben brauche.

    What?

    Global für eine Funktion zu machen soll wohl "nur für die Funktion verfügbar" heißen.
    Aaaaber: static const könnte man in dem Fall auch in deine Funktion packen, es wäre effektiv kein Unterschied vorhanden. Erstens wirst du noch kaum mit Multi-Threading-Programmen zu tun haben, zweitens, selbst wenn, sind read-only Zugriffe auf gleiche Speicherbereiche ungefährlich und müssen nicht gelockt werden. Meines Wissens. Auf x86 und x64. Vielleicht gibt es da draußen Obskurru-Plattformen, die das nicht können, oder die Unsinn mit dem Cache machen (ARM, ich blick in deine Richtung!). Nur wenn du halt in das Array schreibst, wird es garantiert gefährlich.

    Deswegen ist das static für globale Symbole ja auch was anderes als das static für Lokale. Globale Symbole werden ebenfalls von allen Ausführungen geteilt, und wenn du da reinschreibst und nicht lockst, hast du das gleiche Problem.

    Der einfachen Lesbarkeit halber packt man sowas aber meines Erachtens in eine globale Struktur. Am Besten noch an den Anfang der Quellcode-Datei. Falls irgendwann mal was getweakt werden muss nach Jahren.



  • Kurz am Rande, es funktioniert!

    Ich meinte global für die Funktion, die ich geschrieben habe. In der Funktion selbst sind noch andere Funktionen, und für diese Funktionen wäre dann ja das Array sichtbar 🙂

    Ist sicherlich nicht richtig formuliert gewesen 🙂

    Momentan lerne ich über Vorlesungsmaterial C und den Zusammenhang von C zur Maschinencode.
    Im September werde ich dann angewandte Informatik studieren gehen. Da werde ich dann alles sehr ausführlich noch kennenlernen. Ich mache das hier alles in Vorbereitung für das Studium. Es ist besser wenn ich mich jetzt schon mit den Details der Grundlagen beschäftige 🙂



  • Ach und das Array ist read only, es befindet sich in einer Funktion, die ebenfalls in einer Funktion aufgerufen wird. Daher lasse ich das Array weder static noch const. Es wird kurz eingelesen und mit anderen Werten verglichen und ich benötige es danach auch nicht mehr.

    Das Programm soll ein Sudokusolver werden. Das Array speichert Zellenpositionen die zu einem Sudokusektor zählen. Ich rufe dann in einem anderen Array über eine while schleife die Werte des sudokugrids aus diesen Zellenpositionen ab und vergleiche diese mit einem Versuchswert um herauszufinden ob der Wert in dem Sektor bereits existiert. Dasselbe habe ich bereits für die Reihen und Zeilen geschrieben. Die Gesamtfunktion heißt isLegal und prüft ob ein Versuchswert sowohl für Row, Col und Sector TRUE oder FALSE ist.

    Ich habe für alle Funktionen Testfunktionen und jetzt hat isLegal mit der Sektoranalyse auch funktioniert.
    Großartig, ein gutes Gefühl, wenn es langsam funktioniert! 🙂



  • if ist keine Funktion sondern eine (Auswahl)Anweisung.

    Es gibt mehrere Varianten, ein Array nach der Definition/Initialisierung mit mehreren Werten (quasi blockweise) zu befüllen:

    void initarray(int*d,int n,...)
    {
    	va_list v;
    	va_start(v,n);
    	for(int i=0;n--;) d[i++]=va_arg(v,int);
    	va_end(v);
    }
    
    int main()
    {
    	int v[3];  /* Zielarray */
    	typedef struct{int i[3];} I3; /* Hilfstyp für struct-Kopie */
    
    	{ int x[3]={1,2,3};	*(I3*)v=*(I3*)x; }
    	printf("%d%d%d\n",*v,v[1],v[2]);
    
    	{ int x[3]={4,5,6};	memcpy(v,x,sizeof v); }
    	printf("%d%d%d\n",*v,v[1],v[2]);
    
    	*(I3*)v=*(I3*)(int[3]){7,8,9};
    	printf("%d%d%d\n",*v,v[1],v[2]);
    
    	memcpy(v,(int[3]){4,4,4},sizeof v);
    	printf("%d%d%d\n",*v,v[1],v[2]);
    
    	initarray(v,3,9,9,9);
    	printf("%d%d%d\n",*v,v[1],v[2]);
    
    	return 0;
    }
    

    http://ideone.com/F51FfV


Log in to reply