Question

So we are learning FoxPro in school and there's this program which I don't understand and can't really make it to work (teacher did it).

There's a table: Food C(15); Food_Cost N(3)

I need to calculate which food is the most to say 'popular' in it and write it (or them if there's more with the same number).

Here's the program: (error in IF B(j)>max line - operand/operator type mismatch)

If someone could rewrite or correct it and explain it to me how it works,I would greatly appreciate it!

USE table1
COUNT TO n
DIMENSION A(n)
GO 1
i=1
A(i)=food
SCAN
R=.F.
FOR j=1 TO i
IF A(i)=food
R=.T.
ENDIF
IF R=.F.
i=i+1
A(i)=food
ENDIF
ENDFOR
ENDSCAN
FOR j=1 TO i
DIMENSION B(i)
COUNT TO B(i) FOR food=A(i)
ENDFOR
max=B(1)
FOR j=1 TO i
IF B(j)>max
max=B(j)
ENDIF
ENDFOR
@15,1 say 'Most popular food:'
FOR j=1 TO i
IF max=B(j)
@15+j,2 say A(j)
ENDIF
ENDFOR
Was it helpful?

Solution

First, VFP allows for normal sql queries, much like you would be able to do in MySQL, SQL-Server, etc WITH some caveats AND some minor differences, so get used to reading queries from others even if they are in SQL-Server, MySQL, etc. The PRINCIPALS and basic syntax is the same. The big difference between them is other engines use ";" semi-colon to END the syntax. VFP uses ";" to indicate the statement continues on the next line... and this goes with all other VFP syntax too.

I'll start by doing a simple SQL-based query

*/ Pre-close the cursor in case previously opened...
*/ You will get to something like this later..
USE IN SELECT( "C_PopularFoods" )

*/ Run a simple SQL query and have the engine do the counting on a per-food basis
SELECT ;
      food, ;
      COUNT(*) as FoodCount;
   FROM ;
      Table1;
   GROUP BY ;
      food ;
   ORDER BY ;
      FoodCount DESC;
   INTO ;
      CURSOR C_PopularFoods READWRITE 

The "INTO CURSOR" basically creates ANOTHER result table IN MEMORY without it being a permanent table that you would have to manually erase after-the-fact when finished. Now, the work area / table alias "C_PopularFoods" is the current "work area" and is sitting at the first record in the result set. You can now grab the food count column from that result set as the basis for the most popular food by count.

*/ Preserve the first value in case there are MULTIPLE by this same count
lnPopularFoodCount = C_PopularFoods.FoodCount

*/ Announce the popular food count... but could also be done with @say...
*/ using "?" is like a simple output to the screen.   
? "The most popular food by count is: " + ALLTRIM( STR( lnPopularFoodCount ))

*/ NOW, you can do with either a do/while or scan loop.  One of the difference between
*/ do/while and scan is that scan is always based on a table (or cursor) and will go
*/ through each record, and at the end of the loop will automatically skip to the next
*/ record and exit the loop once the end of the file is reached.  
*/ Do/While loops can be done for any other condition, such as prompting user for 
*/ something or until some condition is reached.
*/
*/ In this case, since we KNOW what the most popular food IS, just scan through those
*/ records based on a simple FOR condition
? "Most Popular Food(s) is(are):"
SCAN FOR FoodCount = lnPopularFoodCount
    ? C_PopularFood.Food
ENDSCAN 

*/ Done, close the temp cursor we are done with it.
USE IN SELECT( "C_PopularFood" )

Your other code does NOT utilize any real strengths of dealing with tables, querying, etc. However that said, if I DID have to do it in code manually, here is what I would do.

use Table1
dimension PopFoods( reccount(), 2 )

*/ Prime the array that we have one food item, but
*/ leave it's count (array element ,2) to zero until
*/ we are IN the scan loop and actually cycle through the rows
numFoods = 1
PopFoods( 1, 1 ) = Table1.Food
PopFoods( 1, 2 ) = 0
maxFoodCount = 0

scan
   */ prep flag that it WILL BE ASSUMED a new food
   isANewFood = .T.

   */ Take the current record and go through all KNOWN foods
   for int i = 1 to numFoods
      */ is the current food record the same as the food already
      */ in the array list?
      if( Table1.Food = PopFoods( i, 1 )
         */ Yes, already in the list... clear the isANewFood flag
         isANewFood = .F.
         */ Now, just increment the counter for this food
         PopFoods( i,2 ) = PopFoods( i,2 ) + 1

         */ Did this food become the new Most popular food?
         if PopFoods( i, 2 ) > maxFoodCount
            */ Yes, it is a new maximum most popular food.
            */ set the maxFoodCount to whatever this count just hit
            maxFoodCount = PopFoods( i, 2 )
         endif 
      endif 
   endfor    

   */ If we went through the entire list of KNOWN foods, and the flag
   */ for IsANewFood is still TRUE, then it was not in the list and
   */ we need to add it and set it's initial count value to 1
   if isANewFood
      */ We have a new food item not already in the list
      numFoods = numFoods +1
      PopFoods( numFoods, 1 ) = Table1.Food
      PopFoods( numFoods, 2 ) = 1
   endif 
endscan


*/ Ok, we are DONE with all rows in the table being put into the array
*/ dump the results.
? "The most popular food count is: " + allt( str( maxFoodCount ))

*/ Now, go through the array for all items that match the count
for int i = 1 to numFoods
   if PopFoods( i, 2 ) = maxFoodCount
      ? PopFoods( i, 1 )
   endif 
endfor 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top