I am trying to solve a question.
If in array a number is duplicated I make him 0. My code is throwing an error could you please help me ?
#include <stdio.h>
int main() {
int a[] = {-3, -2, -1, -7, -3, 2, 3, 4, 2, 7, 10, 3};
int length = 12;
int zero_duplicates(int laenge, int *a) {
int zero[] = {};
int k = 0;
int j = 1;
for(int x=0; x<laenge; x++)
{
if (zero[*a] == 1) {
*a = 0;
} else {
zero[*a] = 1;
k++;
}
a++;
}
return k;
}
int count = zero_duplicates(length, a);
printf("%d -- ", count);
for(int i = 0; i < length; i++) printf(" %i ", a[i]);
return 0;
}
This ...
int zero[] = {};
... is not a valid array declaration in C. If your compiler accepts it as an extension then it ought at least to be emitting a warning, and even then it probably doesn't mean what you think it means. Specifically, among the most likely extensions would be to interpret that as declaring a zero-length array (which also would constitute an extension), such that accessing any element overruns the array bounds.
Moreover, no matter how long the array is, if any of the elements of the input array are negative (as is the case in the example) then zero[*a] will constitute an out-of-bounds access when a points to one of those elements.
Overall, you need a different approach. What you're trying to do is not viable.
As a separate matter, C does not support nested functions, so your code is relying on yet another extension in that respect. This particular issue can be resolved by lifting the nested function out of main(), however, putting it above instead of inside.
Related
#include "stdio.h"
int printsomething(int *array, int arrayreturn[5]) {
int i;
for(i = 0; i < 10; ++i) {
printf("%d\n", array[i]);
}
for(i = 0; i < 5; ++i) {
int &arrayreturn[i] = {i};
}
return 0;
}
int main() {
int array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// int *arraypointer = &array;
int arrayp[5];
int i;
printsomething(array, arrayp);
for(i = 0; i < 5; ++i) {
printf("%d\n", arrayp[i]);
}
return 0;
}
I am learning C and right now just playing with arrays and pointers trying to get comfortable. This bit of code has the goal of passing an array to a function, which was successful before I added the second part. That second part being assigning values in the called function to an already initialized array. Since we can't directly return an array I understood this was the way to do it. What exactly do you all think is going wrong here? And I just completely off the target?
If you want to assign values to the array elements you need to use [] to access the elements and = to assign them. I cannot really explain your code because it is unclear how you came to the conclusion that you need to write int &arrayreturn[i] = {i};. Your loop can be this:
for(i = 0; i < 5; ++i) {
arrayreturn[i] = i;
}
the first problem is that when you have a parameter of the form int arrayreturn[5] you actually just pass an int pointer not an entire array of 5 elements. int arrayreturn[5] and int *arrayreturn compile to exactly the same cpu instructions. I never use the int arrayreturn[5] syntax because i think it is confusing so i rather just pass a pointer and this is common practice as far as i know.
secondly in the second part of your code you try to declare a new array of size i by calling int &arrayreturn[i] = {i} this is not possible because of multiple reasons mostly because you cant dynamically allocate arrays on the stack. it should be arrayreturn[i] = i
Should I be using a long for the array or a float?
Should I be making the array size larger?
When I use a larger array, say for instance 12 numbers, the program does not abort but instead prints a minus figure as the first item when its been sorted.
I know this is a memory issue but I'm just not entirely sure how to fix it.
Some explanation would be great!
PS. I am new to C. I don't remember encountering any issues like this with python.
#include <stdio.h>
void print_grades();
void average();
void swap();
void bubble_swap();
int main()
{
const int SIZE = 10;
int grades[SIZE] = { 67, 56, 65, 76, 32, 14, 59, 34, 6, 77 };
print_grades(grades, SIZE);
average(grades, SIZE);
bubble_swap(grades, SIZE);
return 0;
}
// This function prints the array
void print_grades(int grades[], int size)
{
int i;
printf("My grades are:\n");
for (i = 0; i < size; i++)
{
printf("%i\t", grades[i]);
}
}
// This function calculates the average of the array
void average(int grades[], int size)
{
int i;
double sum = 0.0, average;
printf("\nMy average grade is: ");
for (i = 0; i < size; i++)
{
sum += grades[i];
}
printf("%.1f\n", sum/size);
}
// This function swaps two ints
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
// This is the bubble sort function.
void bubble_swap(int grades[], int size)
{
int i, j;
for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
{
if (grades[j] < grades[j+1])
{
NULL;
}
else
{
swap(&grades[j], &grades[j+1]);
}
}
printf("\nMy sorted grades are:\n");
for (i = 0; i < size; i++)
{
printf("%i\t", grades[i]);
}
}
Bubble sort is working correctly but sometimes it aborts
That's like the definition of "not working correctly".
PS. I am new to C. I don't remember encountering any issues like this with python.
Python has an entirely different philosophy to C: Python tries to be friendly, and does lots of checking for you. If there is a bug, you'll probably get a helpful exception that points you to the place it went wrong.
C tries to be fast and assumes you know what you're doing. It doesn't check anything because checks take time (and if you do know what you're doing, you either don't need them or can write them yourself). You shouldn't rely on the compiler catching any errors for you at all, by default.
However, you can and should enable lots of compiler warnings that aren't on by default (something like -Wall -Werror -Wextra for GCC or clang will perform a lot more static checking without slowing down the compiled executable).
I know this is a memory issue but I'm just not entirely sure how to fix it.
Because C is relatively unfriendly, there are plenty of tools to help. They're just not running by default because they make the program slower.
You can try running your program as-is under valgrind, or you can rebuild it with an address sanitizer, if your compiler offers one. Either will give you a lot of information about what is happening.
Should I be using a long for the array or a float?
You should use the type you need. Use float or double if you actually need fractional numbers. It won't fix your current problem anyway.
Should I be making the array size larger?
Ideally you want to have a hypothesis about what's actually going wrong before you start randomly changing things.
const int SIZE = 10;
int grades[SIZE] = { 67, 56, 65, 76, 32, 14, 59, 34, 6, 77 };
Writing it this way makes it really easy to accidentally mismatch SIZE and the number of elements. It's idiomatic to use
int grades[] = { 67, 56, 65, 76, 32, 14, 59, 34, 6, 77 };
const size_t ngrades = sizeof(grades)/sizeof(grades[0]);
(or wrap it in a macro like #define NELEM(a) (sizeof(a)/sizeof(a[0])))
and learning idiomatic C is just as useful as writing Pythonic Python.
Canonically, bubble sort should run until no elements are exchanged. So, this outer loop:
for (i = 0; i < size; i++)
is wrong (although it's not the source of your memory bug).
Just reading the sort function, lines like
if (grades[j] < grades[j+1])
jump out as possible problems. When j==size-1 on the last iteration, you're looking at grades[size] which is out of bounds.
As an aside, the statement NULL; doesn't do anything, but it's not idiomatic, and there isn't really an equivalent of Python's pass. Maybe write ; /* NO OP */ or something to indicate a deliberately empty statement (or just reverse the if statement and omit it entirely).
Anyway, the key fix is just reducing the loop upper bound by 1. Either valgrind or an address sanitizer would have shown you going off the end of the array directly. With the outer condition corrected as well, it looks something like:
void bubblesort(int *a, size_t n)
{
bool swapped = false;
do {
swapped = false;
for (size_t i = 0; i < n - 1; i++) {
if (a[i] > a[i+1]) {
swapped = true;
swap(&a[i], &a[i+1]);
}
}
} while(swapped);
}
There are multiple problems in your code:
The inner loop runs one time too many: when j reaches the value size - 1, you compare grades[j] and grades[j+1] which is beyond the end if the array. If memory at this location can be read and happens to contain a lesser value, this will be swapped into the array and may appear in the sorted output (the negative value you observe). Note however that reading beyond the end of the array has undefined behavior, and even more so for writing, potentially causing some important data such as the function return address to become corrupted, so anything can happen (as you observe sometimes) and nothing can be predicted or expected.
To avoid accessing an element beyond the end of the grades array, instead of for (j = 0; j < size; j++) you should write:
for (j = 0; j < size - 1; j++)
The function prototypes should include the argument lists.
void print_grades(int grades[], int size);
void average(int grades[], int size);
void swap(int *a, int *b);
void bubble_swap(int grades[], int size);
Also note that an array with a variable length cannot be initialized in C: even though SIZE is defined as a const variable, int grades[SIZE] defines a variable length array (VLA), which the C Standard says cannot have an initializer. You either rely on a compiler extension or compile your program as C++, for which SIZE is really defined as a constant. You should define the array without a length and define SIZE as the array length measured from its actual size:
int grades[] = { 67, 56, 65, 76, 32, 14, 59, 34, 6, 77 };
const int SIZE = sizeof(grades) / sizeof(grades[0]);
Here is a modified version:
#include <stdio.h>
void print_grades(const int grades[], int size);
void average(const int grades[], int size);
void swap(int *a, int *b);
void bubble_swap(int grades[], int size);
int main() {
int grades[] = { 67, 56, 65, 76, 32, 14, 59, 34, 6, 77 };
const int SIZE = sizeof(grades) / sizeof(grades[0]);
print_grades(grades, SIZE);
average(grades, SIZE);
bubble_swap(grades, SIZE);
return 0;
}
// This function prints the array
void print_grades(const int grades[], int size) {
printf("My grades are:\n");
for (int i = 0; i < size; i++) {
printf("%i\t", grades[i]);
}
printf("\n");
}
// This function calculates the average of the array
void average(const int grades[], int size) {
double sum = 0.0;
for (int i = 0; i < size; i++) {
sum += grades[i];
}
printf("\nMy average grade is: %.1f\n", sum / size);
}
// This function swaps two ints
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// This is the bubble sort function.
void bubble_swap(int grades[], int size) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size - 1; j++) {
if (grades[j] > grades[j + 1]) {
swap(&grades[j], &grades[j + 1]);
}
}
}
printf("\nMy sorted grades are:\n");
for (int i = 0; i < size; i++) {
printf("%i\t", grades[i]);
}
printf("\n");
}
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
void check(int n, int arr[]);
int arr[] = {1, 2, 3, 4};
int i;
check(4, arr);
for (i = 0; i < 4; i++) {
printf("%d\n", arr[i]);
}
return 0;
}
void check(int n, int arr[]) {
int i = 0;
int *p = 0;
while (i++ < n)
p = &arr[i];
*p = 0;
}
I need an explanation for the output.
The original question I was asked, and the expected multiple-choice answers, are:
Please post your actual code, not what you intended to type. Actually copy-paste your real code.
Because you typed it in wrong.
You either put extra {} in here:
while(i++ < n) {
p = &arr[i];
*p = 0;
}
or you used a comma instead of a semicolon:
while(i++ < n)
p = &arr[i],
*p = 0;
and so the assignment to zero ran every time.
Edit to add: Yep, you put extra {} which the original question didn't have. So in your code, the "*p = 0" executes every time round the while loop, whereas the original question the "*p = 0" only executes once and clobbers some random data that is one past the end of the array.
(By the way, the answer to the original question is actually "it is undefined behaviour; the program doesn't necessarily print anything. Valid behaviours include printing 1 2 3 4, printing 42 42 42 42, crashing, and formatting your hard drive.")
I'm not sure what choices you're talking about, however the cause of your output is here:
int i=0;
int *p=0
while(i++<n)
{
p=&arr[i];
*p=0;
}
Variable 'i' starts at 0 but you increment it before entering the loop so the first index of the array is ignored. You then set a pointer to array index 'i' and then immediately dereference the pointer and set the value to 0;
Because of this any array you pass will always retain its first value whilst every other value will be zero.
if you want to include the first index of the array you'd be much better off doing:
for (int i = 0; i < n; ++i)
{
// stuff
}
With this, 'i' is not incremented until after the code between the braces has been executed.
In check(), i gets incremented after the comparison, but before the first statement inside. So the zero (first) element of the array is never set to 0, like the rest are. arr's 1 stays 1, and 2, 3, & 4 each become 0.
EDIT:
The OP code has changed since the version I discussed. It's a whole new problem now.
Some things you should know.
First:
you should declare your functions if you declare/define them after main.
Second:
when you declare an Array, the array starts from 0 to n and not from 1 to n.
So, if you declare int arr = {1,2,3,4} then you have arr[0],1,2,3 and not arr[1],2,3,4.
Third:
you should avoid code like:
while (i++ < n) {
p = &arr[i];
*p = 0;
}
And use:
while (i < n) {
p = &arr[i];
*p = 0;
i++;
}
Fourth:
What exactly did you expected from this:
int *p = 0;
Anyway, you just try to access a memory location that not belong to you.
when I am compiling this small program I am getting different values as output, instead of getting numbers from 0 to 5. And the size of array is always 8. The different values I am getting are:
-981774704
32767
0
0
4195728
0
Any tips would be really valuable. Thank you
#include <stdio.h>
int main() {
int array[10];
int i;
for (i = 0; i < 6; i++) {
printf("%d\n", array[i]);
}
int z = sizeof(&array);
printf("\n Size of array is %d", z);
return 0;
}
You aren't assigning any values to the array, so you're getting the uninitialized values.
You need to do something like array[0] = 5; //or some value etc.
If you want an array of size 8, with the numbers indexing the array stored in it, so {0, 1, 2, 3, 4, 5, 6, 7}, you could do something like:
int array[8];
for(int i = 0; i < 8; ++i)
{
array[i] = i;
}
the elements of the array are uninitialized therefore it's printing garbage value...first initialize the elements with values...you can do this...
#include<stdio.h>
int main()
{
int array[10] ;
int i;
for (i = 0; i < 6; i++)
{
array[i]=i;
printf("%d\n", array[i]);
}
int z = sizeof(&array);
printf("\n Size of array is %d", z);
return 0;
}
if you want the array to be initialized automatically then declare the array globally...
if you want to get the size of the whole array remove &
sizeof(array);
C will not initialize your array to any default value. When you create the array it will be full of garbage values (nothing relevant or defined). Always initialize your data using memset or something equivalnet.
So if you are expecting a value of 0 on a new array then initialize it like this:
memset(array, 0, sizeof(array));
you have to initialize your array first, memory may not be filled with 0 by default
Being able to define an array e.g.
int a[] = {1,2,3};
is very convenient, however, the array a is an r-value so I can't subsequently change the values in a, e.g.
a[] = {4,5,6};
The context for wanting to do this is writing a bunch of unit tests where I am feeding in arrays to functions and testing the outputs. I'm running tests on the same function with different inputs and would like to avoid having to have unique names for my input arrays, e.g. I'm having to do this:
int test1_a[] = {1,2,3};
/* calls to functions */
int test2_a[] = {4,5,6};
/* calls to functions */
Also, if I want to pass a pointer to an array into a function I have to 1st cast it like this:
int a[] = {1,2,3};
int *b = a;
my_func(&b);
passing a pointer to an r-value like this doesn't work:
my_func(&a);
My question is whether there is any other way to easily initialise an array of values without suffering from these limitations? (particularly with a view to making it easy to write many similar unit tests without each test having a unique set of array names)
If you already have the values you want to pass to the functions, why not use a multi-dimensional array?
int a[][] = {
{ 1, 2, 3 },
{ 4, 5, 6 }
}
for (int i = 0; i < 2; i++)
{
/* Call functions with 'a[i]' as argument */
}
Also, if the functions you call expect an array, and you have a e.g. int a[] = {...}; int *b = a;, then don't call them with &b. Using &b passes the address of the pointer, not what it points to.
If i have understood your question properly.I guess the following should solve your problem.
memcpy(a, (int[]){3, 2, 1}, sizeof a);
Only if your c compiler supports compound literals(c99 onwards).
To specify the standard, gcc can be invoked as "gcc -std=c99 -Wall -pedantic".
Here's one option:
#include <stdio.h>
#include <stdarg.h>
void ReinitArray(int* p, size_t cnt, ...)
{
va_list ap;
va_start(ap, cnt);
while (cnt--)
{
*p++ = va_arg(ap, int);
}
va_end(ap);
}
int array[5] = { 1, 2, 3, 4, 5 };
int main(void)
{
size_t i;
printf("array[5]=");
for (i = 0; i < 5; i++) printf("%d ", array[i]);
printf("\n");
ReinitArray(array, 5, 11, 22, 33, 44, 55);
printf("array[5]=");
for (i = 0; i < 5; i++) printf("%d ", array[i]);
printf("\n");
return 0;
}
Output:
array[5]=1 2 3 4 5
array[5]=11 22 33 44 55
And you can simply write my_func(a); where a is an array name. This will be equivalent to passing &a[0], the address of the very first array element. You can't pass entire arrays directly as function parameters in C.