C trying to fix infinite loop - c

I have a function that gets an index value, puts it in an array. Then generates a new new random index using rand + srand(key). And it checks if the newly generated index is in array already, it will will keep on generating new index and checking until a unique value is generated.
The problem is that it works fine for small keys, but at longer keys it gets stuck in an infinite loop and can never find a unique value. Here's my code:
int getNewIndex(PPM *im, int index, int *visitedPixels, int *visitedPixelsIndex) {
int i = 0;
if(*visitedPixelsIndex == im->height) {
perror("Cannot encode anymore: pixels limit reached");
exit(1);
}
visitedPixels[*visitedPixelsIndex] = index;
(*visitedPixelsIndex)++;
// If index is already in the list, generate a new number and check again.
while (i < *visitedPixelsIndex) {
if(index == visitedPixels[i]) {
index = rand() % im->height;
i = 0;
} else {
i++;
}
}
return index;
}
EDIT: im->height which is the image height is about 400-600 in average.

As far as I can see the code will generate an infinite loop when you insert the last free index into the array.
Assume that:
1) im->height is 500 so that valid index is in the range [0 .. 499]
2) You have already inserted 499 values, i.e. *visitedPixelsIndex is 499
So when the function is called this condition *visitedPixelsIndex == im->height will be false so you don't exit but continue on and you insert value number 500 in the array.
Then you do (*visitedPixelsIndex)++; so that *visitedPixelsIndex becomes 500.
After that you enter the while loop trying to find a new unused index. However - since you have already used all 500 valid index values, you'll never find an unused index.
In other words - an infinite loop
Maybe you should do:
(*visitedPixelsIndex)++;
if(*visitedPixelsIndex == im->height) {
perror("Cannot encode anymore: pixels limit reached");
exit(1);
}
I also think you should generate a new index before the while loop.
However, in general I think your code would be more clear if you split the current function into two functions. Like
int isPresent(int index, int *visitedPixels, int N)
{
for(int i = 0; i<N; ++i)
{
if (index == visitedPixels[i]) return 1;
}
return 0;
}
int getNewIndex(PPM *im, int index, int *visitedPixels, int *visitedPixelsIndex)
{
visitedPixels[*visitedPixelsIndex] = index;
(*visitedPixelsIndex)++;
if (*visitedPixelsIndex == im->height) {
perror("Cannot encode anymore: pixels limit reached");
exit(1);
}
do
{
index = rand() % im->height;
} while(isPresent(index, visitedPixels, *visitedPixelsIndex));
return index;
}

Related

Updating specific elements in C array

I'm having trouble conceptualising how to go about some of my code.
My C program wishes to compare each individual element of an array of structs aka arr_person[i].name against a user's input to see if there's a match. (i.e. if the user types in "Billy" and "Billy" is also a string in arr_person[].name array)
for(i=0;i<num_of_lines;i++)
{
if(strcmp(nameInput, arr_person[i].name)==0) {
printf("Match at element %d\n", i);
}
}
Then, a separate function finds reoccurring elements within arr_person[i].name by iterating through the array, and if the same name occurs twice, it will take the corresponding integer values of the same elemental positions and will add them up and store in new variable newChange. For example, if "Billy" occurs twice in the array, at arr_person[0].name and arr_person[4].name, and arr_person[0].number = 15 and arr_person[4].number = 10, then I want to update the number such that it becomes 25.
for(i = 0; i < num_of_lines; i++) {
for(j=0;j<num_of_lines;j++) {
if(strcmp(arr_person[j].name, arr_person[i].name)==0)
*newNumber = arr_person[i].number + arr_person[j].number;
}
}
How do I go about this so that any elements in the array that don't reoccur are still kept the same?
If the user inputs "Rachel" and Rachel only appears once in the array, and her corresponding number is 85, I want to print
Rachel 85
But if the user inputs "Billy" and Billy occurs twice, and he has the two numbers 10 and 15 as corresponding integers in another array, I want to print
Billy 25
I've only been programming for a few months. Thanks in advance.
Seems like the only thing you need to do is this:
int sum = 0;
for(int i=0;i<num_of_lines;i++)
{
if(strcmp(nameInput, arr_person[i].name)==0)
sum += arr_person[i].number;
}
I would structure it like this:
// Previous code from your post slightly modified to function
// returns -1 on no match and index otherwise
int match(struct person *arr_person, char *nameInput, int num_of_lines)
{
for(int i=0;i<num_of_lines;i++) {
if(strcmp(nameInput, arr_person[i].name)==0)
return i;
}
return -1;
}
int sum(struct person *arr_person, char *nameInput, int num_of_lines)
{
int sum = 0;
for(int i=0;i<num_of_lines;i++) {
if(strcmp(nameInput, arr_person[i].name)==0)
sum += arr_person[i].number;
}
return sum;
}
int main()
{
// Insert code for declaration and initialization
int index = match(arr_person, nameInput, num_of_lines);
if(index >= 0) {
printf("Match at element %d\n", index);
printf("%s %d\n", nameInput, sum(arr_person, nameInput, num_of_lines));
} else {
printf("No match\n");
}
}

