I am currently working on a C project that requires the creation, storage and mathematical usage of numbers that are too large to be put into normal variable types. To do this, we were instructed to represent numbers as a sequence of digits stored in an array of integers. I use a struct defined as so:
struct BigInt {
int val[300000];
int size;
};
(I know I can dynamically allocate memory, and that that is
preferable, however this is how I am most comfortable doing it, it has
worked perfectly fine so far and this is how the professor instructed us to do it.)
I then define member A:
struct BigInt A={NULL};
I can generate and store, then add, subtract and multiply random numbers with this, and they can have any number digits up to 300000(far more than I will ever need to account for). For example, if the number 1432 was generated and stored into BigInt A, A.size would be 4 and A.val[2] would be 3.
Now I need to create a way to store user input into this type. For example, the user needs to be able go straight from inputting 50! and then it be stored into this struct array type I have created. How would I go about doing this?
The only ways that I could think of would be to store the user input as a string then have the math in that string be executed multiple times, each time storing a different digit, or reading numbers straight off of stdout, but I don't know if either of those are even possible or would solve my problem.
You can try using string as follows:
char s[300001];
scanf("%s", s);
A.size = strlen(s);
for(int i = 0; i < A.size; i++){
A.val[i] = s[i] - '0';
}
I think it will solve your problem, but this way of implementation for big integers is not efficient though.
Sorry for previous answer, to solve in c you need to use array of chars to store each digits.
Related
Is it possible to create arrays based of their index as in
int x = 4;
int y = 5;
int someNr = 123;
int foo[x][y] = someNr;
dynamically/on the run, without creating foo[0...3][0...4]?
If not, is there a data structure that allow me to do something similar to this in C?
No.
As written your code make no sense at all. You need foo to be declared somewhere and then you can index into it with foo[x][y] = someNr;. But you cant just make foo spring into existence which is what it looks like you are trying to do.
Either create foo with correct sizes (only you can say what they are) int foo[16][16]; for example or use a different data structure.
In C++ you could do a map<pair<int, int>, int>
Variable Length Arrays
Even if x and y were replaced by constants, you could not initialize the array using the notation shown. You'd need to use:
int fixed[3][4] = { someNr };
or similar (extra braces, perhaps; more values perhaps). You can, however, declare/define variable length arrays (VLA), but you cannot initialize them at all. So, you could write:
int x = 4;
int y = 5;
int someNr = 123;
int foo[x][y];
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
foo[i][j] = someNr + i * (x + 1) + j;
}
Obviously, you can't use x and y as indexes without writing (or reading) outside the bounds of the array. The onus is on you to ensure that there is enough space on the stack for the values chosen as the limits on the arrays (it won't be a problem at 3x4; it might be at 300x400 though, and will be at 3000x4000). You can also use dynamic allocation of VLAs to handle bigger matrices.
VLA support is mandatory in C99, optional in C11 and C18, and non-existent in strict C90.
Sparse arrays
If what you want is 'sparse array support', there is no built-in facility in C that will assist you. You have to devise (or find) code that will handle that for you. It can certainly be done; Fortran programmers used to have to do it quite often in the bad old days when megabytes of memory were a luxury and MIPS meant millions of instruction per second and people were happy when their computer could do double-digit MIPS (and the Fortran 90 standard was still years in the future).
You'll need to devise a structure and a set of functions to handle the sparse array. You will probably need to decide whether you have values in every row, or whether you only record the data in some rows. You'll need a function to assign a value to a cell, and another to retrieve the value from a cell. You'll need to think what the value is when there is no explicit entry. (The thinking probably isn't hard. The default value is usually zero, but an infinity or a NaN (not a number) might be appropriate, depending on context.) You'd also need a function to allocate the base structure (would you specify the maximum sizes?) and another to release it.
Most efficient way to create a dynamic index of an array is to create an empty array of the same data type that the array to index is holding.
Let's imagine we are using integers in sake of simplicity. You can then stretch the concept to any other data type.
The ideal index depth will depend on the length of the data to index and will be somewhere close to the length of the data.
Let's say you have 1 million 64 bit integers in the array to index.
First of all you should order the data and eliminate duplicates. That's something easy to achieve by using qsort() (the quick sort C built in function) and some remove duplicate function such as
uint64_t remove_dupes(char *unord_arr, char *ord_arr, uint64_t arr_size)
{
uint64_t i, j=0;
for (i=1;i<arr_size;i++)
{
if ( strcmp(unord_arr[i], unord_arr[i-1]) != 0 ){
strcpy(ord_arr[j],unord_arr[i-1]);
j++;
}
if ( i == arr_size-1 ){
strcpy(ord_arr[j],unord_arr[i]);
j++;
}
}
return j;
}
Adapt the code above to your needs, you should free() the unordered array when the function finishes ordering it to the ordered array. The function above is very fast, it will return zero entries when the array to order contains one element, but that's probably something you can live with.
Once the data is ordered and unique, create an index with a length close to that of the data. It does not need to be of an exact length, although pledging to powers of 10 will make everything easier, in case of integers.
uint64_t* idx = calloc(pow(10, indexdepth), sizeof(uint64_t));
This will create an empty index array.
Then populate the index. Traverse your array to index just once and every time you detect a change in the number of significant figures (same as index depth) to the left add the position where that new number was detected.
If you choose an indexdepth of 2 you will have 10² = 100 possible values in your index, typically going from 0 to 99.
When you detect that some number starts by 10 (103456), you add an entry to the index, let's say that 103456 was detected at position 733, your index entry would be:
index[10] = 733;
Next entry begining by 11 should be added in the next index slot, let's say that first number beginning by 11 is found at position 2023
index[11] = 2023;
And so on.
When you later need to find some number in your original array storing 1 million entries, you don't have to iterate the whole array, you just need to check where in your index the first number starting by the first two significant digits is stored. Entry index[10] tells you where the first number starting by 10 is stored. You can then iterate forward until you find your match.
In my example I employed a small index, thus the average number of iterations that you will need to perform will be 1000000/100 = 10000
If you enlarge your index to somewhere close the length of the data the number of iterations will tend to 1, making any search blazing fast.
What I like to do is to create some simple algorithm that tells me what's the ideal depth of the index after knowing the type and length of the data to index.
Please, note that in the example that I have posed, 64 bit numbers are indexed by their first index depth significant figures, thus 10 and 100001 will be stored in the same index segment. That's not a problem on its own, nonetheless each master has his small book of secrets. Treating numbers as a fixed length hexadecimal string can help keeping a strict numerical order.
You don't have to change the base though, you could consider 10 to be 0000010 to keep it in the 00 index segment and keep base 10 numbers ordered, using different numerical bases is nonetheless trivial in C, which is of great help for this task.
As you make your index depth become larger, the amount of entries per index segment will be reduced
Please, do note that programming, especially lower level like C consists in comprehending the tradeof between CPU cycles and memory use in great part.
Creating the proposed index is a way to reduce the number of CPU cycles required to locate a value at the cost of using more memory as the index becomes larger. This is nonetheless the way to go nowadays, as masive amounts of memory are cheap.
As SSDs' speed become closer to that of RAM, using files to store indexes is to be taken on account. Nevertheless modern OSs tend to load in RAM as much as they can, thus using files would end up in something similar from a performance point of view.
Foreword: I have simplified the problem into its key functionalities, so if it sounds weird it is because this is a small aspect of the whole program.
Problem:
I want to create something like 100 text files: I'll loop and use my loop counter to name the files.
Then, I want to populate each file with random strings. I use my String struck defined below for this. I want to fill the file up from [1KB up to 500KB].
struct String // And yes I am using my own String library.
{
char *c;
int length;
int maxLength;
}
Lets assume I have the file opened (probably at the moment I create it, so it is empty). Now I would check something like this.
int range = Random.Range(0,500);
I would get a number that would predetermine the file size. So if range == 100 then the file would be populated with 100KB of "data".
I would first have my string created.
// Maybe making this 100 chars would help?
String *s1 = makeString("abcdefghijklmnopqrstuvwxyz");
How would I figure out how many times I have to write my String s1 into the file to make it the size of range? Preferably before writing to the file, I wouldn't want to write first then check, then write again.
And How would I get a random integer value in C? I used to the Random.Range in C#.
To keep it simple, it would best if you can make your string size the common denominator of 1KB (1024 bytes). So you don't have to take care fraction.
After that you can do as #naitoon mentioned above (range*1024)/s1->length. If each of the character of your string is 1 byte long.
As for random integer, you can call the standard library rand() which returns integer between 0 to RAND_MAX, which is at least 32767.
Also, in order to keep the random number with your range(0~500), you can do a modular of the return value.
range = rand() % 500;
I'd like for my array to be of a set length using a simple format. Please, let me know how this is done.
What I already have:
arr[100]
Pseudocode: what I would like to have:
arr[4-20] or arr[$min_int THROUGH $max_int]
Additional detail edit: The int should be within the range array = (4, 20). The input may contain leading zeros. I'd like to keep the length of the array restricted (i.e., to 9 or 10 characters).
Arrays simply do not work this way in C. You will need to implement it yourself by only looping through valid indices (and wasting memory in the process) or by using a data structure better suited to the job, like a map (which you will have to find in a library or write yourself as it does not exist in the language).
#define ARRMINIDX 4
#define ARRMAXIDX 20
int arrmem[ARRMAXIDX+1-ARRMINIDX];
#define arr(x) arrmem[ARRMINIDX+(x)]
// process elements of arr
for( i = ARRMINIDX; i <= ARRMAXIDX; i++ )
dosomething(arr(i));
OTOH, this make not be what you want at all, given your comment
I want an array with 0-1 elements: a limited int or limited "numeric
int"--string mimicking an int.
which I can't make heads or tails of in this context. Are you saying that you want a string of 4-20 chars that represents an integer?
I need to write a program, that will ask a user to enter a number of how many ints they would like to enter.. so the output would look like
Enter number of Ints (must be greater then 1)
and they would input a number between 2 - infinity (if they really wanted to go that far)
at that point i would scanf that number and set it to a variable
now with that number, i want to run a for loop to ask them to begin entering their Ints
for (count = 0; count < numofInts; count++)
{
printf(" Enter an integer: ");
scanf("%d", &Number);
}
the problem im having is that i need to make sure that it records every number that they enter, so i need to have those values stored to an array, but the number of elements of the array must be dynamic so that it can change depending on the numofInts, I'm supposed to use Malloc() to create a dynamic memory allocated space, and i understand that it creates a variable with a memory space of what ever i set the malloc to, but i don't know how to store a series a variables to that space, and then call them back as i need them.
The end result of the program is supposed to take a number like 123456789, and cycle through the number storing the intergers as the "largest" int, and then spit out which int is the largest, so like x = 1234567890, x % 10, x = 0, largest = x, x / 10, x % 10, x = 9, if x > largest, largest = x, and just loop that till it cycles through the whole number, and store that number at the very end. I have that part down, but because i have to take a series of numbers and run this loop for all of those numbers, i need to be able to store and recall those values and place them in the loop to be able to store the largest digits of those numbers
any help with this problem would be greatly appreciated, i just have not been able to figure out how to use malloc or to create a dynamic array and most of the tutorials ive read online or watched from youtube are about C++ and i need to do this with just C...
http://pastebin.com/PZyvEQ4J
what i have so far
After you read numInts, you allocate the array like so:
int* arr = malloc(numInts*sizeof(int));
Now you populate the array with your already existing function and assigning the values read to the array.
I'm not going to give you a full solution, since this is homework and wouldn't help you, but you access the i'th element of the array with the [] operator:
arr[i];
Learn more about pointers and calloc
Currently my program allows the user to enter 5 integers which are used to create an average number. This is set to five as after the fifth number is entered the loop is broken.
I am trying to implement a method which will let the user continue to add as many numbers as they like to an array from which i can then use to create an average without a limit on the amount of numbers that can be entered.
I have come across a few problems, firstly i cannot create an array which is dyamic as i have no idea how many numbers the user may wish to enter which means i can't give it a definitive size.
Secondly the way my program currently creates the average is by looping through the elements in the array and adding the consecutively to an integer, from which the the average is made. I cannot specify the limit for the loop to continue running if i cannot determine the array.
Hopefully my example explains this better.
#include <stdio.h>
#include <string.h>
void main()
{
int i = 0;
int arrayNum[5];
int temp = 1;
int anotherTemp = 0;
int answer = 0;
printf("Enter as many numbers as you like, when finished enter a negative number\n");
for(i = 0; i < 5; i++)
{
scanf("%d", &temp);
arrayNum[i] = temp;
anotherTemp = anotherTemp + arrayNum[i];
}
answer = anotherTemp / 5;
printf("Average of %d,%d,%d,%d,%d = %d",arrayNum[0],arrayNum[1],arrayNum[2],arrayNum[3],arrayNum[4],answer);
}
Although this may not be the best way to implement it, it does work when the amount of numbers are specified beforehand.
What would be the best way to get around this and allow the user to enter as many number as necessary?
Edit: Although i needed to use an array I have decided that it is not necessary as the solution is much simpler without being restricted to it.
In terms of code simplicity, you might want to check out the realloc() function; you can allocate an initial array of some size, and if the user enters too many numbers call realloc() to get yourself a bigger array and continue from there.
You don't, however, actually need to keep the numbers as you go along at all, at least if you only care about the average:
int input;
int sum = 0;
int count = 0;
int average;
while (1) {
scanf("%d", &input);
if (input < 0) {
break;
}
sum += input;
count++;
}
average = sum / count;
If you're trying to compute an average, then you don't need to save the numbers. Save yourself the work of worrying about the array. Simply accumulate (add) each number to a single total, count each number, then divide when you're done. Two variables are all that you need.
With this method, you aren't in any risk of overflowing your array, so you can use a while loop... while (temp != -1)
Basically you start with a dynamically allocated array with a fixed size, and then allocate a new array that is bigger (say, twice as big as initial size) and copy the stuff from the old array to the new one whenever you run out of space.
For the second part of the problem, keep a counter of the number of items the user entered and use it when averaging.
Something like this.
Use a dynamic array data structure, like Vector in Java (java.util.Vector).
You can implement such a dynamic array yourself easily:
allocate array of size N
as soon as you need more elements than N, allocate a new bigger array (e.g. with size N+10), copy the content of the old array into the new array and set your working reference to the new array and your array size variable N to the new size (e.g. N+10). Free the old array.