3

This is a noob question. I have an array called Counter[N][N] and I want to do something like:

While (each element of Counter < 10000) {do something}

While (there exists an element of Counter < 10000) {do something}

Is there an easy way of doing that in C?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Ariaramnes
  • 943
  • 2
  • 10
  • 18
  • 2
    You can use a doubly nested loop to check, then you can use an if to do something. – nhahtdh Sep 22 '12 at 15:34
  • @Francisco:see my post,it gives u answer – Ravindra Bagale Sep 22 '12 at 15:44
  • 2
    Are you now asking for "IF there's a single element in Counter less than 10000"? – btstevens89 Sep 22 '12 at 15:46
  • That is exactly what I meant. – Ariaramnes Sep 22 '12 at 15:48
  • My solution is not really efficient, neither could any similar one be. But if you can assume that before your while loop all the lements of the counter array are less than 10000 and if in your while loop you modify the values of the array, then with a boolean and a simple check of the modified values would result in a great optimization – Kwariz Sep 22 '12 at 15:49
  • 1
    Ok, i'm not sure what the application of this is. Looping over a 2D array for each while loop may not be the best idea. What do you plan on doing IF there is an element? If you plan on manipulating the element to make it less than or greater than 10000, you want to use FOR loops like in my example. That way you'll only loop through the array once. – btstevens89 Sep 22 '12 at 15:55

8 Answers8

2

This function tests whether the counter array passed in has an element smaller than the specified value:

bool has_element_less_than(int value, int counter[N][N])
{
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
             if (counter[i][j] < value)
                 return true;
        }
    }

    return false;
}

You use it:

if (has_element_less_than(10000, counter))
    do_something();

You could deal with variable dimension arrays in C99 by passing N as a parameter to the function. It assumes you have the C99 header <stdbool.h> available and included.


Is this what you're after? You mention 'While' so it isn't clear whether you need to use a while loop — if you do, I think this does the job:

int i = 0;

while (i < N)
{
    int j = 0;
    while (j < N)
    {
         if (counter[i][j] < 10000)
         {
             counter[i][j] = do_something(i, j, counter[i][j]);
         }
         j++;
    }
    i++;
}

Or, more colloquially but using for loops:

for (int i = 0; i < N; i++)
{
    for (int j = 0; j < N; j++)
    {
         if (counter[i][j] < 10000)
         {
             counter[i][j] = do_something(i, j, counter[i][j]);
         }
    }
}

Note that this code is using C99; you can declare i and j outside the loops and it becomes C89 code. Also, if for any reason you need i or j (or, more likely, both) after the loop, you need to declare the variables outside the loop.

The second solution with for loops is more idiomatic C; the for loop is very good for this job and is what you should plan to use, not least because it packages all the loop controls on a single line, unlike the while loop solution which has the initialize code on one line (outside the loop), the condition on another, and the reinitialization on yet a third line.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • @Francisco: you might note that most of the original answers could be trivially adapted to answer the revised question by putting the code in a function, doing the 'do something' when the first value less than your limit is discovered, and then immediately returning. The only downside is hardwiring the action into what is otherwise a general-purpose routine. Also, if you need to know which element is less than the limit, you need a couple of output (pointer) arguments to the `has_element_less_than()` function. – Jonathan Leffler Sep 22 '12 at 16:17
2

You could do

for(int x = 0; x < N; x++) {
    for(int y = 0; y < N; y++) {
        if (Counter[x][y] < 10000){
             //Do something with Counter[x][y]
        }
    }
}
btstevens89
  • 147
  • 2
  • 10
1

this can be nicely done with pointers

  while(true)
  {
     int* pEnd = &Counter[0][0] + N*N;
     int* pCurrent = &Counter[0][0];

     bool AnyLess = false;
     while(pCurrent < pEnd && !AnyLess) { AnyLess |= *pCurrent++ < 10000; } 
     if(!AnyLess)
        break;

  }
user287107
  • 9,286
  • 1
  • 31
  • 47
  • I don't think that's what the OP is asking, I think they want to loop over every element in `Counter` that is less than 10000, not loop over the first 10000 elements. – verdesmarald Sep 22 '12 at 15:36
  • pointers are good if you want to do it very quickly and with a short source code, see other answers if you want to do it without pointers – user287107 Sep 22 '12 at 15:39
  • @mhasan Should not be. They're not that bad. And you'll eventually have to learn them... –  Sep 22 '12 at 15:39
  • 4
    @mhasan: The OP asked for an easy way of doing this in C. When presented with an array, playing games with pointers is almost always the answer. – kbyrd Sep 22 '12 at 15:39
  • But present day most prevalent languages like Java , C# don't have pointers.. Anyway I will go through pointer concepts for my exams and then dive into OOP. Thats where all the action is nowdays. Or am i wrong ? – Mudassir Hasan Sep 22 '12 at 15:44
  • C# has pointers, also they need to be marked as "unsafe" because the compiler can't check the expressions. anyway loops in C# are also more efficient through the enumerator-concept than the int-based for loops in C/C++ – user287107 Sep 22 '12 at 15:51
1

Easy if you can write a function which will return 1 if all the elements are less than 10000 :

int check_array_lt(int row_count, int col_count, int** array, int value)
{
  int i,j;
  for(i=0;i<row_count;i++)
    for(j=0;j<row_count;j++)
      if (array[i][j]>=value)
        return 0;
  return 1;
}

then use it :

while( check_array_lt(N,N,counter,10000) ) {
  do something
}

For the second version of the question (no more 'each element < 10000' but 'at least one element < 10000') :

int check_array_lt_atleast(int row_count, int col_count, int** array, int value)
{
  int i,j;
  for(i=0;i<row_count;i++)
    for(j=0;j<row_count;j++)
      if (array[i][j]<value)
        return 1;
  return 0;
}

As stated by Jonathan Leffler, this solution works only if the array is dynamically created; if Counter is declared as an array with #defined N, than my solution decays in Jonathan's one.

Kwariz
  • 1,306
  • 8
  • 11
  • 'All the elements less than 10000' is different from 'At least one of the elements is less than 10000'. – Jonathan Leffler Sep 22 '12 at 16:25
  • @JonathanLeffler Right ... it was just an answer on the OP's "first draft". I'll update my post. ... done :) – Kwariz Sep 22 '12 at 16:37
  • I know I'm a pest, but... An `int **array` parameter is very different from an `int array[][N]` parameter. The former requires an array of pointers, each of which points to (the first element of) an array of `int`; the second expects a 2D array. If you try your code with an actual 2D array, I think you'll run into problems, especially if most of the values in the array are zeroes. – Jonathan Leffler Sep 22 '12 at 17:42
  • @JonathanLeffler Not a pest at all, that's what I like here, I always learn something. I modified my answer to reflect your point. Thx :) – Kwariz Sep 22 '12 at 18:03
0

Use nested for loop

for(i=0;i<N;i++)
for(j=0;j<N;j++){

if(counter[i][j]<10000)
{
//Do something
}
}
Mudassir Hasan
  • 28,083
  • 20
  • 99
  • 133
0

What about this?

 int flag=0;
        for(i=o;i<n;i++)
        {
            for(j=o;j<n;j++)
            {
                if(counter[i][j]<10000)
                    //statements;
                else
                {
                  flag=1;
                    break;
                }

            }
  if(flag==1)
    break;
        }
Ravindra Bagale
  • 17,226
  • 9
  • 43
  • 70
  • Thanks, that would work if my question was the first one, but I didn't mean that, sorry. – Ariaramnes Sep 22 '12 at 15:43
  • it checks whether element having value 1000 is exist, if exist then it continues to work, if it got value >1000 then it breaks the loop – Ravindra Bagale Sep 22 '12 at 15:46
  • The `break` statements need some explaining. If the element was less than 1000 (note that the question said 10000, but what's an order of magnitude between friends), you do some statements and break; otherwise, you break anyway. That's not much of an inner loop; it iterates at most once. – Jonathan Leffler Sep 22 '12 at 15:46
  • setting flags...very nice mechanism to come out of multiple loops..Learned something new..thanx..upvoted – Mudassir Hasan Sep 22 '12 at 16:04
  • The revised code is still not behaving orthodoxly. I think that the `if (flag == 1) break;` fragment should be after the close brace of the inner loop; then it would work. It would be probably be better to package the whole thing as a function. The action might or might not be embedded inside the function (if it isn't the code can become general purpose; if it is, it is tightly coupled to its existing niche and not easily reusable until refactored). You might or might not need to return the location of the first element found that is under the limit via pointer arguments. – Jonathan Leffler Sep 22 '12 at 16:22
0

Solution for EDITED question

    for(i=0;i<N;i++)
    for(j=0;j<N;j++){

    if(counter[i][j]<10000)
    {
       //Do something
    }else
       goto OUT;
    }

    OUT:
    printf("out of loops");

In my arrogant opinion

goto

statement is the most elegant construct in programming language . If anybody wants to become billionaire like Bill Gates , they must use lots and lots of goto's while developing their path breaking software .

Mudassir Hasan
  • 28,083
  • 20
  • 99
  • 133
  • 1
    Suppose `counter[0][0]` contains 1000000 and every other value is 0. Your code jumps out of the loop on the first element it looks at, ignoring all the others that show that the processing needs to be done. Please indent your loops in a more orthodox manner. See also McConnell's "Code Complete" and [GOTO still considered harmful?](http://stackoverflow.com/questions/46586/goto-still-considered-harmful/) for some of the many discussions of GOTO. – Jonathan Leffler Sep 22 '12 at 16:13
0

although you did not ask for c#, here is the c# solution because it would be so easy:

    var Counter = new int[N,N];
    while(Counter.Cast<int>.Any(i => i < 10000)) { dosomething(); } 
user287107
  • 9,286
  • 1
  • 31
  • 47