How do I perform a linear search over this inventory array then the index of the matching item if it is found, -1 if it is not found?

Does my method look correct? I have a function called:
int searchInventory(const struct Item items[], const int sku_item,
const int size)
This function receives the address of an array of type Item (items[]), an integer for the sku number of the desired item, and an integer size representing the size of the array. I'm not sure if I used the flags correctly. Through the array I have to search for an item with the desired sku number and return the index of the matching item if it is found. If not found I have to return -1. New to this site, so I am not sure I have given all the needed info for you guys to help me. If you understand at all, please advise me.
for (i = 0; i < size; i++)
{
if (sku_item == items[i]._sku)
return i;
else
{
return -1;
}
}
for (i = 0; i < size; i++) {
if (sku_item == items[i]._sku) {
return i;
}
}
return -1;
You need to iterate over the whole array before declaring the item is not found. So move return -1 outside of the loop.

how to initialize array of unknown size in c

I am doing a homework assignment for an intro to programming class in c.
I need to write a program that looks at an int array of unknown size (we are given a initializer list as the test case to use), and determine all the duplicates in the array.
To make sure that an element that was already found to be a duplicate doesn't get tested, I want to use a parallel array to the original that would hold the numbers of all the elements that were duplicates.
I need this array to be the same size as the original array, which of course we don't really know till the initializer list is given to us.
I tried using sizeof() to achieve this, but visual studio says that is an error due to the variable size (const int size = sizeof(array1);) not being constant. Am I not using sizeof correctly? Or is this logic flawed?
Perhaps there is another way to approach this, but I have yet to come up with one.
Here is the code included below, hope the comments don't make it too hard to read.
// Dean Davis
// Cs 1325
// Dr. Paulk
// Duplicates hw
#include <stdio.h>
int main()
{
int array1[] = { 0,0,0,0,123,124,125,3000,3000,82,876,986,345,1990,2367,98,2,444,993,635,283,544, 923,18,543,777,234,549,864,39,97,986,986,1,2999,473,776,9,23,397,15,822,1927,1438,1937,1956,7, 29,- 1 };
const int size = sizeof(array1);
int holdelements[size];
int a = 0; // counter for the loop to initialize the hold elements array
int b = 0; // counter used to move through array1 and be the element number of the element being tested
int c = 0; // counter used to move through holdelements and check to see if the element b has already been tested or found as duplicates
int d = 0; // counter used to move through array1 and check to see if there are any duplicates
int e = 0; // counter used to hold place in hold element at the next element where a new element number would go. sorry if that makes no sense
int flag = 0; // used as a boolian to make sure then large while loop ends when we reach a negative one value.
int flag2 = 0; // used as a boolian to stop the second while loop from being infinite. stops the loop when the end of hold elements has been reached
int flag3 = 0; // used to close the third while loop; is a boolian
int numberofduplicates=0;// keeps track of the number of duplicates found
for (a; a < size; a++)
{
if (a == (size - 1))
holdelements[a] = -1;
else
holdelements[a] = -2;
}
while (!flag)
{
flag2 = 0;
flag3 = 0;
if (array1[b] == -1)
flag = 1;
else
{
while ((!flag) && (!flag2))
{
if (holdelements[c] == -1)
flag2 = 1;
else if (array1[b] == holdelements[c])
{
b++;
c = 0;
if (array1[b] == -1)
flag = 1;
}
}
while (!flag3)
{
if (array1[d] == -1)
flag3 = 1;
else if (array1[b] == array1[d] && b != d)
{
printf("Duplicate of %d, index %d, was found at index %d.\n", array1[b], b, d);
holdelements[e] = d;
d++;
e++;
numberofduplicates++;
}
}
}
b++;
}
printf("Total Duplicates Found: %d\n", numberofduplicates);
return 0;
}
redo to the following:
const int size = sizeof(array1)/sizeof(int);

