Is there a way to clear arrays completely? - c

"I am trying to find the size of the 'list[34]' array but it is being set by random numbers when the program is being initialised. I cannot remove the rand() function in main because that is part of the question and is just added back in by the solution checker when I submit.
I have tried setting all the values in the array to '0' but that throws out the 'list_size' variable if the list is shorter than 35 values since the list is just filled with whatever is parsed into it followed by '0' in all other values.
#include <stdlib.h>
#include <float.h>
// Declare Global variables here.
double list[34];
int list_size;
void array_stats() {
// Insert your solution here.
for(int i = 0; i <= 35; i++)
{
scanf("%lf", &list[i]);
list_size = i;
if (list[i] == 0)
{
break;
}
}
}
#include <stdlib.h>
#include <time.h>
int main() {
// Simulate the test setup process.
srand( time( NULL ) );
for ( int i = 0; i < 34; i++ ) {
list[i] = rand();
}
list_size = rand();
// Call submitted code.
array_stats();
// Display contents of array list.
for (int i = 0; i < list_size; i++) {
printf("%f ", list[i]);
}
printf("\n");
printf("Item count: %d\n", list_size);
return 0;
}```
Expected result for an empty string (echo '' | file_name) is 0
Actual result for an empty string (echo '' | file_name) is 34

If you you whould have used int datatype in your array:
memset(arr, 0, sizeof(arr));
But since your are not, it get's a bit tricky and to clear a double array the best way is:
double list[34];
for (size_t i = 0; i < list; ++i)
arr[i] = 0.0;
Theoretically, you should be safe using memset for floats and doubles, but see the caveats in the answers at Is it legal to use memset(,0,) on array of doubles? in case you have a non-standard floating point implementation.

Related

Double arrays in C

Im in the process of learning C and the basis of the class is C primer plus(6th edition). We use Eclipse as an IDE.
For an project we have to create to arrays. One array that takes numbers in a loop and another array that display the cumulative value. So if array 1 has values 1, 5 and 3(out of 10 inputs total) then the resulting input in array 2 should be 9(on the 3th input because of the 3 inputs in array 1).
Im having trouble getting started the right way - anyone here has ideas how I could proceed?
So far I have this for starters but forgive me for it it very weak:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
void doublearrays (double usernumber);
int main(void)
{
double usernumbers = 0.0;
int loop1 = 1;
while(loop1)
{
printf("Type numbers as doubles. \n");
fflush(stdout);
loop1 = scanf("%lf", &usernumber);
if(loop1)
{
doublearrays(usernumber);
}
}
return 0;
}
All the text in a homework assignment shall be read:
For a project we have to create two arrays... 10 inputs total...
Why on earth do not you declare them?... You already have defined SIZE so
double usernumbers[SIZE];
double cumulnumbers[SIZE];
Next do yourself a favour and handle one problem at a time:
One array that takes numbers in a loop...
Ok, so write a loop up to 10 reading floats directly into the array and note how many numbers were received
int n;
for(n=0; n<SIZE; n++) {
if (scanf("%lf", &usernumbers[n]) != 1) break;
}
// ok we now have n number in the first array
Let us go on
and another array that display the cumulative value.
Ok cumul is initially 0. and is incremented on each value from the first array:
double cumul = 0.;
for(int i=0; i<n; i++) {
cumul += usernumbers[i];
cumulnumbers[i] = cumul;
}
(your current code isn't what you need... delete it and then...)
anyone here has ideas how I could proceed?
Well the first step would be to actually define some arrays.
double input[SIZE];
double cum[SIZE];
The next step would be a loop to read input.
for (int i = 0; i < SIZE; ++i)
{
if (scanf("%lf", &input[i]) != 1)
{
// Input error - add error handling - or just exit
exit(1);
}
}
The next step is to add code for calculating the the cumulative value.
I'll leave that for you as an exercise.
The last step is to print the array which I also will leave to you as an exercise.
The straight forward way of doing this, which would also use two arrays and a loop construct would be to create something like this.. I've changed the doubles to integers. (and i am also ignoring any errors from scanf()).
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
static void
print_array(int *arr, const char *arr_name)
{
int i;
printf("%s = [");
for (i = 0; i < SIZE; i++)
printf("%d%s", arr[i], i < SIZE -1 ? ",":"");
printf("]\n");
}
int main(int argc, char **argv)
{
int i;
int input[SIZE];
int cumsum[SIZE];
for (i = 0; i < SIZE; i++)
{
int _input;
printf("Give me numbers!\n");
fflush(stdout);
scanf("%d", &_input); /* assuming integer */
input[i] = _input;
cumsum[i] = i > 0 ? cumsum[i-1] + _input : _input;
}
print_array(input, "input");
print_array(cumsum, "cumulative");
return 0;
}
or If you'd like to play around with pointers and have a bit more compact version.. perhaps this could be something to study to help you understand pointers, it does the same thing as my code above
#include <stdio.h>
#include <stdlib.h>
#define SIZE 10
static int data[SIZE*2];
int main(int argc, char *argv[])
{
int *input_p = &data[0];
int *cumsum_p = &data[0] + SIZE;
for (; input_p != &data[0] + SIZE; input_p++, cumsum_p++)
{
printf("Give me numbers!\n");
scanf("%d", input_p);
*cumsum_p = input_p == &data[0] ? *input_p : *(cumsum_p-1) + *input_p;
}
}

My code functions with a printf statement, but not without it

Adding the printf("Hi!\n") statements allows the code to work. It also works if the bound initial bound is improper and the user enters a new one. When I ran some tests calculate divers sometimes returned a character instead of an integer. I'm thinking it has something to do with my memory allocation. I also noticed that ./a.out 6 10 "|" would work but ./a.out 6 25 "|" would not causing an infinite loop when printing the lines of "|".
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// Structs
typedef struct data_struct {
int lineNumber;
int divisorSum;
char type[10];
}data;
// Prototypes
int calculateDivsors(int integer);
// Functions
int main (int argc, char *argv[]) {
int lowerBound;
int upperBound;
char character;
// Gets the values from command-line
sscanf(argv[1], "%d", &lowerBound);
sscanf(argv[2], "%d", &upperBound);
sscanf(argv[3], "%c", &character);
// Check to see if bound is proper
while (upperBound <= lowerBound || lowerBound < 2) {
printf("Error, please enter a new range (positive increasing).\n");
scanf("%d %d", &lowerBound, &upperBound);
}
// Structure calls
data* info = NULL;
int totalData = upperBound - lowerBound;
// Allocate the memory
info = (data*)malloc(totalData * sizeof(data));
printf("Hi!\n");
if (info != NULL) {
// Iterate through all the digits between the two bounds
for (int i = lowerBound; i <= upperBound; i++) {
int sum = calculateDivsors(i);
// Write data to indiviual structures
info[i].lineNumber = i;
info[i].divisorSum = sum;
// Check to see if the sum is greater than, less than, or equal to the original
if (sum == i) {
strcpy(info[i].type, "Perfect");
}
else if (sum > i) {
strcpy(info[i].type, "Abundant");
}
else if (sum < i) {
strcpy(info[i].type, "Deficient");
}
// Line n# has a column width of 4, string of 10
printf("%4d is %-10s\t", info[i].lineNumber, info[i].type);
// Generate Pictogram
for (int j = 0; j < info[i].divisorSum; j++) {
printf("%c", character);
}
printf("\n");
}
}
}
// Adds up the sum of diviors
int calculateDivsors(int integer) {
int sum = 0;
for (int i = 1; i < integer; i++) {
// Add to sum if perfectly i is a sum of integer
if (integer % i == 0) {
sum += i;
}
}
return sum; // Returns the sum of diviors
}
You are accessing data outside its allocated buffer whenever lowerBound doesn't start with 0.
info[i].lineNumber = i;
Ideally, you should become...
info[i - lowerBound].lineNumber = i;
To ensure that the indexing starts at 0. Further, your window between lowerBound and upperBound is inclusive. That means it includes both ending boundaries. Therefore, totalData is undersized by one element. Even if you fix the indexing problem, your code will still be wrong with this:
int totalData = (upperBound - lowerBound) + 1;
Failing to do both of the above causes your code to invoke undefined behavior (UB), and thus unpredictable results thereafter. It may even appear to work. That, however, is a red herring when your code has UB. Don't confuse defined behavior with observed behavior. You can trust the latter only once you have the former; the two are not synonymous.

Counting different numbers other than 0 (C) outputs different in different compilers

I am trying to find the number of distinct numbers from input which are not equal to 0. n is in 1-100 range. The numbers in the array are in the 0-600 range.
http://codeforces.com/problemset/problem/937/A
For this question, I wrote a code:
#include <stdio.h>
#include <string.h>
int main(void)
{
int n, count = 0, i;
scanf("%d", &n);
int ar[n], ar2[601];
memset(ar2, 0, 600 * sizeof(int));
for (i = 0; i < n; i++) {
scanf("%d ", &ar[i]);
if (ar2[ar[i]] == 0)
ar2[ar[i]] = 1;
}
for (i = 1; i < 601; i++) {
if (ar2[i] != 0)
count++;
}
printf("%d",count);
return 0;
}
for the first test case (4 1 3 3 2) , it outputs the right answer 3 in ideone.com 's gcc 6.3, but outputs 4 in gcc 5.1 which is used at codeforces.
Why does this happen, and how can I prevent this ?
(I think it's because of memset, but I'm not sure.)
You are defining an array of size n before the value of n has beed determined (note that you scanf the value of n later). This is undefined behaviour, such that different compilers may give different results, and even starting your program on your machine may give different results (including crashes).
instead of
int n, count = 0, i;
int ar[n];
...
write
int n, count = 0, i;
scanf("%d", &n);
int ar[n], ar2[601] = { 0 };
At least the malformed array should then be solved, and ar2 is completely initialized with 0. You can get rid of your memset, which initialized only 600 items (instead of 601) anyway.
Here is a quicker solution to the problem
#include <stdio.h>
int main()
{
bool seen_number_before[601] = { false };
int count = 0;
seen_number_before[0] = true;
int n;
scanf("%d", &n); // Should do error checking here
for (int i = 0; i < n; ++i) {
int v;
scanf("%d", v); // More error checking
if (!seen_number_before[v]) // Not seen it before
seen_number_before[v] = true; // Mark it as seen
++count; // Add to the count
}
}
printf("%d\n", count);
return 0;
}
}
There are some errors in your code, from a[n] when n is not defined.
To check errors try compiling with some useful options:
gcc -Wall code.c -o code -g
the -Wall is for Warning all and the -g is used for debug on valgrind (useful tool to check memory leak and other errors).
Also I suggest you to name properly every var in your code, could helpful for a large size of code base.
This is my solution,
#include <stdio.h>
#include <stdlib.h>
int main(){
int n, count = 0;
scanf("%d", &n);
int *a = malloc(n * sizeof(int));
int hash[600] = { 0 };
for(int i=0; i<n; i++){
scanf("%d ", &a[i]);
if(a[i] != 0){
hash[a[i]] = 1;
}
}
for(int i=0; i<600; i++){
printf("%d ", hash[i]);
if(hash[i] == 1) ++count;
}
printf("\n\n%d\n", count);
return 0;
}
it can be optimized in time, using only one for, and/or in memory by creating an hashset of int, and every int can store 32 bit and do some bitwise operations, so if the nth bit is 1, count++, otherwise don't do nothing.

how to print 5 unique strings from array of 10 strings

I am writing a code which will print 5 unique and random strings from an array of 10 strings. But my code doesn't print it uniquely, there are always some repetitions.
Here is my code, can anyone suggest how to make it print unique?
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void main(void){
char arr[10][10]={"abc","def","ghi","klm","nop","qrs","tuv","wxy","zab","cde"};
int i=0,j=0;
srand(time(0));
for(i=0;i<5;i++){
j=rand()%10;
printf("%d\n",j);
}
}
Just remember idices that have already been printed out:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
char arr[10][10] = {"abc","def","ghi","klm","nop","qrs","tuv","wxy","zab","cde"};
int i = 0, j = 0;
int done[10] = { 0 };
srand(time(0));
for (i = 0; i < 5; ++i)
{
do
{
j = rand()%10;
}
while (done[j] == 1);
done[j] = 1;
printf("%s\n", arr[j]);
}
return 0;
}
Your rand() function may evaluate to the same string index multiple times. There are different ways to resolve that. Most of them will be a take off on bit vector approach. You can create a Boolean array and initialize it to false. Whenever a number is printed, you can change the element in the Boolean array for that index to true. If an element is selected, you can check in the Boolean array if it has already been printed. If yes, you can regenerate the random number, or move to the next unprinted element, making sure that the corresponding Boolean entry is changed to true when you print that element.
Your random function gives the repetition, e.g. your dice throw '3' two time out of 4 throws.
What you could do to make it simple, create an array [0..9],
and let the random function swap a[i] with a[j].
Then you get a random permutation. Take the first 5 elements of the permutated array.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <time.h>
int main(){
char arr[10][10]={"abc","def","ghi","klm","nop","qrs","tuv","wxy","zab","cde"};
int found[10] = { 0 };
int i = 0,j = 0;
srand(time(NULL));
for(i = 0; i < 5; i++){
j = rand() % 10;
while(1){
if(!found[j]) break;
j = rand() % 10;
}
found[j] = 1;
printf("%s\n", arr[j]);
}
return 0;
}

Find missing number between 1 to 100

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);
}

Resources