thearkranger has asked for the wisdom of the Perl Monks concerning the following question:

In this code, the user types in an element, and the code searches the array for that element then takes the weight of that element and uses it in calculations. No matter what chemical I give it, the code always chooses the first row of the array. Here's the code in it's entirety. Thanks for any assistance. The problem is in sub findMass. No matter what chemical is entered, that if statement activates.
## Grams to Moles use 5.14.2; no strict 'refs'; my ($grams, $chemWeight, $moles); #integers my $chemical; #strings my @periodicTable; sub main { fillArray(); setChemical(); setGrams(); findMass(); } main(); sub fillArray { @periodicTable = ( [1 , 'H' , 'Hydrogen' , 1], [2 , 'He', 'Helium',4], [3,'Li', 'Lithium',6], [4,'Be', 'Beryllium',9], [5,'B', 'Boron',10], [6,'C', 'Carbon',12], [7,'N', 'Nitrogen',14], [8,'O', 'Oxygen',15], [9,'F', 'Fluorine',18], [10,'Ne', 'Neon',20], [11,'Na', 'Sodium',22], [12,'Mg', 'Magnesium',24], [13,'Al', 'Aluminum',26], [14,'Si', 'Silicon',28], [15,'P', 'Phosphorus',30], [16,'S', 'Sulfur', 32], [17,'Cl', 'Chlorine', 35], [18,'Ar', 'Argon', 39], [19,'K', 'Potassium',39], [20,'Ca', 'Calcium',40], [21,'Sc', 'Scandium',44], [22,'Ti', 'Titanium',47], [23,'V', 'Vanadium',50], [24,'Cr', 'Chromium',51], [25,'Mn', 'Manganese',54], [26,'Fe', 'Iron' ,55], [27,'Co', 'Cobalt' ,58], [28,'Ni', 'Nickel' ,59], [29,'Cu', 'Copper' ,63], [30,'Zn', 'Zinc' ,65], [31,'Ga', 'Gallium' , 69], [32,'Ge', 'Germanium' , 72], [33,'As', 'Arsenic' , 74], [34,'Se', 'Selenium' , 78], [35,'Br', 'Bromine' , 79], [36,'Kr', 'Krypton' , 83], [37,'Rb', 'Rubidium' , 85], [38,'Sr', 'Strontium' , 87], [39,'Y', 'Yttrium' , 88], [40,'Zr', 'Zirconium' , 91], [41,'Nb', 'Niobium' , 92], [42,'Mo', 'Molybdenum' , 95], [43,'Tc', 'Technetium' , 98], [44,'Ru', 'Ruthenium' , 101], [45,'Rh', 'Rhodium' , 102], [46,'Pd', 'Palladium' , 106], [47,'Ag', 'Silver' , 107], [48,'Cd', 'Cadmium' , 112], [49,'In', 'Indium' , 114], [50,'Sn', 'Tin' , 118], [51,'Sb', 'Antimony' , 121], [52,'Te', 'Tellurium' , 127], [53,'I', 'Iodine' , 127], [54,'Xe', 'Xenon' , 131], [55,'Cs', 'Cesium' , 132], [56,'Ba', 'Barium' , 137], [57,'La', 'Lanthanum' , 138], [58,'Ce', 'Cerium' , 140], [59,'Pr', 'Praseodymium' , 140], [60,'Nd', 'Neodymium' , 144], [61,'Pm', 'Promethium' , 145], [62,'Sm', 'Samarium' , 150], [63,'Eu', 'Europium' , 151], [64,'Gd', 'Gadolinium' , 157], [65,'Tb', 'Terbium' , 159], [66,'Dy', 'Dysprosium' , 162], [67,'Ho', 'Holmium' , 165], [68,'Er', 'Erbium' , 167], [69,'Tm', 'Thulium' , 169], [70,'Yb', 'Ytterbium' , 173], [71,'Lu', 'Lutetium' , 175], [72,'Hf', 'Hafnium' , 178], [73,'Ta', 'Tantalum' , 181], [74,'W', 'Tungsten' , 184], [75,'Re', 'Rhenium' , 186], [76,'Os', 'Osmium' , 190], [77,'Ir', 'Iridium' , 192], [78,'Pt', 'Platinum' , 195], [79,'Au', 'Gold' , 197], [80,'Hg', 'Mercury' , 201], [81,'Tl', 'Thallium' , 204], [82,'Pb', 'Lead' , 207], [83,'Bi', 'Bismuth' , 209], [84,'Po', 'Polonium' , 209], [85,'At', 'Astatine' , 210], [86,'Rn', 'Radon' , 222], [87,'Fr', 'Francium' , 223], [88,'Ra', 'Radium' , 226], [89,'Ac', 'Actinium' , 227], [90,'Th', 'Thorium' , 232], [91,'Pa', 'Protactinium' , 231], [92,'U', 'Uranium' , 238], [93,'Np', 'Neptunium' , 237], [94,'Pu', 'Plutonium' , 244], [95,'Am', 'Americium' , 243], [96,'Cm', 'Curium' , 247], [97,'Bk', 'Berkelium' , 247], [98,'Cf', 'Californium' , 251], [99,'Es', 'Einsteinium' , 252], [100,'Fm', 'Fermium' , 257], [101,'Md', 'Mendelevium' , 258], [102,'No', 'Nobelium' , 259], [103,'Lr', 'Lawrencium' , 262], [104,'Rf', 'Rutherfordium' , 267], [105,'Db', 'Dubnium' , 268], [106,'Sg', 'Seaborgium' , 271], [107,'Bh', 'Bohrium' , 272], [108,'Hs', 'Hassium' , 270], [109,'Mt', 'Meitnerium' , 276], [110,'Ds', 'Darmstadtium' , 281], [111,'Rg', 'Roentgenium' , 280], [112,'Cn', 'Copernicium' , 285], [113,'Uut', 'Ununtrium' , 284], [114,'Uuq', 'Ununquadium' , 289], [115,'Uup', 'Ununpentium' , 288], [116,'Uuh', 'Ununhexium' , 293], [117,'Uus', 'Ununseptium' , 294], [118,'Uuo', 'Ununoctium' , 294], ); } sub setChemical { print "Chemical(1-2 Letter Abbreviation):"; chomp ($chemical = <STDIN>); } sub setGrams { print "Mass in Grams: "; chomp ($grams = <STDIN>); } sub findMass { for (my $i = 0; $i < 118; $i++) { if ($chemical = $periodicTable[$i][1]) { #always activates $chemWeight = $periodicTable[$i][3]; calculateMoles(); } } } sub calculateMoles { $moles = $grams/$chemWeight; printResults(); } sub printResults { print "\n Final Weight: $chemWeight"; print "\t$chemical weighs $moles Moles\n\n"; die "Finished.."; }