How to simplify an extensive C if statement?

I am wondering what the best way is to approach this problem. I have a randomizing function set up that takes 8 strings as input and outputs a random one of them. I would like this randomizer to disregard all strings which have no value. For example, if I have strings text#, where # is 1-8, and let's say text5 and text7 have no text, then I want the randomizing function to check if any to use only use text#, where # is 1-8 but not 5 or 7.
Yikes! Put the strings in an array instead of having 8 different variables. Then use a for loop.
Count the list for valid strings.
Form random number (rand() % Count).
Find the matching string.
Sample code
int StringCount = 8;
char *String[StringCount];
// populate `Sting` somehow
// count valid strings
int Count = 0;
for (int i=0; i<StringCount; i++) {
if (ValidString(String[i])) Count++;
}
if (Count == 0) Handle_NoGoodStrings();
int random_number = rand()%Count;
int i;
for (i=0; i<StringCount; i++) {
if (ValidString(String[i])) {
if (Count == random_number) {
break;
}
}
}
// String[i] is the string
Put the strings in an array
Choose a random index into the array, using your random function
Use code similar to:
int i;
for (i = index; i != index; i = (i+1) % numitems)
{
/* check we have a string and it isn't empty */
if (strings[i] && *strings[i])
return strings[i];
}
return NULL;
assuming index is your random number between 0 and numitems -1.

Parsing Garbage Values Randomly Arrays

I am generating random values and parsing into arrays.
Any idea which part is causing the problem?
Thank you all in advance! :)
for(x=0; x<numberOfSboxes; x++)
{
vecCheck.clear();
for (y=0;y<sbox_Size; y++)
{
int secondTemp = y;
int firstTemp;
firstTemp = rand() % numberRange;
int mycount = (int) std::count (vecCheck.begin(), vecCheck.end(), y); // count if number is in vector
if( (mycount==1) || (firstTemp==y) )
{
continue;
}
else
{
if(vecCheck.size()==0)
{
vecCheck.push_back(firstTemp); // first number
sBox[x][y] = firstTemp;
sBox[x][firstTemp] = secondTemp;
vecCheck.push_back(secondTemp); //second number
}
else
{
int mycount = (int) std::count (vecCheck.begin(), vecCheck.end(), firstTemp); // count if number is in vector
if(mycount==1)
{
//if number generated is found, then break loop and restart
--y;
continue;
}
else
{
//if number generated is not found
sBox[x][y] = firstTemp; // first number generated
sBox[x][firstTemp] = secondTemp;
vecCheck.push_back(firstTemp); //push back to record
vecCheck.push_back(secondTemp); //push back to record
}
}
}
}
}
It does not always generate garbage values but sometimes it does.
An example is to be shown below.
sBox[0][16] = {9,12,15,5,7,3,12765952,4,13,0,11,10,1,8,12688216,2};
sBox[1][16] = {6,11,3,2,8,10,0,15,4,134514593,5,1,14,-1075,0,78827,12,7};
sBox[2][16] = {3,4,7,0,1,13,11,2,10,14,8,6,15,5,9,12};
I do not think it has a problem on the rand().
EDIT:
firstTemp generation has no issues. the numbers are always in the range of 0-15.
anyone knows why the output of the values tend to be of such stated above?

Resources