Προς το περιεχόμενο

Ανάλυση προγράμματος σε Perl.


firewalker

Προτεινόμενες αναρτήσεις

Σημείωση. Δεν βάζω το εν λόγο θέμα στον τομέα του προγραμματισμού διότι αναφέρετε σε λειτουργικό GNU/Linux και πιστεύω ότι θα βρω περισσότερη βοήθεια στο παρόν. Σε κάθε περίπτωση που κάποιος θεωρήσει ότι πρέπει να μετακινηθεί...

 

 

Έχω το παρακάτω πρόγραμμα που επικοινωνεί με την /dev/ttyUSBx.

 

>
#!/usr/bin/perl

use POSIX;
use Time::HiRes qw(gettimeofday);


#
# Set terminal parameters of the TTY that the optocoupler is connected to
#
sub init_tty {
my $fd = fileno(shift);
my $termios = POSIX::Termios->new();

$termios->getattr($fd) or die "Can't get terminal parameters for $dev";
$termios->setispeed(B2400);
$termios->setiflag(0);
$termios->setlflag(0);
$termios->setattr($fd, TCSANOW);
}


#
# Read next (complete) binary string from the optocoupler
#
sub next_bin_str {
my $bin_str;
while (!eof(USB_TTY) and length($bin_str) != 14 * 4) {
	my $byte = getc(USB_TTY);
	my $nibble_number = ord($byte) >> 4 & 0xf;
	
	$bin_str .= substr(unpack("B*", $byte), 4);
	length($bin_str) == $nibble_number * 4 or $bin_str = "";
}
$bin_str;
}


#
# Decode the measured data from the binary string
#
sub decode_bin_str {
my ($AC, $DC, $auto, $unknown1,
    $minus, $digi1, $dot1, $digi2, $dot2, $digi3, $dot3, $digi4,
    $micro, $unknown2, $kilo, $diode_test,
    $milli, $percent, $mega, $cont_check,
    $unknown3, $ohm, $rel, $hold,
    $amp, $volt, $hz, $unknown4,
    $min, $unknown5, $celsius, $max) = shift =~
   	   /^(.)(.)(.)(.)(.)(.{7})(.)(.{7})(.)(.{7})(.)(.{7})
    (.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) *$/x;

my %digi = (
	"1111101" => 0,
	"0000101" => 1,
	"1011011" => 2,
	"0011111" => 3,
	"0100111" => 4,
	"0111110" => 5,
	"1111110" => 6,
	"0010101" => 7,
	"1111111" => 8,
	"0111111" => 9,
);

my $val = ($minus ? "-" : "") . $digi{$digi1} . ($dot1 ? "." : "") .
				$digi{$digi2} . ($dot2 ? "." : "") .
				$digi{$digi3} . ($dot3 ? "." : "") .
				$digi{$digi4};

my $flags = join("~", $AC         ? "AC"         : (),
		      $DC         ? "DC"         : (),
		      $auto       ? "auto"       : (),
		      $diode_test ? "diode_test" : (),
		      $cont_check ? "cont_check" : (),
		      $rel        ? "rel"        : (),
		      $hold       ? "hold"       : (),
		      $min        ? "min"        : (),
		      $max        ? "max"        : ());

my $unit = ($micro   ? "u"   : "") .
	   ($kilo    ? "k"   : "") .
	   ($milli   ? "m"   : "") .
	   ($mega    ? "M"   : "") .
	   ($percent ? "%"   : "") .
	   ($ohm     ? "Ohm" : "") .
	   ($amp     ? "A"   : "") .
	   ($volt    ? "V"   : "") .
	   ($hz      ? "Hz"  : "") .
	   ($celsius ? "C"   : "");

$val, $flags, $unit;
}


################################################################################


$dev = shift || "/dev/ttyUSB0";
open USB_TTY, $dev or die "Can't open $dev";
init_tty(\*USB_TTY);

# force immediate flushing to stdout
$| = 1;

my $last_timestamp;

while ($bin_str = next_bin_str) {
my ($val, $flags, $unit) = decode_bin_str($bin_str);

$last_timestamp ||= gettimeofday;
my $timestamp = gettimeofday;


printf "%4.2f~%5.3f~%s~%s\n", $timestamp - $last_timestamp,
				 $val, $unit, $flags;

# $last_timestamp = $timestamp;
}

 

Το πρόγραμμα τυπώνει στην stdout όμοια με το παρακάτω.

 

0.00~23.200~C~auto

0.30~23.200~C~auto

0.59~23.200~C~auto

 

Εγώ θέλω στο δεύτερο πεδίο (μεταβλητή $val) να αντικαταστήσω το . τελεία με , κόμμα. Στο πρόγραμμα υπάρχουν οι μεταβλητές $dot1, $dot2 και $dot3. Στο παρακάτω τμήμα

 

>
my $val = ($minus ? "-" : "") . $digi{$digi1} . ($dot1 ? "." : "") .
				$digi{$digi2} . ($dot2 ? "." : "") .
				$digi{$digi3} . ($dot3 ? "." : "") .
				$digi{$digi4}; 

 

