This question already has answers here:
Are negative array indexes allowed in C?
(9 answers)
Closed 2 months ago.
I don't know why my program can't count from -5 to 19. Does anyone have a tip for me? Thanks a lot!
int printArray(int array[], int count){
for ( i = 0; i < count; i++)
{
printf("%d ", array[i]);
}
printf("\n");
}
int aufgabe4(int array[], int count){
for ( i = -5; i < 20; i++)
{
array[i] = i + 3;
}
}
int main (void){
printf("4.Aufgabe\n");
int data3[9] = {0};
aufgabe4(data3, 10);
printArray(&data3[0], 10);
}
The expected output should be -5 -2 1 4 7 10 13
16 19 be But the shell gives me 3 4 5 6 7 8 9 10 11 12.
I really don't know what is wrong because I calculate i + 3.
Answer 1:
If it does not, it is because you have undefined behaviour.
The undefined behaviour is caused by accessing outside of an array.
Which happens here array[i] = i + 3; for the cases of i being any of -5,-4,-3,-2,-1.
Answer 2:
This answer is not really the answer, because in the presence of undefined behaviour, all explanation attempts are moot.
It is however possible that among all those evil things which the compiler and runtime environment are allowed to do in case of undefined behaviour (basically EVERYTHING...) is the following:
this loop for ( i = -5; i < 20; i++) does indeed count from -5 to 19
this line array[i] = i + 3; inside that loop accesses first before the array (causing undefined behaviour) and later inside and writes values to illegal memory places (i.e. those you should not write to) and then into the array writes some values which are three higher than then counter i
later you print those values from index 0 to index 9, and get an output of them, each three higher than the corresponding index, i.e. what you observe
3,4,5,6,7,8,9,10,11,12
A few issues ...
In your example, writing to array[i] with a starting value for i of -5 is trying to write before the start of the array in main. This is UB (undefined behavior)
You are setting the array value to i + 3.
This does not increment/count by 3.
We want to use i and increment by 3
In main, the array has 9 elements, but we're passing 10 as a count.
The function does not check the array index against the count, so it relies on serendipity that the limit of the value will prevent overflow.
So, change:
for (i = -5; i < 20; i++) {
array[i] = i + 3;
}
Into:
for (int i = 0, j = -5; i < count; i++, j += 3)
array[i] = j;
Here is the corrected code. It is annotated:
#include <stdio.h>
int
printArray(int array[], int count)
{
for (int i = 0; i < count; i++) {
printf("%d ", array[i]);
}
printf("\n");
}
int
aufgabe4(int array[], int count)
{
// NOTE/BUG: this is indexing _before_ the start of the array so this is
// UB (undefined behavior)
// NOTE/BUG: we don't want "i + 3" -- we want to increment by 3
#if 0
for (int i = -5; i < 20; i++) {
array[i] = i + 3;
}
#else
for (int i = 0, j = -5; i < count; ++i, j += 3) {
array[i] = j;
}
#endif
}
int
main(void)
{
printf("4.Aufgabe\n");
// NOTE/BUG: too small for passed count value
#if 0
int data3[9] = { 0 };
#else
int data3[10] = { 0 };
#endif
aufgabe4(data3, 10);
printArray(&data3[0], 10);
return 0;
}
In the code above, I've used cpp conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Note: this can be cleaned up by running the file through unifdef -k
Related
I'm trying to accomplish a simple task in C which is to print out the smallest number from array 1 and smallest number from array 2. Both array elements are imputed by the user.
First one just returns 0 (which in my testing case its supposed to be 1) and the other one returns the correct one (11). I seriously can't understand why and I also tried to google this with no result so that's when I once again decided to seek help here!
int main () {
int masyvas1[10] = {0};
int masyvas2[10] = {0};
for(int i = 0; i < 10; i++){
int x;
printf("Ivesk pirmo masyvo 10 sk: ");
scanf("%d", &x);
masyvas1[i] = x;
}
for(int i = 0; i < 10; i++){
int x;
printf("Ivesk antro masyvo 10 sk: ");
scanf("%d", &x);
masyvas2[i] = x;
}
int mas1maz[2] = {0, 0};
for(int i = 0; i < 10; i++){
if(masyvas1[i] < mas1maz[1]){
mas1maz[1] = masyvas1[i];
}
if(masyvas2[i] < mas1maz[2]){
mas1maz[2] = masyvas2[i];
}
}
printf("testas: %d %d", mas1maz[1], mas1maz[2]);
}
If I enter numbers say from 1 to 10 for the first array and 11 to 20 for the second the program output is: testas: 0 11 which I was expecting it to be testas: 1 11
Thank you in advance!
I would like you to go over your program by trying what is below
int mas1maz[2] = {0, 0};
The Array has 2 elements, try to print each element.
Note: there are only 2 elements but I am printing 3 as you have used mas1maz[2] ( this is grabage= 11)
printf("%d,%d,%d",mas1maz[0],mas1maz[1],mas1maz[2]);
Then you are trying to compare with mas1maz[1]=0, this will result in a minimum always equal to zero.
for(int i = 0; i < 10; i++) {
/*
*/
if(masyvas1[i] < mas1maz[1]) {
mas1maz[1] = masyvas1[i];
}
Here you are tyring to compare mas1maz[2] with garbage=11, this is the reason why you see 11.
if(masyvas2[i] < mas1maz[2]) {
mas1maz[2] = masyvas2[i];
}
What you should try is the following :
for(int i = 0; i<9; i++) {
if(masyvas1[i]>masyvas1[i+1])
{
/*copy to your array*/
mas1maz[0]=masyvas1[i]
}
/* similarly for masyvas2*/
}
see that for an array of length len, indices of the array ranges from 0 to len-1
if(masyvas2[i] < masyvas2[i]){
mas1maz[2] = masyvas2[i];
}
Change your second if as follow. You was checking for smaller number in masmaz1 array and was passing 2 in array parameters which is not compatible. As you have initialized an array for 2 locations 0 and 1 as array locations are started from 0. So change that Second if to compare it with itself for smallest number.
int min;
int max;
int i;
min=max=mas1maz[0];
for(i=1; i<10; i++)
{
if(min>mas1maz[i])
min=mas1maz[i];
}
You should use this after you fill your tables with scanf to find the minimum value
then compare the two different minimums
I have an array of data, arr, and an array of indexes, index. My goal is to use a for loop to create new arrays of data partitioned at each of the indexes and to further find the minimum in each partitioned array. I am using malloc to create a dynamic array which I then free at the end of each loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
int j;
int arr[] = {1,3,4,6,7,8,12,87,89,12,34,43,54,67,81,2,0,10,23,45,81,23,89,23,56,81,28,79};
int index[] = {1,5,9,13,19,24};
int h = 27;
int k;
int c;
for(j = 0;j < h - 1;++j)
{
int *temp_arr = malloc(10*sizeof(int));
for(k = index[j];k<(index[j+1]);++k )
{
temp_arr[k] = arr[k];
}
int local_min ;
local_min = temp_arr[0];
for ( c = 1 ; c < sizeof(temp_arr) / sizeof(temp_arr[0]) ; c++ )
{ printf("Temp array %d ", temp_arr[c]);
if ( temp_arr[c] < local_min)
{
local_min = temp_arr[c];
printf("Local min in loop %d ", local_min );
}
}
free(temp_arr);
printf("\n");
}
return 0;
}
Unfortunately, the program is crashing without giving me any error messages. I think that I may have done something fundamentally wrong using malloc. Any suggestions on how to correctly do this would be greatly appreciated.
for(j = 0;j < h - 1;++j) // Where h = 27
It means j can be max 25
for(k = index[j];k<(index[j+1]);++k ) // If j = 25
You are touching index[26], while index has 6 elements.
for ( c = 1 ; c < sizeof(temp_arr) / sizeof(temp_arr[0]) ; c++ ) // Where int *temp_arr
temp_arr is pointer and sizeof(pointer) is always 8 on 64bit or 4 on 32bit system.
for(k = index[j];k<(index[j+1]);++k )
{
temp_arr[k] = arr[k]; // Where int index[] = {1,5,9,13,19,24};
}
If k is 13 or 19 or 24 you are ouside of bounds.
You should take a look at valgrind, and debug your code, step by step, expression by expression.
It appears that you forgot to inspect the output from Valgrind, which shows exactly where you use uninitialized values and where you run off the end of temp_arr.
Note also that temp_arr is a pointer type, and sizeof temp_arr is the size of that pointer, not the size of the array it points to.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
So Im creating a simple for loop within a for loop. The var frequecyCount is not resetting to 0, don't understand why.
I have going through to arrays x and hist array and need a counter variable to count the frequency of the same value in x as the position of hist.
#include <stdio.h>
void create_hist(double *x, int count, int *hist) {
int frequencyCount = 0;
for (int iHist = 0; iHist <= 5; iHist++) {
//initalize to zero
hist[iHist] = 0;
for (int ix = 0; ix < count; ix++) {
// convert to int
x[ix] = (int)x[ix];
if (x[ix] == hist[iHist]) {
frequencyCount++;
}
}
// add to the hist[] array the frequency count at position i
hist[iHist] = frequencyCount;
frequencyCount = 0;
}
int main( void ) {
double x[5] = {0, 0, 0, 0, 3};
int hist[5];
int count = 5;
create_hist(x, count, hist);
printf( "\tInput data:\n" );
for ( int i = 0; i < count; i++ ) {
printf( "\t%d\t%f\n", i, x[i] );
}
printf( "\tHistogram:\n" );
for ( int i = 0; i <= 5; i++ ) {
printf( "\t%d\t%d\n", i, hist[i] );
}
return 0;
}
Try this change:
for (int iHist = 0; iHist < 5; iHist++) { // <= changed to <
int frequencyCount = 0; // Moved this line to be inside the loop
The frequencyCount variable is resetting. There is another reason your output is not what you expect.
This if statement is most likely wrong:
if (x[ix] == hist[iHist]) {
frequencyCount++;
}
At this stage, hist[iHist] is always 0 (that's the value you assigned just before the loop).
I think you mean:
if (x[ix] == iHist) {
frequencyCount++;
}
You also need to change the loop range condtion from i <= 5 to i < 5 in main and from iHist <= 5 to iHist < 5 in create_hist to avoid buffer overflow.
Making these changes results in the output:
Input data:
0 0.000000
1 0.000000
2 0.000000
3 0.000000
4 3.000000
Histogram:
0 4
1 0
2 0
3 1
4 0
I have 2 arrays, in parallel:
defenders = {1,5,7,9,12,18};
attackers = {3,10,14,15,17,18};
Both are sorted, what I am trying to do is rearrange the defending array's values so that they win more games (defender[i] > attacker[i]) but I am having issues on how to swap the values in the defenders array. So in reality we are only working with the defenders array with respect to the attackers.
I have this but if anything it isn't shifting much and Im pretty sure I'm not doing it right. Its suppose to be a brute force method.
void rearrange(int* attackers, int* defenders, int size){
int i, c, j;
int temp;
for(i = 0; i<size; i++){
c = 0;
j = 0;
if(defenders[c]<attackers[j]){
temp = defenders[c+1];
defenders[c+1] = defenders[c];
defenders[c] = temp;
c++;
j++;
}
else
c++;
j++;
}
}
Edit: I did ask this question before, but I feel as if I worded it terribly, and didn't know how to "bump" the older post.
To be honest, I didn't look at your code, since I have to wake up in less than 2.30 hours to go to work, hope you won't have hard feelings for me.. :)
I implemented the algorithm proposed by Eugene Sh. Some links you may want to read first, before digging into the code:
qsort in C
qsort and structs
shortcircuiting
My approach:
Create merged array by scanning both att and def.
Sort merged array.
Refill def with values that satisfy the ad pattern.
Complete refilling def with the remaining values (that are
defeats)*.
*Steps 3 and 4 require two passes in my approach, maybe it can get better.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char c; // a for att and d for def
int v;
} pair;
void print(pair* array, int N);
void print_int_array(int* array, int N);
// function to be used by qsort()
int compar(const void* a, const void* b) {
pair *pair_a = (pair *)a;
pair *pair_b = (pair *)b;
if(pair_a->v == pair_b->v)
return pair_b->c - pair_a->c; // d has highest priority
return pair_a->v - pair_b->v;
}
int main(void) {
const int N = 6;
int def[] = {1, 5, 7, 9, 12, 18};
int att[] = {3, 10, 14, 15, 17, 18};
int i, j = 0;
// let's construct the merged array
pair merged_ar[2*N];
// scan the def array
for(i = 0; i < N; ++i) {
merged_ar[i].c = 'd';
merged_ar[i].v = def[i];
}
// scan the att array
for(i = N; i < 2 * N; ++i) {
merged_ar[i].c = 'a';
merged_ar[i].v = att[j++]; // watch out for the pointers
// 'merged_ar' is bigger than 'att'
}
// sort the merged array
qsort(merged_ar, 2 * N, sizeof(pair), compar);
print(merged_ar, 2 * N);
// scan the merged array
// to collect the patterns
j = 0;
// first pass to collect the patterns ad
for(i = 0; i < 2 * N; ++i) {
// if pattern found
if(merged_ar[i].c == 'a' && // first letter of pattern
i < 2 * N - 1 && // check that I am not the last element
merged_ar[i + 1].c == 'd') { // second letter of the pattern
def[j++] = merged_ar[i + 1].v; // fill-in `def` array
merged_ar[i + 1].c = 'u'; // mark that value as used
}
}
// second pass to collect the cases were 'def' loses
for(i = 0; i < 2 * N; ++i) {
// 'a' is for the 'att' and 'u' is already in 'def'
if(merged_ar[i].c == 'd') {
def[j++] = merged_ar[i].v;
}
}
print_int_array(def, N);
return 0;
}
void print_int_array(int* array, int N) {
int i;
for(i = 0; i < N; ++i) {
printf("%d ", array[i]);
}
printf("\n");
}
void print(pair* array, int N) {
int i;
for(i = 0; i < N; ++i) {
printf("%c %d\n", array[i].c, array[i].v);
}
}
Output:
gsamaras#gsamaras:~$ gcc -Wall px.c
gsamaras#gsamaras:~$ ./a.out
d 1
a 3
d 5
d 7
d 9
a 10
d 12
a 14
a 15
a 17
d 18
a 18
5 12 18 1 7 9
The problem is that you are resetting c and j to zero on each iteration of the loop. Consequently, you are only ever comparing the first value in each array.
Another problem is that you will read one past the end of the defenders array in the case that the last value of defenders array is less than last value of attackers array.
Another problem or maybe just oddity is that you are incrementing both c and j in both branches of the if-statement. If this is what you actually want, then c and j are useless and you can just use i.
I would offer you some updated code, but there is not a good enough description of what you are trying to achieve; I can only point out the problems that are apparent.
This question has been asked here on SO before with below code
find3missing(int* array)
{
int newarray[100] = {0};
For i = 0 to 99
++newarray[array[i]] ;
For i = 0 to 99
If newarray[i] != 1
Cout << “the missing number is ” << i+1 << endl ;
}
But when I checked this code, it doesn't seem to work. Suppose I have an array of {1,2,6}. The output should be 3,4,5 but with the code above I get 1,4,5,6 instead. Below is my implementation of pseudo code with array size 6.
main()
{
int a[6]={1,2,6};
int tmp[6]={0},i;
for(i=0;i<6;i++)
{
++tmp[a[i]];
}
for(i=0;i<6;i++)
{
if(tmp[i]!=1)
{
printf("%d",i+1);
}
}
}
Is this the right code?
This ++newarray[array[i]] should be ++newarray[array[i] - 1]. This because you are interested in a sequence of 1-100 numbers, so no 0, but C arrays are 0 based. If you then look at the cout: the missing number is ” << i+1 here you "unshift" the number by adding 1.
There is another problem: you should pass the number of elements of the array, something like:
find3missing(int* array, int length) {
int newarray[100] = {0};
for (int i = 0; i < length; i++) {
++newarray[array[i] - 1] ;
}
C/C++ arrays are zero based, as A[i] is equivalent to *(A+i). So change ++newarray[array[i]] to ++newarray[array[i]-1]. Also use malloc, free and memset to use an array of dynamic size.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void find3missing(int* pArray, size_t size, int min, int max){
int* newarray;
int i;
unsigned int j;
int range = max - min;
if(range < 0)
return;
newarray = (int*) malloc(range*sizeof(int)); // allocate enough memory
memset(newarray,0,range*sizeof(int)); // set that block to zero
for(j = 0; j < size; ++j){
++newarray[pArray[j]-min];
}
for(i = 0; i < range; ++i){
if(!newarray[i])
printf("%d is missing!\n",min+i);
}
free(newarray);
}
int main(){
int test[] = {1,3,6};
find3missing(test,sizeof(test)/sizeof(int),1,6);
return 0;
}
Please note that this solution is very inefficient if your array is sorted. In this case have a look at Jimmy Gustafsson's answer.
This algoritm will be quite simple, since you're using a sorted array. Simply check if the current value +1 equals the nextvalue like below:
find3missing(){
int array[arraySize]; // the array with integers
for(i=0;i<arraySize;i++)
if(array[i]+1 != array[i+1]) // if value array[i]+1 is not equal the next index
// value, then it's a missing number
printf("A missing number: %i", i+1);
}