I am trying to implement a set ADT using dynamic arrays. I have a set for odd and even numbers. When a array is full I use realloc to get a bigger array.
The problem is that this also seems to fill the array with unwanted numbers.
struct set
{
void **array;
int numitems;
int maxitems;
cmpfunc_t cmpfunc;
};
.
void set_add(set_t *set, void *elem)
{
if (!set_contains(set, elem))
{
if (set->numitems + 1 >= set->maxitems) // Make new bigger array if full
{
void **new_array = realloc(set->array, sizeof(void *) * set->maxitems * 2);
if (new_array == NULL)
printf("Error");
set->maxitems *= 2;
set->array = new_array;
}
set->array[set->numitems] = elem;
set->numitems++;
}
}
In main i use this to add numbers.
for (i = 0; i <= n; i++) {
if (i % 2 == 0)
set_add(evens, numbers[i]);
else
{
printset("Odd numbers":, odds);
set_add(odds, numbers[i]);
}
}
This is the output I get.
Output:
Odd numbers: 1
Odd numbers: 1 3
Odd numbers: 1 3 5
...
Odd numbers: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29
Odd numbers: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
Odd numbers: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Odd numbers: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 18 19 20 21 22 23 24 25 26 27 28 29 30
...
After 31 is added, the array maxsize (=16) is doubled. Any ideas what causes the rest of the array to be filled? This is just a small part of the code, so if nothing here seems to be the cause I can post more.
=== Addition info: ===
static void printset(char *prefix, set_t *set)
{
set_iter_t *it;
printf("%s", prefix);
it = set_createiter(set);
while (set_hasnext(it)) {
int *p = set_next(it);
printf(" %d", *p);
}
printf("\n");
set_destroyiter(it);
}
.
set_iter_t *set_createiter(set_t *set)
{
set_iter_t *iter = malloc(sizeof(set_iter_t));
if (iter == NULL)
return NULL;
bobsort(set);
iter->set = set;
iter->cur = 0;
return iter;
}
int set_hasnext(set_iter_t *iter)
{
if (iter->set->array[iter->cur] == NULL)
return 0;
else
return 1;
}
void *set_next(set_iter_t *iter)
{
if (iter->set->array[iter->cur] == NULL)
return NULL;
else
{
void *elem = iter->set->array[iter->cur];
iter->cur++;
return elem;
}
}
It's for an assignment, so I'm following the function signatures. I'm used to make adt list with linked list and not arrays.
In function set_add you should change the if condition:
if (set->numitems + 1 >= set->maxitems) // Make new bigger array if full
to
if (set->numitems >= set->maxitems) // Make new bigger array if full
Let's look at the definition of realloc(): The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size is larger than the old size, the added memory will not be initialized.
So I believe you shouldn't use if (iter->set->array[iter->cur] == NULL) in set_hasnext(set_iter_t *iter) as you didn't initialize the re-allocate array to NULL. In another word, the value in the array may be random.
The 2 two changes that fix my issue:
In add_set(), change
if (set->numitems + 1 >= set->maxitems)
to
if (set->numitems >= set->maxitems)
And in set_hasnext(), change
if (iter->set->array[iter->cur] == NULL)
to
if (iter->cur >= iter->set->numitems)
Thanks to Tran and Anthony.
Related
I have created a program to search for prime numbers. It works without problems until the entered number is smaller than 52, when it is bigger output prints out some blank (0) numbers and I don't know why. Also other numbers have blank output.
My code is:
#include <stdio.h> //Prime numbers
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
int c[100], n, a[50], d, e, b = 1;
void sort() {
for (int i = 1; i < n; i++) {
if (c[i] > 1) {
a[b] = c[i];
printf("%d %d %d\n", a[1], b, i);
b++;
e = 2;
d = 0;
while (d <= n) {
d = c[i] * e;
c[d - 1] = 0;
e++;
}
}
}
}
int main() {
printf("Enter number as an limit:\n");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
c[i] = i + 1;
}
sort();
printf("Prime numbers between 1 and %d are:\n", n);
for (int i = 1; i < b; i++) {
printf("%d ", a[i]);
}
return 0;
}
Here is output for 25:
Enter number as an limit:
25
2 1 1
2 2 2
2 3 4
2 4 6
2 5 10
2 6 12
2 7 16
2 8 18
2 9 22
Prime numbers between 1 and 25 are:
2 3 5 7 11 13 17 19 23
But for 83 is:
Enter number as an limit:
83
2 1 1
2 2 2
2 3 4
2 4 6
2 5 10
2 6 12
2 7 16
2 8 18
2 9 22
2 10 28
2 11 30
2 12 36
2 13 40
2 14 42
2 15 46
2 16 52
0 17 58
0 18 60
0 19 66
0 20 70
0 21 72
0 22 78
0 23 82
Prime numbers between 1 and 83 are:
0 3 5 7 11 0 17 19 23 29 31 37 0 43 47 53 0 61 67 71 73 79 83
Blank spots always spots after 17th prime number. And always the blank numbers are the same. Can you help me please what is the problem?
The loop setting entries in c for multiples of c[i] runs too far: you should compute the next d before comparing against n:
for (d = c[i] * 2; d <= n; d += c[i]) {
c[d - 1] = 0;
}
As a matter of fact you could start at d = c[i] * c[i] because all lower multiples have already been seen during the previous iterations of the outer loop.
Also note that it is confusing to store i + 1 into c[i]: the code would be simpler with an array of booleans holding 1 for prime numbers and 0 for composite.
Here is a modified version:
#include <stdio.h>
int main() {
unsigned char c[101];
int a[50];
int n, b = 0;
printf("Enter number as a limit:\n");
if (scanf("%d", &n) != 1 || n < 0 || n > 100) {
printf("invalid input\n");
return 1;
}
for (int i = 0; i < n; i++) {
c[i] = 1;
}
for (int i = 2; i < n; i++) {
if (c[i] != 0) {
a[b] = i;
//printf("%d %d %d\n", a[0], b, i);
b++;
for (int d = i * i; d <= n; d += i) {
c[d] = 0;
}
}
}
printf("Prime numbers between 1 and %d are:\n", n);
for (int i = 0; i < b; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
Output:
chqrlie$ ./sieve4780
Enter number as a limit:
25
Prime numbers between 1 and 25 are:
2 3 5 7 11 13 17 19 23
chqrlie$ ./sieve4780
Enter number as a limit:
83
Prime numbers between 1 and 83 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79
Your problem seems to be caused by the fact that you have declared an array with size 50, but in fact it goes further than that: imagine you want to use Eratosthenes' procedure to find the first 10,000 prime numbers. Does this mean that you need to declare an array of size 10,000 first (or even bigger), risking to blow up your memory?
No: best thing to do is to work with collections where you don't need to set the maximum size at declaration time, like a linked list, a vector, ..., like that you can make your list grow as much as you like during runtime.
I am writing a program that takes the 1st day of a month and number of days in a month and prints the relevant calendar.
If I enter 3 and 30 it should print
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
This is the code I wrote
#include <stdio.h>
void printclndr();
int main(){
int first,days;
first = firstday();
if(first<1||first>7)
{
printf("%d is not a valid day. Try again. \n",first);
firstday();
}
days = monthdays();
if(days<28||days>31)
{
printf("Retry. Enter days for a valid month. \n");
monthdays();
}
printf("\n");
printclndr(first,days);
printf("\n\n");
main();
}
void printclndr(int day1, int numdays){
int date,check,count,tab;
check = day1 + numdays;
tab = 0;
for(count=1;count<check;count++)
{
if(count<day1)
{
printf("\t");
tab+=1;
}
if(count>=day1)
{
printf("%d\t",count-day1+1);
tab+=1;
}
if(tab==7)
{
printf("\n");
tab=0;
}
}
}
int firstday(){ //function to get the starting day of the month
int day; //initializing local variables
printf("First day of the month (1= Sun, 7= Sat): ");
scanf("%d",&day);
return day; //returns the value of day
}
int monthdays(){ //function to get no of days in a month
int days; //local variables
printf("Number of days in the month: ");
scanf("%d",&days);
return days;
}
firstday and monthdays scanf user inputs and are working fine. My code works and prints the calender. Now I want to rightalign my calender.
I want
1
8
15
instead of
1
8
15
How do I do it?
When you are printing the calendar use printf("%nd",number); n is a maximum number of decimal places, in your case n=2, printf("%2d\t",count-day1+1);;
This right-justifies the numbers as requested.
#include <stdio.h>
void printclndr(int day1, int numdays){
int day, count;
for(count = 1; count < day1-1; count++) { // initial padding
printf("\t");
}
count = day1 - 1;
for(day = 1; day <= numdays; day++) {
if(count >= 7) {
printf("\n");
count = 0;
}
else if(count > 0) {
printf("\t");
}
printf("%2d", day);
count++;
}
printf("\n");
}
int main(){
printclndr(3, 30);
printf("\n");
printclndr(1, 28);
printf("\n");
printclndr(2, 28);
return 0;
}
Program output:
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28
I used "%2d\t" and got the center aligned result.
Then I tried ("%*d/t",2,count-day1+1) and got the same result.
Then I downloaded Eclipse on which with some difficulty ran all the codes including #WeatherVane 's and voila!! I was using CodeLite in my Mac.
This question already has answers here:
Function to left shift a 2D array in C
(3 answers)
Closed 8 years ago.
I am learning how to manipulate a 2D array in C and I have to apply a left shift to a matrix, so A[0][0] becomes the value at A[0][1] etc. This is the code and output that I got after a few tries; I think I may be getting close:
void LeftShift2D(int A[M][N]){
int i;
int j;
int temp;
for(i = 0; i < M; i++){
for(j = 0; j < N; j++){
temp = A[0][0];
A[i][j] = A[i+1][j+1];
}
}
A[i][j] = temp;
}
Given this as the input:
14 17 28 26 24
26 17 13 10 2
3 8 21 20 24
17 1 7 23 17
12 9 28 10 3
21 3 14 8 26
this is the desired output:
17 28 26 24 26
17 13 10 2 3
8 21 20 24 17
1 7 23 17 12
9 28 10 3 21
3 14 8 26 14
but this is the actual output I'm getting:
14 17 28 26 24
26 17 13 10 2
3 8 21 20 24
17 1 7 23 17
12 9 28 10 3
21 3 14 8 26
4
17 13 10 2 3
8 21 20 24 17
1 7 23 17 12
9 28 10 3 21
3 14 8 26 4
-1218716075 -1217196044 0 -1079502888 134514340
What's wrong?
By far the easiest way to do what you want is:
void LeftShift2D(int A[M][N])
{
int i;
int temp = A[0][0];
int *base = &A[0][0];
for (i = 0; i < M * N - 1; i++)
base[i] = base[i+1];
A[i] = temp;
}
This treats the array as a vector and shifts the data down one space, rotating the value originally at the start to the end. If you wanted to rotate each row separately, you'd use different code, more closely related to what you show:
void LeftShift2D(int A[M][N])
{
int temp;
for (int i = 0; i < M; i++)
{
int j;
int temp = A[i][0]
for (j = 0; j < N - 1; j++)
A[i][j] = A[i][j+1];
A[i][j] = temp;
}
}
Your code has various problems. The A[i][j] = A[i+1][j+1]; assignment accesses data out of bounds, and copies data 'diagonally', copying the cell to the bottom-right (or south-east) of the current cell, not the cell to the right (east) of the current cell. It has problems wrapping, too.
You have a buffer overflow here
A[i][j] = A[i+1][j+1];
you need to iterate to i < M - 1 and j < N - 1.
You are accessing invalid memory which explains the observed values, that also invokes undefined behavior so you could observe some strange behavior eventually.
an array is entered:
ary[] = [11 12 13 14 15 16 17 18 19 20 11 12 13 14 15 16 17 18 19 20 11 12 13 14 15 16 17 18 19 20 11 12 13 14 -1] (the negative one signifies that it is the end of the array)
a size is entered:
size = 34
I need this array to be rearranged so that it is in sequential order. Below is my code:
int x;
int numpasses;
int temp;
for(numpasses = 1; numpasses < size; numpasses++)
{
for(x = 0; x < size - numpasses; x++)
{
if(ary[x] > ary[x + 1] && ary[x] != ary[size - 1])
{
temp = ary[x];
ary[x] = ary[x + 1]; //THIS PORTION SWITHCHES TWO ADJECENT VALUES TO MAKE ARRAY SEQUENTIAL
ary[x + 1] = temp;
}
}
int a;
for(a = 0; a < size; a++)
{
printf("%d ", ary[a]);
}
}
This prints the numbers as follows:
11 11 12 12 13 13 14 14 15 15 16 16 17 17 18 18 19 19 20 11 12 13 14 15 16 17 18 19 20 11 12 13 14
Replacing the line
if(ary[x] > ary[x + 1] && ary[x] != ary[size - 1])
by
if(ary[x] > ary[x + 1] )
worked fine for me.
I'll let you figure out why.
PS.
Please add
printf("\n");
after printing the array. It makes seeing the result at the end of the outer loop a little bit clearer.
This code, in every loop cycle creates twice smaller segment that it adds to number 0. Problem is that, if you split 50 you get 25 and 25 and if you split 51 you also get 25. This x and y should represent array index so they start from 0. If you know better iterative algorithm (must not use recursion) I'll be glad to see it but I really wnat to solve this problem this way(unless it can't be done).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n;
int a, b, x, r, y;
printf("Enter N: ");
scanf("%d", &n);
a = 0;
b = n - 1;
x = a;
y = b;
r = b;
printf(" %2d %2d\n", a, b);
while(b > 1)
{
r /= 2;
while(x < n - 1)
{
printf(" %2d ", x);
y = x + r; //if(something) y = x + r - 1;
printf("%2d", y); //else y = x + r;
x = y + 1;
}
x = a;
b = r;
y = b;
putchar('\n');
}
return 0;
}
output:
Enter N: 50
0 49
0 24 25 49
0 12 13 25 26 38 39 51
0 6 7 13 14 20 21 27 28 34 35 41 42 48
0 3 4 7 8 11 12 15 16 19 20 23 24 27 28 31 32 35 36 39 40 43 44 47 48 51
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
Press [Enter] to close the terminal ...
This is a breadth-first traversal problem and should be implemented with a queue. I do not think that there is a simple way to implement breadth-first recursion, so an iterative approach will have to do. The following is a rough algorithm:
1) Create two queues, q and p, containing your initial range [a, b].
2) While p is not empty, dequeue an element from p and print it.
3) While q is not empty, dequeue an element [i, j] from q and enqueue two new ranges [i, (i + j) / 2] and [(i + j) / 2 + 1, j] into p.
4) Copy p to q.
5) If q has a size of a + b + 1, then you are done. Otherwise, go back to step 2.
Here is my implementation in C#:
using System;
using System.Collections.Generic;
struct Pair
{
public int a;
public int b;
public Pair(int a, int b)
{
this.a = a;
this.b = b;
}
}
class Program
{
static void Main()
{
Console.Write("Enter a number: ");
int size = int.Parse(Console.ReadLine());
Queue<Pair> queue = new Queue<Pair>();
queue.Enqueue(new Pair(0, size));
bool lastRound = false;
do
{
if (queue.Count == size + 1)
{
lastRound = true;
}
Queue<Pair> temporary = new Queue<Pair>(queue);
while (temporary.Count > 0)
{
Pair pair = temporary.Dequeue();
if (pair.b - pair.a == 0)
{
Console.Write("{0} ", pair.a);
}
else
{
Console.Write("{0}-{1} ", pair.a, pair.b);
}
}
Console.WriteLine();
while (queue.Count > 0)
{
Pair pair = queue.Dequeue();
if (pair.b - pair.a == 0)
{
temporary.Enqueue(new Pair(pair.a, pair.b));
}
else
{
temporary.Enqueue(new Pair(pair.a, (pair.a + pair.b) / 2));
temporary.Enqueue(new Pair((pair.a + pair.b) / 2 + 1, pair.b));
}
}
queue = temporary;
} while (!lastRound);
}
}
Here is its output:
Enter a number: 20
0-20
0-10 11-20
0-5 6-10 11-15 16-20
0-2 3-5 6-8 9-10 11-13 14-15 16-18 19-20
0-1 2 3-4 5 6-7 8 9 10 11-12 13 14 15 16-17 18 19 20
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Do a google search for quicksort. You will find many examples of code that use this technique.
When you're splitting the number, you'll need to decide whether there is a remainder or not (depending on whether the number you are splitting is odd or even).
You will need to handle the two different scenarios differently. You will also have to decide where to put the extra number (on the first half or the second half).
Perhaps a possible modification is to have two r's to track the two halves.
The root of problem is that a fixed jump size (r) cannot be calculated for each iteration. A constant
r for each iteration will work only when the starting number
is a power of two (try starting with 64 and you will see that it all works as you want). For any other number the
jump size (r) may be either r or r+1 depending on whether
the prior iteration divided the current range being split into an even or odd number of elements. Consequently
the value of r may not be a constant throughout the entire iteration.
As soon as you see that the current iteration depends on results from a prior iteration the words "stack" or "recursion" pop up
as immediate solutions. This is because prior state information is needed to solve the problem.
There may be a purely iterative solution to your problem, but I think that it will either take some interesting
math or extra memory to maintain state information.