Java: reading from an input file, then moving data

2019-09-11 01:16发布

问题:

Early stages of a simulation project, when this program runs, its supposed to read in a file such as the one below, then it should process each neuron and synapse through the program. There are two types of synapse, unnamed synapses and named ones. Synapse X above is a named synapse connecting neurons A and B. Unnamed synapses have a single dash in the name field. Neuron and synapse names be non-numeric. Any synapse that is named may be the target of a secondary synapse. The synapse B X above is a secondary synapse that connects neuron B to (primary) synapse X. A synapse can be named or unnamed has two subclasses: Primary and Secondary.

My question: This code is part of a semester project, the first few parts were not difficult, but I'm unsure about subclasses. How do I scan in the synapse line and determine which belongs in subclass Primary and which ones belong in Secondary? Should I do something to the InitializeNetwork method or do I need something somewhere else?

Sample Input File:*

neuron A 1.0 0.95
neuron B 1.0 0.0
synapse X A B 1.2  0.5
synapse - B A 0.3 -0.5
synapse - B X 0.3  0.5

The code I have so far:

import java.io.File;
import java.io.FileNotFoundException;
import java.util.LinkedList;
import java.util.Scanner;

// Utility classes

/** Error reporting methods
 */
class Errors {
    static void fatal( String message ) {
        System.err.println( "Fatal error: " + message );
        System.exit( 1 );
    }
    static void warning( String message ) {
        System.err.println( "Error: " + message );
    }
}

/** Input scanning support methods
 */
class ScanSupport {
    /** Force there to be a line end here, complain if not
     */
    static void lineEnd( Scanner sc, String message ) {
        String skip = sc.nextLine();
        if (!"".equals( skip )) {
            // Bug:  do we want to allow comments here
            Errors.warning( message + " -- expected a newline" );
        }
        // Bug:  what if sc.nextLine() was illegal (illegal state)
    }

    /** Get the next float, or complain if there isn't one
     */
    static String nextName( Scanner sc, String message ) {
        if (sc.hasNext( "[a-zA-Z]\\w*" )) {
            return sc.next();
        } else {
            Errors.warning( message + " -- expected a name" );
            return null;
        }
    }

    /** Get the next float, or complain if there isn't one
     */
    static float nextFloat( Scanner sc, String message ) {
        if (sc.hasNextFloat()) {
            return sc.nextFloat();
        } else {
            Errors.warning( message + " -- expected a number" );
            return 99.99f;
        }
    }
}

// Simulation classes

/** Neurons are the vertices in the neuron network
 *  @see Synapse
 */
class Neuron {
    String name;            // name of this neuron
    private float threshold;    // voltage at which the neuron fires
    private float voltage;      // voltage at the given time
    private float time;     // (see above)

    private LinkedList <Synapse> synapses;  // the outputs of this neuron

    public class IllegalNameException extends Exception {}

    // initializer
    public Neuron( Scanner sc ) throws IllegalNameException {
        // scan and process one neuron
        name = ScanSupport.nextName( sc, "Neuron ??" );
        if (name == null) {
            sc.nextLine();
            throw new IllegalNameException();
        }
        if (NeuronNetwork.findNeuron( name ) != null) {
            Errors.warning(
                "Neuron " + name + " -- duplicate declaration"
            );
            sc.nextLine();
            throw new IllegalNameException();
        }
        threshold = ScanSupport.nextFloat( sc, "Neuron " + name );
        voltage = ScanSupport.nextFloat( sc, "Neuron " + name );
        time = 0.0f;
        ScanSupport.lineEnd( sc, "Neuron " + name );
    }

    // other methods
    public String toString() {
        return (
            "Neuron " +
            name +
            " " +
            threshold +
            " " +
            voltage
        );
    }
}

/** Synapses join neurons
 *  @see Neuron
 */
class Synapse {
    Neuron source;
    Neuron destination;
    Float delay;
    Float strength;

    // name is source destination

