Thread: Multi-level logic gates for begginers

  1. #31
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    The fscanf(...) == 2 line is meant to only read the first two fields on any line. You must use additional fscanf's to read any additional data.

    If the type is 'F' or 'T', there's nothing more to read.
    If the type is 'N', you need to read one more integer (into gates[i].in1).
    If the type is 'A', 'O', or 'X' you need to read two more integers.

    So there will be two additional fscanf's. Leave the first one as is since it's controlling the loop, so when it doesn't return 2 (because it either couldn't read an integer followed by a string or because it hit the end of input) the loop will stop.

  2. #32
    Registered User
    Join Date
    Jan 2016
    Posts
    22
    The fscanf(...) == 2 line is meant to only read the first two fields on any line. You must use additional fscanf's to read any additional data.

    If the type is 'F' or 'T', there's nothing more to read.
    If the type is 'N', you need to read one more integer (into gates[i].in1).
    If the type is 'A', 'O', or 'X' you need to read two more integers.

    So there will be two additional fscanf's. Leave the first one as is since it's controlling the loop, so when it doesn't return 2 (because it either couldn't read an integer followed by a string or because it hit the end of input) the loop will stop.
    Oh haha, you wouldn't believe how long I've been trying to make my program works. I couldn't understand how the scanf and the whole loop works in this case. I wrote it with printf to check if it reads everything properly.
    Code:
    while (fscanf(file, "%d %s ", &i, gate_type_string) == 2) {
            gates[i].type = gate_type_string[0];  
            printf("{GATE %d}    GATE NUMBER %d\n",i, i);
            printf("            GATE TYPE   %c\n",gates[i].type);
            if (gates[i].type == 'N') 
            {
                fscanf(file,"%d", &gates[i].in1);
                printf("       GATE INPUT  %d\n",gates[i].in1);
            }
    
            if ((gates[i].type == 'X') || gates[i].type == 'A' || gates[i].type == 'O')
            {
                fscanf(file,"%d %d",&gates[i].in1,&gates[i].in2);
                printf("            GATE INPUT  %d %d\n",gates[i].in1, gates[i].in2);
            }
    }
    It works and it's funny how much time I had to spend to write this... But well at least I've learnt something while trying that. For now I'll better go to sleep. Tomorrow I must learn some other thing but maybe I will try to move on a little with project so maybe I will ask some questions tomorrow too. Thank you all for help!

    PS. I have a little question. It's funny but I had some troubles building the OR condition with 'X', 'A', 'O'. I thought that I can write something like
    Code:
    if (gates[i].type == ('X' || 'A' || 'O'))
    but it never worked. My question is, is it possible to write it in similar way? Without repeating the variable name? Or I always have to repeat it, as I've done in my code?
    Last edited by Pinkysuavo; 01-16-2016 at 10:10 PM.

  3. #33
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Well you have to make a comparison between each OR.
    Code:
    if (gates[i].gate_type == 'X' || gates[i].gate_type == 'A' || gates[i].gate_type == 'O')
    If the number of possibilities is many, then you may consider searching through an array a good alternative. Another way to write the above without a big boolean test is:
    Code:
    if (strchr("XAO", gates[i].gate_type) != NULL) // one of X, A or O.

  4. #34
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by Pinkysuavo View Post
    My question is, is it possible to write it in similar way? Without repeating the variable name? Or I always have to repeat it, as I've done in my code?
    You can use a switch:
    Code:
    switch (gates[i].type) {
    case 'T': case 'F':
      break; // nothing to do
    case 'N':
      fscanf(file, "%d", &gates[i].in1);
      break;
    case 'A': case 'O': case 'X':
      fscanf(file, "%d %d", &gates[i].in1, &gates[i].in2);
      break;
    default:
      printf("Bad gate type: %c\n", gates[i].type);
      exit(1);  // exit program (need to include <stdlib.h> for this)
    }
    After the while loop, set another variable to i, e.g., ngates = i; to hold the highest gate number (this assumes the gates are in order in the input). Then make a loop to print all the input to check it:
    Code:
    ngates = i;
    for (i = 1; i <= ngates; i++)
      printf("%3d %c %3d %3d\n", i, gates[i].type, gates[i].in1, gates[i].in2);

  5. #35
    Registered User
    Join Date
    Jan 2016
    Posts
    22
    Hello again. It turned out I have a little more time for the project. Today I've been working on it and I have a following problem:
    I don't know how to loop the program to gather the information all the time, until all outputs are known.
    My program goes in one side, gathering information along the way, then writing output of a gate only if it has enough data.
    I'm not sure how to deal with it.
    I don't know if it's good idea, but I decided FALSE to be -1, TRUE to be 1 and UNKNOWN to be 0 (due to easier negation when there's NOT)
    Code:
            case 'T':
                gates[i].out = 1;
                break;
            case 'F':
                gates[i].out = -1;
                break;
    Here's also an example on how I tried to deal on how NOT gate works
    Code:
       case 'N': // if gate is NOT then it needs one input
                fscanf(file,"%d", &gates[i].in1);
    
                buff=gates[i].in1; //  set some buff. Buff contains number of input gate now
                if (gates[buff].out == -1 || gates[buff].out == 1) // if output is -1 or 1, we can set our gate value
                {
                    gates[i].out = -gates[buff].out;                  // it's just opposite. -1 is low, 1 is high, 0 is unknown
                }
    I have ideas for AND,XOR and OR also, but here's my problem. In this code I don't know what if there's 0. It should just continue to find the value but I don't know how to get back to this moment again then, with that value. I need to know how to make it all work in iterative way. I have many thoughts but can't invent anything. I have to sleep now, I hope my mind will be clearer tomorrow.
    #EDIT Last thing that came to my mind is using fseek or something. Like program gets as much data as it can, changing as many variables as it can, then I go to the beginning and read again. I could stop the loop then if all of array output elements were nonzero. I don't know if it makes any sense...
    Last edited by Pinkysuavo; 01-20-2016 at 11:05 PM.

  6. #36
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Firstly, do not do any calculations of the "out" values while reading in the data. We're dividing the program into three neatly-separated parts: first read the data into the array; second, calculate the output values from the array; third, print the results. (So there's no need to read the file again. We can use the data that we've read into the array. That's kind of the point!)

    Secondly, you should use 0 for false, 1 for true, and -1 for unknown (this means that you'll have to set the out's to -1 when reading in the gates). This will make the built-in logical (and bitwise) operators of C work correctly, which expect false to be 0. For example, instead of using the "minus" arithmetic operator, use the logical negation operator ! :
    Code:
      out = !val;  // If val was nonzero, out will be 0.
                   // If val was 0, out will be 1.
    
                       not  or   and  xor
    Logical operators:  !   ||   &&
    Bitwise operators:  ~   |    &     ^
    The bitwise operators will give the same output as the logical operators if you use only the values 1 and 0. Note that xor is only available as a bitwise operator.

    As for calculating the out values, there are two ways: recursive and iterative. The recursive solution is incredibly simple, but you may have trouble understanding how it works. The iterative solution is to loop through the gate array over and over, setting any out values that you can (by looking "one level deep", as it were), until you have set them all.

    I think the iterative solution would be more to your liking at this stage.
    Code:
    Loop through the gates until all outputs are set:
      if it's T, set out = 1
      if it's F, set out = 0
      if it's N, set out = ! in1  (but only if in1 is not -1,
                                   otherwise we can't set this one yet)
      if it's A, set out = in1 && in2  (but only if both are known)
      ...

  7. #37
    Registered User
    Join Date
    Jan 2016
    Posts
    22
    First of all, thank you very much for your help. My code finally starts working.
    But I have a little problem - I do not entirely understand how. At first, just after opening the file, I set all the outputs to unknown (-1).
    Code:
    for (i=0;i<=GATES_SIZE;i++)
            {
                gates[i].out = -1; // -1 is unknown
            }
    Then I started the loop. But I think I made it a little messy. I made a loop reading it and I evaluated what I could at that time, then I made second loop evaluating it again. I think that's not what you've meant, but I couldn't get it other way. Here's how the reading + evaluating loop looks like:
    Code:
        while (fscanf(file, "%d %s ", &i, gate_type_string) == 2 ) {
    
            // The gate number, i, is used as the index into the gates array
            gates[i].type = gate_type_string[0]; 
        switch (gates[i].type)
           {
            case 'T':
                gates[i].out = 1;
                break;
            case 'F':
                gates[i].out = 0;
                break;
            case 'N': // if gate is NOT then it needs one input, so I read one more variable
                fscanf(file,"%d", &gates[i].in1);
                buffn = gates[i].in1; //buff is the number of input gate
                if (gates[buffn].out != -1) //if its known then negate the output
                {
                    gates[i].out=!gates[buffn].out;
                }
                break;
            case 'X': //if it's X, A or O it needs to read 2 inputs
                fscanf(file,"%d %d",&gates[i].in1, &gates[i].in2);
                buffx1 = gates[i].in1;
                buffx2 = gates[i].in2;
                if (gates[buffx1].out != -1 && gates[buffx2].out != -1)
                {
                    gates[i].out = gates[buffx1].out ^ gates[buffx2].out;
                }
                break;
            case 'O':
                fscanf(file,"%d %d",&gates[i].in1, &gates[i].in2);
                buffo1 = gates[i].in1;
                buffo2 = gates[i].in2; 
                if ( gates[buffo1].out != -1 && gates[buffo2].out != -1)
                {
                    gates[i].out = gates[buffo1].out || gates[buffo2].out;
                }
                break;
            case 'A':
                fscanf(file,"%d %d", &gates[i].in1, &gates[i].in2);
                buffa1 = gates[i].in1;
                buffa2 = gates[i].in2;
                if (gates[buffa1].out != -1 && gates[buffa2].out != -1)
                {
                    gates[i].out = gates[buffa1].out && gates[buffa2].out;
                }
                break;
            default:                                            //if gate is not T/F/N/X/O/A
                printf("Bad gate type: %c\n",gates[i].type);    //then say which letter wasn't correct
                exit(1);                                        //and exit the program
            }
        }
        
        imax=i; //imax has number of the last gate now
        puts("nr tp  in1  in2 out\n");
        for (i=1;i <= imax; i++) // loop evaluating the values
        {
            if (gates[i].type == 'N')
            {
                buffn=gates[i].in1;
                if (gates[i].out != -1)
                gates[i].out = !gates[buffn].out;
            }
            if (gates[i].type == 'A')
            {
                int buffa1,buffa2;
                buffa1=gates[i].in1;
                buffa2=gates[i].in2;
                if (gates[buffa1].out != -1 && gates[buffa2].out != -1)
                gates[i].out = gates[buffa1].out && gates[buffa2].out;
            }
            if (gates[i].type == 'O')
            {
                int buffo1,buffo2;
                buffo1=gates[i].in1;
                buffo2=gates[i].in2;
                if (gates[buffo1].out != -1 && gates[buffo2].out != -1)
                gates[i].out = gates[buffo1].out || gates[buffo2].out;
            }
            if (gates[i].type == 'X')
            {
                int buffx1,buffx2;
                buffx1=gates[i].in1;
                buffx2=gates[i].in2;
                if (gates[buffx1].out != -1 && gates[buffx2].out != -1)
                gates[i].out = gates[buffx1].out ^ gates[buffx2].out;
            }
        if (gates[i].out==0) // printing the whole array with gates information
        {
        printf("%d %3c %3d %3d  FALSE\n", i, gates[i].type, gates[i].in1, gates[i].in2);
        }
        else if (gates[i].out==1){
            printf("%d %3c %3d %3d  TRUE\n", i, gates[i].type, gates[i].in1, gates[i].in2 );
        }
        }
    Point is: this stuff works only if I delete the part of code where I set everything to -1. It's weird for me. Also, I still don't get why everything can't be evaluated in the first loop. This thing that I've done here works but isn't fully understandable by me. (unless it doesn't, but I checked it on quite complex circuit examples and it evaluated everything properly).
    It's strange for me, that I actually evaluate AND/XOR/NOT/OR values at reading loop and evaluating loop at once. Also, I am aware that I need to write some code detecting loops in circuits, or some errors, but that's for later.
    Last edited by Pinkysuavo; 01-23-2016 at 12:06 PM.

  8. #38
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    When you think about it, there's no way your program could possibly work as written. While you read in the file you set the out's for T and F and any other gate that happens to have had its needed inputs set. Then you go through the gates ONCE more and set any other gates that you can. This can only go 2 (or maybe 3) levels deep at most! Try this (X1 should be true):
    Code:
    .                           X1
               A2                       N3
        O4           X5                 T6
     F7    N8     F9    N10
           F11          F12
    
     1 X  2  3
     2 A  4  5
     3 N  6
     4 O  7  8
     5 X  9 10 
     6 T
     7 F
     8 N 11
     9 F
    10 N 12
    11 F
    12 F
    The proper technique is to remove any setting of out's from the input loop (except perhaps for setting T's to 1 and F's to 0). Then have a processing loop (with no output statements!) that goes through the gates array MULTIPLE TIMES (not just once). It goes through until it finds that all out's are set. Then, after the processing loop, you would have an output loop that would create the final table of output. Each of these stages could be a separate function to keep things neat and tidy.

    You will need the setting of out's to -1 at the beginning to do it properly. The reason it might have seemed to "work" with your current code when removing the -1 initialization is that the system may have essentially initialized the out's to 0 instead (this is not guaranteed), which is a valid (though not necessarily correct) value.

    So the processing loop just goes through all the gates and, if the gate's out value is -1 and it's inputs are known, it sets it's out value. There should also be a flag here that you set simply because an out has been set. That way the outer loop knows that something has changed and that it needs to go around again.
    Code:
    int changes = 0;
    do {
      changes = 0;
      for (all gates) {
        switch (gates[i].type) {
          // ...
          // set changes to 1 if an "out" is changed
        }
      }
    }while (changes);
    BTW, you don't want the space after the %s in the first fscanf (this can cause it to "hang" in certain situations). Remove it.

    And you don't need a bunch of separately-named values for the temporary variables you're calling "buff...". Just use two variables called in1 and in2 (and declare them at the top of main so you don't have to declare them all the time).
    Last edited by algorism; 01-23-2016 at 02:06 PM.

  9. #39
    Registered User
    Join Date
    Jan 2016
    Posts
    22
    I noticed also that my program had no sense. It worked cause I made it work on around 2 ,,checks" which were enough in case of my circuits.
    That space after %s must have been some missclick, I haven't done that on purpose.

    I have done the loop. It takes all the outputs correctly, although I couldn't do it in your way. I mean, the loop was ending too quickly, or I just messed the code. Although I made an analysis on how it should work and finally got to some form, which looked same as yours, although
    Code:
    // set changes to 1 if an "out" is changed
    Turned out to be wrong. I have to set "1" when the output is still "-1" and hasn't changed. It works that way (now it surely works (okay 99%), checked it on multi-level circuits!)

    Last thing I have to do now is the anty-loop system. For now, the program is working forever when there's a loop, I have some ideas to break the program when the loop occures and to show some warning on the screen, althought it's getting late here (early actually, 6 am...), so I should go to sleep now. I'm almost at the end already!

    I'd like to THANK YOU all very much, but especially to algorism - you helped me a lot! I'm very grateful!

  10. #40
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    It's possible that you have a bug or two in your implementation. Did you notice that I edited my post because it had a bug? I changed the while (!changes) to while (changes).

    Anyway, this method should actually handle loops already. For instance,
    Code:
    this:
    
    1 NOT 2
    2 NOT 1
    
    should produce output something like:
    
     nr tp in1 in2   out
      1 N    2   0   UNKNOWN
      2 N    1   0   UNKNOWN
    Note that you need to print not just TRUE for 1 and FALSE for 0, but also UNKNOWN for -1. A trick for that is:
    Code:
    const char *value_str[] = {"UNKNOWN", "FALSE", "TRUE"};
    printf("%s\n", value_str[gates[i].out + 1]);
    If your program is not handling loops like this then it's not implemented correctly. In general, your explanation of what you're doing with "changes" sounds wrong. Try posting (or PM'ing me) your entire program so I can see exactly what's going on.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 08-30-2015, 10:50 PM
  2. codes for displaying logic gates ???
    By shikha_muz in forum Windows Programming
    Replies: 1
    Last Post: 12-16-2012, 11:29 AM
  3. Logic Gates - Multiplexer Help
    By alexmallaburn in forum C Programming
    Replies: 21
    Last Post: 02-22-2012, 05:30 PM
  4. C program related to logic gates!
    By yellowmania in forum C Programming
    Replies: 4
    Last Post: 02-14-2012, 07:38 AM
  5. Logic Gates
    By JFK in forum C Programming
    Replies: 0
    Last Post: 10-21-2001, 05:56 AM