Replies are listed 'Best First'.
Re: Array problems.
by toolic (Bishop) on Oct 28, 2014 at 13:08 UTC
    Others have pointed out the problem, but since you are comparing strings, eq is preferable to == (perlop)
    if ( $chemical eq $periodicTable[$i][1] ) {

    Also, consider using a hash for your table because it facilitates look-up.

    UPDATE: CPAN is a handy resource: Chemistry::Elements

      yes i was to fast and i thought was the number.. Obviously you are rigth.
      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Array problems.
by Discipulus (Canon) on Oct 28, 2014 at 13:03 UTC
    You are testing the return value of the assignement. Instead you have to use ==
    ###WRONG if ($chemical = $periodicTable[$i][1]) { #always activates ###RIGHT if ($chemical == $periodicTable[$i][1]) {


    In any case thanks for the element table in the array!

    In your situation i normally use hashes:
    my %periodic_table = ( 1 => {symbol=>'H', name => 'Hydrogen', weight = +> 1}, 2 => {symbol=>'He', name => 'Helium', weight => + 4}, )


    HtH
    L*
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      In your situation i normally use hashes:
      my %periodic_table = ( 1 => {symbol=>'H', name => 'Hydrogen', weight = +> 1}, 2 => {symbol=>'He', name => 'Helium', weight => 4}, )
      While I would definitely agree that using a hash would often be better for such lookups, your example would work perfectly (and probably slightly faster) with an array (an array of hashes, that is), since you are using the atomic number as a key to your hash, and atomic numbers are just all the integers between 1 and 118, so that an array is a perfect fit.

      Having said that, it seems that the original poster is accessing the data through the chemical symbol, rather that the atomic number, and for that, a hash is much much better and way faster.

      To the OP: The structure of the hash would have to be something like this:

      <c> my %periodic_table = ( H => {atom_num => 1, name => 'Hydrogen', weight => 1}, He => {atom_num => 2, name => 'Helium', weight => 4}, # ... );
      The advantage is that it is then easier (and faster) to retrieve the characteristics of an element. For example, instead of scanning the whole array to find an element, one could have direct access to the characteristics of an element using a hash slice:
      my ($atom_nr, $elmnt_name, $atom_weight) = @{$periodic_table{$chem_sym +bol}}{qw /atom_num name weight/};
      Or, if the hash slice notation is intimidating to you, this more basic syntax:
      my $atom_nr = $periodic_table{$chem_symbol}{atom_num}; my $name = $periodic_table{$chem_symbol}{name}; my $atom_weight = = $periodic_table{$chem_symbol}{weight};

Re: Array problems.
by Eily (Monsignor) on Oct 28, 2014 at 13:04 UTC

    You wrote $chemical = $periodicTable[$i][1] instead $chemical == $periodicTable[$i][1] (so you are first changing the value of $chemical, and then checking that it is not null)

    Edit: it looks like I'm a bit slow :)