    public Synapse( Scanner sc ) {
        // scan and process one synapse
        String sourceName = ScanSupport.nextName( sc, "Synapse ??" );
        String dstName = ScanSupport.nextName( sc,
            "Synapse " +
            ( sourceName != null ? sourceName : "??" ) +
            " ??"
        );
        delay = ScanSupport.nextFloat( sc,
            "Synapse " +
            ( sourceName != null ? sourceName : "??" ) +
            " " +
            ( dstName != null ? dstName : "??" ) +
            " ??"
        );
        strength = ScanSupport.nextFloat( sc,
            "Synapse " +
            ( sourceName != null ? sourceName : "??" ) +
            " " +
            ( dstName != null ? dstName : "??" ) +
            " " + delay + " ??"
        );
        ScanSupport.lineEnd( sc,
            "Synapse " +
            ( sourceName != null ? sourceName : "??" ) +
            " " +
            ( dstName != null ? dstName : "??" ) +
            delay + " " + strength
        );

        // check correctness of fields
        source = NeuronNetwork.findNeuron( sourceName );
        if (source == null) {
            Errors.warning(
                "Synapse " +
                ( sourceName != null ? sourceName : "??" ) +
                " " +
                ( dstName != null ? dstName : "??" ) +
                " -- no such source"
            );
        }
        destination = NeuronNetwork.findNeuron( dstName );
        if (destination == null) {
            Errors.warning(
                "Synapse " +
                ( sourceName != null ? sourceName : "??" ) +
                " " +
                ( dstName != null ? dstName : "??" ) +
                " -- no such destination"
            );
        }
        if (delay < 0.0f) {
            Errors.warning(
                "Synapse " +
                ( sourceName != null ? sourceName : "??" ) +
                " " +
                ( dstName != null ? dstName : "??" ) +
                " " + delay + " " + strength +
                " -- illegal negative delay"
            );
            delay = 99.99f;
        }
    }

    // other methods
    public String toString() {
        return (
            "Synapse " +
            ( source != null ? source.name : "---" ) +
            " " +
            ( destination != null ? destination.name : "---" ) +
            " " + delay + " " + strength
        );
    }
}

/** NeuronNetwork is the main class that builds the whole model
 *  @see Neuron
 *  @see Synapse
 */
public class NeuronNetwork {

    // the sets of all neurons and all synapses
    static LinkedList <Neuron> neurons
        = new LinkedList <Neuron> ();
    static LinkedList <Synapse> synapses
        = new LinkedList <Synapse> ();

    /** Look up s in neurons, find that Neuron if it exists
     *  return null if not.
     */
    public static Neuron findNeuron( String s ) {
        for (Neuron n: neurons) {
            if (n.name.equals(s)) {
                return n;
            }
        }
        return null;
    }

    /** Initialize the neuron network by scanning its description
     */
    static void initializeNetwork( Scanner sc ) {
        while (sc.hasNext()) {
            String command = sc.next();
            if ("neuron".equals( command )) {
                try {
                    neurons.add( new Neuron( sc ) );
                } catch (Neuron.IllegalNameException e) {
                    // no action required
                }
            } else if ("synapse".equals( command )) {
                synapses.add( new Synapse( sc ) );
            } else {
                Errors.warning( command + " -- what is that" );
                sc.nextLine();
            }
        }
    }

    /** Print out the neuron network from the data structure
     */
    static void printNetwork() {
        for (Neuron n:neurons) {
            System.out.println( n.toString() );
        }
        for (Synapse s:synapses) {
            System.out.println( s.toString() );
        }
    }

    /** Main program
     * @see initializeNetwork
     */
    public static void main(String[] args) {
        try {
            if (args.length < 1) {
                Errors.fatal( "-- missing file name" );
            }
            if (args.length > 1) {
                Errors.fatal( "-- too many arguments" );
            }
            initializeNetwork( new Scanner(new File(args[0])) );
        } catch (FileNotFoundException e) {
            Errors.fatal( "" + args[0] + " -- file not found" );
        }
        printNetwork();
    }
}

回答1:

I would question if you really want to use inheritance here. It might be a better idea to use composition, where the behavior of synapses are defined by the classes that compose it. Look into the Strategy Pattern, it will probably end up working much better than some inheritance hierarchy.

http://www.tutorialspoint.com/design_pattern/strategy_pattern.htm