1

I've built a two dimension array with string values. There are always 12 columns but the number of rows vary. Now I'd like to build a string of each row but when I run the following code:

$outstring = "";
for ($i=0; $i < $ctrLASTROW + 1; $i++) {
    for ($k=0; $k < 12; $k++){
       $datastring = $DATATABLE[$i][$k]);
       $outstring .= $datastring;
    }
}

$outstring takes the first value. Then on the second inner loop and subsequent loops the value in $outstring gets overlaid. For example the first value is "DATE" then the next time when the value "ABC" gets fed to it. Rather than being the hoped for "DATEABC" it's "ABCE". The "E" is the fourth character of DATE. I figure I'm missing the scalar / list issue but I've tried who knows how many variations to no avail. When I first started I tried the concatenation directly from the @DATATABLE. Same problem. Only quicker.

TLP
  • 66,756
  • 10
  • 92
  • 149
  • you seem to have a stray close bracket at the end of `$k]);` and as always, turn on strict and warnings. Do you have any undef values breaking the concatenation? – KeepCalmAndCarryOn Aug 19 '13 at 00:09
  • It is not possible to reproduce your problem. Provide input data. – daxim Aug 19 '13 at 00:09
  • Did you perhaps read the row values from a file, where the last entry on the `$k` element arrays are `chomp`ed? Meaning you have a bad line endings problem? – TLP Aug 19 '13 at 00:37

1 Answers1

4

When you have a problem such as two strings DATE and ABC being concatenated, and the end result is ABCE, or one of the strings overwriting the other, a likely scenario is that you have a file from another OS, with the line endings \r\n, which are chomped, resulting in the string DATE\rABC when concatenated, which then becomes ABCE when printed.

In other words:

my $foo = "DATE\r\n";
my $bar = "ABC\r\n";   #  \r\n line endings from file
chomp($foo, $bar);     #  removes \n but leaves \r
print $foo . $bar;     #  prints ABCE

To confirm, use

use Data::Dumper;
$Data::Dumper::Useqq = 1;
print Dumper $DATATABLE[$i][$k];   # prints $VAR1 = "DATE\rABC\r";

To resolve, instead of chomp use a regex such as:

$foo =~ s/[\r\n]+\z//;
TLP
  • 66,756
  • 10
  • 92
  • 149
  • 1
    … to resolve, set the input record seperator to the actual line endings: `$/ = "\r\n"` **or** preferably, add the `:crlf` PerlIO layer to the input file handle. Then `chomp` will work as expected. – amon Aug 19 '13 at 11:04
  • @amon Will these solutions work even when you do not know the line endings beforehand? My solution works for all files. – TLP Aug 19 '13 at 19:19
  • you are right, the substitution works for all common line endings. If, however, the line endings *are* known, then there are other, more elegant (read: maintainable), and arguably more correct solutions. I'm allergic to silver bullets, encoding detection, and line ending guessing. – amon Aug 19 '13 at 19:26
  • @amon Perhaps you should post your own answer then. This problem is common enough that it should be in some FAQ, so that people can find a quick fix. – TLP Aug 19 '13 at 20:38