Ρωτάει τις μεταβλητέ αυτές (που παίρνουν τιμή 0 ή 1 ) και αναλόγως βάζει . ή όχι. Το κομμάτι ($dot1 ? "." : "") δεν κάνει τον έλεγχο; Γιατί όταν το "." το κάνω "," μου μηδενίζει την μεταβλητή $val; Ομοίως ισχύει και για την $minus να στο "-" βάλω οτιδήποτε άλλο π.χ. "^" μου μηδενίζει την $val.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δέν ξέρω άν σου μηδενίζει την val, δοκίμασε ένα κανονικό "print $val" γιατί το script σου προσπαθεί να τυπώσει την μεταβλητή σαν float και μπορεί να μπερδεύεται με τα , και ^ symbols που του βάζεις μέσα.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ναι, την μηδενίζει. Αν είναι float (που το είδες; ) πρέπει να μπερδεύετε διότι το "floating point" είναι . και όχι ,. Δεν το αναγνωρίζει σαν υποδιαστολή. Σωστά; Μπορώ να την αλλάξω σε κάτι άλλο (strigακι);

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

>printf "%4.2f~%5.3f~%s~%s\n", $timestamp - $last_timestamp, $val, $unit, $flags;

Η printf συντάσσεται όπως και στη C άν της δώσεις %5.3f και την αντίστοιχη παράμετρο όπως στη συγκεκριμένη περίπτωση η $val θα προσπαθήσει να τυπώσει τα data σαν floating point με 3 ψηφία μετά την υποδιαστολή.

Ή θα αλλάξεις το %5.3f με %s ή θα βάλεις ένα print $val αμέσως πρίν το printf για να δείς άν είναι όντως null το scalar ή απλώς δεν μπορεί να το τυπώσει σαν float.

Επίσης τρέξε το script με -w στο shebang για να σου βγάλει και warnings.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 2 εβδομάδες αργότερα...

Ας επανέλθω λίγο... Το παρακάτω τι ακριβώς κάνει;

 

>sub decode_bin_str {
my ($AC, $DC, $auto, $unknown1,
    $minus, $digi1, $dot1, $digi2, $dot2, $digi3, $dot3, $digi4,
    $micro, $unknown2, $kilo, $diode_test,
    $milli, $percent, $mega, $cont_check,
    $unknown3, $ohm, $rel, $hold,
    $amp, $volt, $hz, $unknown4,
    $min, $unknown5, $celsius, $max) = shift =~
   	   /^(.)(.)(.)(.)(.)(.{7})(.)(.{7})(.)(.{7})(.)(.{7})
    (.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) *$/x;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ας επανέλθω λίγο... Το παρακάτω τι ακριβώς κάνει;

 

 

Κάνει τον κόσμο να μάθει python (σαν τη ρετσίνα κουρτάκη με τη μπύρα ένα πράμα).

 

>sub decode_bin_str {
my ($AC, $DC, $auto, $unknown1,
    $minus, $digi1, $dot1, $digi2, $dot2, $digi3, $dot3, $digi4,
    $micro, $unknown2, $kilo, $diode_test,
    $milli, $percent, $mega, $cont_check,
    $unknown3, $ohm, $rel, $hold,
    $amp, $volt, $hz, $unknown4,
    $min, $unknown5, $celsius, $max) = shift =~
   	   /^(.)(.)(.)(.)(.)(.{7})(.)(.{7})(.)(.{7})(.)(.{7})
    (.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.) *$/x;

 

Κάνει το εξής: ορίζει μια συνάρτηση η οποία παίρνει ένα string (αν και αυτό δε φαίνεται πουθενά) και το σπάει σε επιμέρους μεταβλητές. Από δεξιά προς τα αριστερά:

 

το /^(.) (.) (.) κλπ *$/x "σπάει" το string σε επιμέρους τμήματα. Όπου . σημαίνει "οποιοσδήποτε χαρακτήρας" και οτιδήποτε βρίσκεται σε παρένθεση επιστρέφεται ως αποτέλεσμα. Με άλλα λόγια, η εφαρμογή της regular expression:

>
/^(.) (.) (.) (.) *$/

Στο string "a b c d", θα επιστρέψει έναν πίνακα ("a", "b", "c", "d"). Στη συνέχεια η shift αποδίδει τις τιμές αυτές στις μεταβλητές που ορίζονται από τη my.

Ωραία όλα αυτά, αλλά θα με ρωτήσεις που είναι το string; Η απάντηση είναι "πουθενά, υπονοείται". That's perl. Κλείστε την και μάθετε python :P

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ένα απόγευμα έλειψα και αρχίσανε τα προβοκάτσια. Αφού το λέει το FM ότι οι subroutines της Perl δεν χρειάζονται ορισμό των παραμέτρων τους στον header. Και στο κάτω κάτω το keyword shift τα προδίδει όλα. :P

Γιατί δεν αρχίζουμε να γκρινιάζουμε και για το shell scripting τότε; Ποίος ψήνεται να γράψουμε ένα shell που θα χρειάζεται explicit declaration των παραμέτρων που θα δέχεται η κάθε function;

Καλημέρα σε όλους!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...