Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Loop variable problem 3

Status
Not open for further replies.

nfaber

Technical User
Oct 22, 2001
446
US
Hello all,

I have the following code:

Code:
foreach $key(@keys) { #Start main loop
	while (<COMP>) {
		chomp;
		next unless (/$key/);
		($junk_key, $company, $exceptions) = split (/,\s*/);
		print "key is:$key\tcompany is:$company\texception are:$exceptions\n";
		@exceptions = split /\s+/, $exceptions;
		print (LOG "Getting ticket counts for $company\n\n");
		print (LOG "Starting Peregrine queries\n\n");
		#
		# Run sub routines. These perform all the queries and a good deal of the query processing.
		#
		my @clock		=	ClockQuery($company, \@exception);
		my @first_problem		=	ProbQuery($company, \@exceptions);
		my @device		=	DevQuery($company);
		my @problem		=	ClockProcess(\@clock,\@first_problem);
		my @results		=	FourMonths(@last4months);	
	}
	print "second:  key is:$key\tcompany is:$company\texception are:$exceptions\n";

@keys contains a list of 3 letter keys from the command line @ARGV. What I am doing is for each key looping through a config file that looks like this:

Code:
Company Key	Company Name			Assignment Group Exceptions

coc,		CHICAGO,
ccc,		IRC COMCAST,
com,		CITY OF MINNEAPOLIS,
cpd,		CPD,
cta,		CTA,
gld,		GAYLORD PALMS,
hgi,		HARLEYSVILLE,
fya,		HEALTH AND HUMAN SERVICES,
ipa,		INTERNATIONAL PAPER,
ipi,		INTERNATIONAL PAPER,
lal,		LEADER,
lmr,		LE MERIDIEN,
mmc,		MAIMONIDES,
mdc,		MIAMI DADE COUNTY,
mwd,		MORGAN STANLEY,			MWD-T3-SRV MWD-T3-NET

Based on the key in the from the @ARGV, I want to set the company name for that iteration of the foreach loop in my while loop. It is not working.

This is the output I am gettingform my print statements:

Code:
key is:glb      company is:GLOBAL PETROLEUM     exception are:
Problem company:        GLOBAL PETROLEUM
Device company: 1
second:  key is:glb     company is:GLOBAL PETROLEUM     exception are:
second:  key is:mwd     company is:GLOBAL PETROLEUM     exception are:
second:  key is:ccc     company is:GLOBAL PETROLEUM     exception are:

For some reason, it only goes through the while loop the first iteration of the foreach loop. From then on, the three letter key is changed, but the company from the lookup in the while loop does not. As you can see, the second time through the key is "mwd" and from the while loop lookup, the company should then be "Morgan Stanley" but it stays set at "Global Petrolium"

I have been wracking my brain for a hours on this.

Any help is appriciated,

Nick
 
I don't think you can do a while loop like that inside a foreach loop and have it do what you are expecting. If you put <COMP> into an array first and then do something like this:

Code:
foreach $key(@keys) { #Start main loop
    foreach(@comp) {

it might just work as expected

 
Thanks Kevin. I'll try that and let you know.
 
That seems to be the problem Kevin, thanks. Now my next question is why can't I nest a while loop in a foreach loop?
 
why can't I nest a while loop in a foreach loop?
That's not the problem. (Nor is it true.) The problem is that you're reading from the filehandle COMP, and after the while loop terminates the first time, the file has been read to the end, so there's nothing to read on subsequent iterations of the for, and so the condition at the top of the while fails, and you just fall through the while on all for iterations after the first.


 
Thanks for the reply Mike. I think I see. Once it reads through the file on the first while, it satisfies the while statement, so while turns to false. I would think however, on the next interation of the foreach, the while would be reset. Guess not.

If I wrote <COMP> to and array @comp and "while" looped through that, would it make a difference?

Thanks,

Nick
 
Use a for loop to loop over the array, as KevinADC suggests. Though you could use a while, it would be less idiomatic and more awkward. And while (@comp) { is an endless loop.

 
You might want to take another look at this thread from a while back: thread219-962182.

 
nfaber
You'd have to close and re-open the COMP filehandle on each iteration for it to work the way you want. But then it would be inefficient to keep reading the config file over and over. Much better to read it into an array
Code:
my @comp = (<COMP>);
chomp @comp; # only need to do it once...
 
I did remember that thread Mike, although I did not re-read it. What I remembered was "use a foreach if you need to assign each element to a scalar". In this case I did not so I used the while.

Forgive me if I repeat myself. I feel like I'm in over my head here sometimes. Eventually osmosis set in though.


[dazed]
 
That's not the problem. (Nor is it true.) The problem is that you're reading from the filehandle COMP, and after the while loop terminates the first time, the file has been read to the end, so there's nothing to read on subsequent iterations of the for, and so the condition at the top of the while fails, and you just fall through the while on all for iterations after the first.

Exactly right, I should have explained that in my post. I can see where my comment could mislead a person to think a while loop can not be nested in a for/foreach loop.
 
Forgive me if I repeat myself. I feel like I'm in over my head here sometimes. Eventually osmosis set in though.

Compared to other folks that only want code handed to them and don't want to understand or try and write some code, you are a pleasure to help. [2thumbsup]

 
Thanks folks. I needed that.

As always,

Nick
 
@stevexff - I'm just nitpicking. Your suggestion that the file is best just slurped into an array is, I agree, the best way to go (unless the file is huge).

stevexff said:
You'd have to close and re-open the COMP filehandle on each iteration for it to work the way you want.

You can actually just use seek() to reset the filehandle back to the start of the file, rather than having to open and close the file. This example illustrates (just comment the seek() line to see the difference):
Code:
open IN, 'some.filename';
for ( 0 .. 2 ) {
   while (<IN>) {
      print;
   }
   seek IN, 0, 0;
}
close IN;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top