I have a file which has the following data in it
typedef INTEGER Id;
typedef Integer32 Id;
typedef Integer32 Id;
typedef Integer32 Id;
typedef INTEGER Identifier;
typedef Integer32 Index;
typedef Unsigned32 Identifier;
typedef Integer32 Index;
typedef Unsigned32 TunnelId;
typedef Unsigned32 TunnelId;
const Unsigned32 maxValue = 65535;
const Integer32 Index_maxValue = 65535;
const Unsigned32 maxValue = 4294967295;
const Unsigned32 Index_maxValue = 65535;
I need to select the variables in this below order:
If variable has …
INTEGERandInteger32definitions –Integer32has to be selectedInteger32andUnsigned32definitions –Unsigned32has to be selectedINTEGERandUnsigned32definitions –Unsigned32has to be selected
Output expected :
typedef Integer32 Id;
typedef Unsigned32 Identifier;
typedef Integer32 Index;
typedef Unsigned32 TunnelId;
const Unsigned32 maxValue = 65535;
const Unsigned32 Index_maxValue = 65535;
I have written the below piece of code …
But its not yielding the above expected result.
@file2 = @file // full content of the file in an array
for ($i = 0; $i <= $#file; $i++) {
$temp = $file[$i];
$check = $file[$i];
$check =~ s/^\s+//;
@fields = split(/ /, $check);
@grepNames = grep(/$fields[2]/, @file2);
if($#grepNames >= 1) {
for ($j = 1; $j <= $#file; $j++) {
if( $file[$i] =~ /INTEGER/ && $file[$j] =~ /Unsigned32/ ) {
push(@data, $file[$j]);
}
elsif( $file[$i] =~ /INTEGER/ && $file[$j] =~ /Integer32/ ) {
push(@data, $file[j]);
}
elsif( $file[$i] =~ /Unsigned32/ && $file[$j] =~ /Integer32/ ) {
push(@data, $file[i]);
}
}
}
Despite the fact that you have accepted 0% of your questions (It would be very fair to raise that number), here is an analysis of your code, so that you can write better (and working) Perl the next time.
General comments on writing Perl
Discipline vs. Chaos
Always
use strictanduse warnings, especially when you are trying to figure out why your script isn’t working or when you are new to Perl. Usually, these pragmas alert you about most stupid errors everybody makes once in a while.Perl doesn’t force you to write good code (and TIM TOWDTY), but most of the time you should stick to the
strictsubset of Perl unless you have a very good reason.Using
strictimplies that you have to declare all your variables withmy, unless you have a very good reason. I think that declaring variables is a good thing.Perl is not C
Most built-in functions do not need parens to delimit their arguments. I.e.
split(/ /, $check)andsplit / /, $checkare the same thing in most circumstances.Also, Perl seldomly needs the
for(INIT; COMPARE; INCREMENT)loop construct, especially when the last part is$i++. Instead, you can use theforeach-syntax and a range:Why your code doesn’t work
And: what bad idiom can be avoided
I already pointed out that all variables should be declared with
myand that there is a better loop syntax available.//doesn’t introduce a comment. It is the defined-or operator. Also, this statement isn’t terminated by a;. This will confuse Perl, as the followingforloop is part of the same statement—but this is invalid.Also, you don’t change the contents of either
@file2or@file, therefore making a copy unneccessary.You never use
$temp.You use this
grepto find out how many lines contain the same variable name. This is superflouus as you loop through all elements in@fileagain later on.What you have written is the question: Is the highest index in
@grepNameslarger than or equal to 1? whereas you probably meant Did we have more than one match?. Id write that asHowever, this is mainly a stylistical comment.
Wait what? If
$file[$i]containsINTEGER, so will$checkor$temp. You can save yourself some typing when using a scalar instead of an array subscript.You push something onto
@dataeven if you already have a line with the same variable name. Even worse, if@filecontains n elements, then the innerforloop iterates over n – 1 elements, and you push something onto@datain most cases, making your algorithm O(n²)Here is a table that states (according to your rules) which element should make it onto
@data. You might want to compare this table to yourif/elsifs and figure out if some cases may be missing.You forgot the
$sigil beforej.A better solution
Your algorithm runs in O(n²), or rather O(n * (2n – 1)). However, your problem can be solved in O(n).
I viewed the problem as:
In my solution (shown below), I used the 1st and the 3rd word as identifier. If a line was already present in the output, I updated it if the current line had a lower weight.
Edit: My Solution
Output: