¿Cómo evaluar una matriz de longitud variable en expresiones booleanas en C?

My question is very similar to the one already asked aquí.

However the length (and input) of the array are read from a file. How can I evaluate the boolean expression in my example?

fread(length, 4, 1, file);
array= calloc(length, sizeof(int));
fread(array, 4, length, file);

b = 7;

// I want to compare b with every entry in array
if(b==array[0]||b==array[1]||b==array[2]||...)    
  // do something   
end

preguntado el 28 de mayo de 14 a las 13:05

Re: For loops and null check. Also, what does *array represent in the calloc? -

sizeof(*array) should contain the size of the type of array when array is a pointer -

@EyeOfTheHawks your of course correct. *array is uninitialized at this point. I changed my post. -

is 4 se supone que es sizeof(int) ¿en esto? -

If this is the first time array is used, be sure to initialize it with an int* array, not just array. That would give you a syntax error though, so I'm sure you've done it somewhere -

2 Respuestas

Assuming the types match, and there is no endian-problems to take care of, you should be able to just loop:

bool array_is_b = true;
for(size_t i = 0; i < length && array_is_b; ++i)
{
  array_is_b = array[i] == b;
}

Después del bucle, array_is_b is true if the each element is equal to b.

Here's an attempt that does away with the explict assignment, it podría se más rápido:

bool array_is_self(const int *array, size_t length, int b)
{
  for(size_t i = 0; i < length; ++i)
  {
    if(array[i] != b)
      return false;
  }
  return true;
}

This re-arranges the operation into a function so that it can use return rather than a separate variable to track status. As long as the loop is running all elements up to i son iguales a b. supuse int for the array type.

contestado el 28 de mayo de 14 a las 14:05

Unfortunately in the final code there will also be a for-loop around the if-clause which will make this very slow... - avalonía

How large is the file? If you're running this on typical PC-grade hardware, I really wouldn't worry. Also, I don't think it can be done much quicker even in magic theory-land. Quizás by re-arranging it to not always assign to array_is_b, but at that point you're so far down the micro-optimizing rabbit-hole you probably don't see the Sun anymore. - relajarse

The file itself is not big and the array probably only varyies from somewhere between 1-30. But this will be embedded in a numerical modelling code which runs on a cluster. The for-loop surrounding the if-clause usually does >10^9 loops. But I agreed I can't see any better solution. - avalonía

Alright, that really is a lot of iterations. But, the file is very small. Next thing to investigate might be SIMD, first through auto-vectorizing of course. If you know that the file is e.g. always a multiple of 2, 4 or 8 bytes in size, you can re-write to compare more values in parallel (or compare single bytes until alignment is acquired, or just pad the buffer!). - relajarse

Or pre-compute a version of the array that just consists of the same element repeated, and do simple memory-comparison between the two. That might be faster, but has different set-up overhead. - relajarse

A for loop is in your answer.

for(i = 0 ; i < length ; i++)
{
    if(b == array[i])
    {
       //do something//
    }
}

By the way, you have a problem with your code. A text file is made out of bytes - each character is a byte means it's being read in type char. If array is an array of integers (it looks like it) then only the ASCII values of the characters would be read into the array (look up ASCII in google for more information but basically it's a value from 0 to 255 representing characters). Even if your text file contains "numbers" it's read as characters so basically if you use fread() you'll read character but with fscanf() you can determine the type of the input. So the expression if(b == array[i])would only be true IF array[i] is 7 (which means the value read from the text file is the character that 7 resembles - which is a BELL sound - the familliar windows error message sound - at all that can't be written into a text file so the boolean expression would be ALWAYS FALSE. Take that in mind. If you want to compare them as integers use if(b == array[i] - '0') as '0'=48 and the numbers in ASCII are from 48 to 57. so for example '4' (52) subtracted by '0' (48) is (52-48) actually integer value 4. Take that in mind. Hope I helped :P

contestado el 28 de mayo de 14 a las 14:05

Thank you for your extensive comment. Fortunately input is already working. In the final code there will also be a for-loop around the if-clause which will make this very slow... I was hoping there was some easier solution. - avalonía

You'll probably won't feel the difference in speed :P - zach p

No, the ASCII character set encoding is a number from 0 to 127, and each character is generally between 1 and 4 bytes. See The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets—No Excuses! - Tom Blodget

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.