I am new to programming and i have been learning C the past few months.
I am working on a program that stores pairs of integers in an array. The program prompts the user to enter the number of pairs to be entered, and then I need to allocate storage for the array and then the user enters the pairs line by line to be stored in the array. The program needs to access these pairs to perform operations on later.
I am having trouble trying to set this up. How can I create this kind of data set, in which each member contains a pair of integers, without knowing the initial size of the array?
There is no built-in support for dynamic array in C. The type that you need is a pointer to your pairs that will be allocated regarding the user choice.
I have written a simple sample code from your description, to help you to understand dynamic allocations.
#include <stdio.h>
#include <stdlib.h>
struct MyPair
{
int first;
int second;
};
int main()
{
int nPairCount=0;
struct MyPair *pPairs = NULL;
// .... prompt from the user
// let's say we have a nPairCount>0
// We allocate a memory space in the heap that will be able to store
// nPairCount pairs contiguously.
pPairs = malloc(nPairCount*sizeof(struct MyPair));
if(pPairs == NULL)
{
// LOG ERROR, THERE IS NOT ENOUGH MEMORY TO ALLOCATE YOUR PAIRS
return -1;
}
for(int i= 0; i<nPairCount; ++i)
{
// you can access the i-th pair in memory thanks to [] operator
// Fill the currentPair
// pPairs[i].first = ... ;
// pPairs[i].second= ... ;
}
// Do your process
// Do not forget to free your pairs from memory
free(pPairs);
return 0;
}
I don't think that there is a bucket function available in c. But you could create an array that has the number of elements entered by the user.
#include<stdio.h>
int main(){
int a,i;
printf("Enter the number of pairs: ");
scanf("%d",&a);
double b[a*2];\\note that a is number of pairs, so 2a will make it elements
printf("Enter the numbers: \n");
for(i=0;i<(2*a-1);i=i+2)
{
scanf("%lf %lf",&b[i],&b[i+1]);
}
printf("The pairs entered by you are:\n ");
for(i=0;i<(2*a-1);i=i+2)
{
printf("%lf and %lf\n ",b[i],b[i+1]);
}
return 0;
}
All I have done is take up 2 elements at a time and assign them consecutive arrays and then print them pairwise.
Sample output:
Enter the number of pairs: 3
Enter the numbers:
12 14
45 456
321 568
The pairs entered by you are:
12.000000 and 14.000000
45.000000 and 456.000000
321.000000 and 568.000000
Related
How can I read integers from the standard input and store them in an array? I do not know in advance how many integers I will have to read from the standard input.
Examples of input:
4 5 6 7 8
(or)
4,5,6,7,8
(or)
4
5
6
7
8
Example of output: Just print that array.
In Python I can do it this way:
arr = list(map(int,input().split(' ')))
In Python it is easy because I do not need to specify the size of the array beforehand.
How can I read integers from the input and store them into an array in this way in C? Is it possible?
The main issue here is to create an array wide enough to store all the integers contained in the standard input, but we don't know how many values we are going to read.
The input is a file on the Hard Disk Drive
If you read from a file, you can afford to read the file twice: the first time, you do not store the values, you just count how many values there are; the second time, you allocate an array with the right size with malloc() and you store the integers into the array.
The input is read from the standard input
On the other hand, if you read from the standard input, you can't read the input twice, because it is consumed as soon as you read it. So you need to compute the size of the array and store the elements in the array at the same time. To do this, you begin by allocating an array of size 10, then you read 10 values from the standard input, and if the array is not big enough, you allocate another one bigger, you copy the values read so far from the first array into the second array, you delete the first array, and you continue to do this until all the input is exhausted.
Here is the algorithm:
Allocate an array of 10 integers with malloc().
Read integers from the standard input with scanf() until the end of the input or until the array is full.
If there are no more integers to read from the standard input, stop.
Otherwise, use the function realloc() to double the size of the array, and go back to step 2. The realloc() function will potentially allocate a second array with the new size, copy the integers from the first array into the first half of the second array (this will happen if there is not enough free space after the end of the first array to expand it).
If it is too difficult
It is not a one-liner like in Python. Doing this correctly is actually quite hard for a beginner. If you struggle too much, just dump the standard input into a temporary file on the hard disk drive, and use the trick of reading the file twice.
If the input is produced by something you control, you could also try to change the format of the input. For instance, if you add the number of values that need to be read as the first element of the input, it will simplify your task.
The (most) flexible solution is to use dynamic linked list (it still has properties of array where you can iterate/traverse over it). On below sample, you can find two(2) scenarios using linked list where on scenario #1, user provide the input once using comma delimited list of integer; while for scenario #2, user will be prompted until a certain input is provided.
Sample output:
=== Scenario 1 ===
Enter comma delimited integer (e.g. 1,2,3,4): 1,6,8,9
=Print List=
1
6
8
9
=== Scenario 2 ===
Enter integer (-99 to stop): 3
Enter integer (-99 to stop): 4
Enter integer (-99 to stop): 5
Enter integer (-99 to stop): 6
Enter integer (-99 to stop): 7
Enter integer (-99 to stop): -99
=Print List=
3
4
5
6
7
Sample Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Element
{
int data;
struct Element *next;
};
void printList(struct Element *list) {
printf("=Print List=\n");
while(list != NULL) {
printf("%d\n", list->data);
list = list->next;
} //end while
}
int main(void) {
/* 1. This is for the case where input from user is expected to be once and is using comma delimited.
Data will be stored on a dynamic linked list.
Note: input is not validated. */
char str1[256];
char delimiter[2] = "," ;
struct Element *listResult = NULL; //this is to store the result list
struct Element *lastElement=NULL;
printf("=== Scenario 1 ===\n");
printf("Enter comma delimited integer (e.g. 1,2,3,4): ");
scanf("%s", str1);
char *token = strtok(str1, delimiter);
//Parse the input and put into the linked list
while(token != NULL ) {
int intData = atoi(token);
struct Element *newElmt = (struct Element *) malloc (sizeof(struct Element));
newElmt->data = intData;
newElmt->next = NULL;
if (listResult == NULL) { //listResult is initially empty, put the new element as the head
listResult = newElmt;
lastElement = newElmt;
} else { //listResult is NOT empty, put the new element as the tail
lastElement->next = newElmt;
lastElement = newElmt;
} //end if
token = strtok(NULL, ",");
} //end while
printList(listResult);
/* 2. This is for the case where input from user is expected to be multiple times until specific input is provided (i.e. -99).
Data will be stored on a dynamic linked list.
Note: input is not validated. */
int inputInt=0;
struct Element *listResult2 = NULL; //this is to store the result list
struct Element *lastElement2 = NULL;
printf("\n=== Scenario 2 ===\n");
do {
printf("Enter integer (-99 to stop): ");
scanf("%d", &inputInt);
if (inputInt != -99) {
struct Element *newElmt = (struct Element *) malloc (sizeof(struct Element));
newElmt->data = inputInt;
newElmt->next = NULL;
if (listResult2 == NULL) { //listResult2 is initially empty, put the new element as the head
listResult2 = newElmt;
lastElement2 = newElmt;
} else { //listResult2 is NOT empty, put the new element as the tail
lastElement2->next = newElmt;
lastElement2 = newElmt;
} //end if
} //end if
} while (inputInt != -99);
printList(listResult2);
return 0;
}
I have been teaching myself C for just a few weeks, and am attempting to write a code that enables the user to decide the size and elements in an array which is then separated into two arrays - one for odd numbers, and one for even numbers.
I am pretty sure that dynamic allocation has something to do with this, but I am unsure of how to implement it. Here is the code so far:
#include <stdio.h>
#include <stdlib.h>
int main()
{
//User decides the size of the array of numbers-------------------------------
int n;
printf("How many numbers? ");
scanf("%d",&n);
//User inputs values into array the size of array[n]--------------------------
int i;
int array[n];
printf("What are the numbers?\n");
for(i=0; i<n; i++)
{
scanf("%d",&array[i]);
}
//loop goes through array, separates even and odds into 2 new arrays----------
//use dynamic allocation??
for(i=0;i<n;i++)
{
int *evenarray = malloc(sizeof(evenarray)); //not sure if this is setup correctly
int *oddarray = malloc(sizeof(oddarray)); //not sure if this is setup correctly
if(array[i] % 2 == 0) //if value in array CAN be divided by 2
{
printf("Test statement.\n");
}
else //if this is not true, append to odd array
{
printf("Second test statement.\n");
}
}
}
/*this program accepts a user chosen number of numbers
then, the program separates the odd and even numbers into
two different arrays*/
There is no magical way to get this information at one shot. You can however, try either of the below:
Loop over the first array to figure out the count of odd (or even) numbers, then, you know the count of elements for which memory has to be allocated, and you can use either a VLA (as the first array itself) or use a pointer and allocator functions to allocate memory.
--> However, in this process, you have to perform the odd/even check twice - once to count the occurrence of odd/even numbers and next time, to actually decide and copy them to the new locations.
Allocate two chunks of memory similar to the first array size, and start filling the odd and even elements into the new memory, respectively. After all the elements are stored, take the counts, realloc() the allocated memories to the exact size.
--> In this case, the pre-allocation is to be done, but the odd/even check needs to be carried out only once.
You could copy into the odd/even arrays and keep seperate counters to track it. i.e:
//loop goes through array, separates even and odds into 2 new arrays----------
//use dynamic allocation??
int evencount =0;
int oddcount =0;
int *evenarray = malloc(sizeof(evenarray)); //not sure if this is setup correctly
int *oddarray = malloc(sizeof(oddarray)); //not sure if this is setup correctly
for(i=0;i<n;i++)
{
if(array[i] % 2 == 0) //if value in array CAN be divided by 2
{
printf("Printing to even array.\n");
evenarray[evencount] = array[i];
evencount++;
}
else //if this is not true, append to odd array
{
printf("Printing to odd array.\n");
oddarray[oddcount] = array[i];
oddcount++;
}
}
printf("evenarray = ");
for(i=0;i<evencount;i++){
printf("%d, ", evenarray[i]);
}
printf("\n");
printf("oddarray = ");
for(i=0;i<oddcount;i++){
printf("%d, ", oddarray[i]);
}
printf("\n");
#include <stdio.h>
int main (void)
{
int phy,geo,i,highest,largest;
int arr[2]={phy,geo};
printf("marks for physics : ");
scanf("%d",&phy);
printf("marks for geo : ");
scanf("%d",&geo);
largest = arr[0];
for (i = 0; i < 2; i++) {
if (arr[i] > largest) {
largest = arr[i];
}
}
// Print out the Result
printf("\nLargest Element : %d", largest);
return(0);
}
I am getting absurd values for the variable 'largest' . It's always the same value no matter what inputs I put in. The purpose of it is to calculate the largest number out of the two inputted numbers.
You're filling your array with uninitialized numbers, that's the source of your "absurd value", then you put your input into variables that are never read, hence why your inputs never change the output.
Try this instead:
printf("marks for physics : ");
scanf("%d", &arr[0]);
printf("marks for geo : ");
scanf("%d", &arr[1]);
Get five spaces in memory filled with whatever was there to begin with:
int phy,geo,i,highest,largest;
Get three spaces in memory, set the last one to null (to show it's the end of an array), and copies the values from two of the earlier five uninitialized spaces into an array:
int arr[2]={phy,geo};
Get two numbers that are input, and write them into two of the five spaces you originally got from memory:
printf("marks for physics : ");
scanf("%d",&phy);
printf("marks for geo : ");
scanf("%d",&geo);
Fill the fifth space in memory with a copy of the value you copied from the first uninitialized space in memory memory into the first element of the array:
largest = arr[0];
For each element in the array (beginning with the one you just copied), if the element is larger than what you've copies into the fifth space in memory, copy it into that space in memory.
for (i = 0; i < 2; i++) {
if (arr[i] > largest) {
largest = arr[i];
}
}
So what you've done is copied uninitialized spots in memory into an array, then taken inputs and written them to those spots in memory, then looked for the largest element in the array. This gives you weird results because you are comparing whatever values happened to be in memory when your program started running.
With the statement
int arr[2]={phy,geo};
you are basically initializing the array with the current values of phy and geo which are as yet uninitialized.
When you later load values through scanf, these won't be reflected in arr.
You need to modify the code as follows:
printf("marks for physics : ");
scanf("%d",&phy);
arr[0] = phy;
printf("marks for geo : ");
scanf("%d",&geo);
arr[1] = geo;
int arr[2]={phy,geo};
This doesn't mean "arr is an array of whatever values phy and geo will hold in the future".
It means "arr is an array of whatever values phy and geo hold now".
And those values are indeterminate because, when you creat arr, neither phy or geo have been initialised yet.
I am reading a list of grades from a txt file into an array. It worked fine when reading user input, but I'm having trouble reading each line when scanning from file. The number of students is variable. The number of grades per student is variable. I have no trouble reading the number of students and number of assignments, but when reading from file I'm having trouble pulling the int (grade) from each line for each student. The input may be like a or b (or any larger number of students/assignments):
txt-example1 (the comments including and after // are my own and not in txt file)
2 //number of students
3 //the number of grades per student (will match the number of grade rows below)
theo alvin //the number of names will match the number of students
75 60
89 90
79 95
txt-example2
3
4
theo alvin simon
78 85 90
85 96 76
77 99 100
88 55 92
I can put the names into 1 dimension of a 2d array (I'll use the second dimension later to print - no problems with that part). I want to get the grades into a 2d array. Here is what I have
#include<stdio.h>
#include<string.h>
int numStus;
int numGrades;
int main()
{
FILE* inputFile;
char stuNames[numStus][10];
int grades[numGrades][numStus];
inputFile = fopen("testData.txt","r"); //assume inputFile has data from Ex 1 or 2 above
fscanf(inputFile,"%d",&numStus);
fscanf(inputFile,"%d",&numGrades);
int i;
int j;
for (i=0; i<numStus; i++)
{
fscanf(inputFile,"%s",&stuNames[i]);
}
//here is where I'm having trouble
for(i=0;i<numGrades;i++)
{
for(j=0;j<numStus; j++)
{
//I want to use fscanf, but don't know how to account for carriage returns to iterate into next part of array
}
}
}
What worked when getting from user input:
int i;
int j;
int k;
for (i=0; i<numGrades; i++)
{
for (j=0; j<numStus; j++)
{
printf("Enter grade for Assignemnt %d for ",i)
for(k=0;k<10;k++)
{
printf("%c",stuNames[j][k]);
}
scanf("%d",&grades[i][j]);
}
}
The part immediately above worked well for user input grades. When getting the same input from a file I'm not sure how to get the grades into the proper dimensions. Any advice on how to account for the newline/CR to increment the array would be very much appreciated. Thanks.
The scanf can be used in the nested loops as usually for reading a single value, since the carrige return is skipped as a space, for example: fscanf(inputFile,"%d",&grades[i][j]);
However, the arrays stuNames and grades must be initialized only after reading numStus and numGrades, for example:
...
fscanf(inputFile,"%d",&numStus);
char stuNames[numStus][10];
fscanf(inputFile,"%d",&numGrades);
int grades[numGrades][numStus];
...
That trick is not allowed in ANSI C. In that case dynamic memory allocation should be used.
You have trouble much earlier than you think. You can't use uninitialized variables when you are declaring your arrays. In your working example you don't show how you allocated your arrays. Were they fixed size? Whatever you did there would probably work in your new program.
You first need to read the amount of students and amount of grades.
A uninitialized variable like int foo; has a "random" value.
You need to initialize the variable like int foo = 0;.
Knowing this lets analyze your code step by step.
int numStus; //numStus gets random value
int numGrades; //numGrades gets random value
int main()
{
FILE* inputFile;
char stuNames[numStus][10]; //random amount gets generated
int grades[numGrades][numStus]; //variable gets random value
fscanf(inputFile,"%d",&numStus); //numStus gets actual value
fscanf(inputFile,"%d",&numGrades); //numGrades gets actual value
C is a language which handles things in order.
This means that the array keeps the size is has been given.
The code can be fixed by switching around the statements like this:
int numStus; //numStus gets random value
int numGrades; //numGrades gets random value
int main()
{
FILE* inputFile;
fscanf(inputFile,"%d",&numStus); //numStus gets actual value
fscanf(inputFile,"%d",&numGrades); //numGrades gets actual value
char stuNames[numStus][10]; //array of wanted size gets created
int grades[numGrades][numStus]; //random amount gets
I hope this helps, may you have any questions ask them
I have this simple problem to which I am trying to write a solution, in C.
If an array arr contains n elements, then write a program to check
if arr[0] = arr[n-1], arr[1] = arr[n-2] and so on.
And my code looks like this-
#include<stdio.h>
int main()
{
int arr[10],i=0,j;
int k=0;
printf("\n Enter 10 positive integers: \n");
for(k=0;k<=9;k++)
scanf("%d",&arr[k]);
while(i<=9)
{
for(j=9;j>=0;j--)
{
if(arr[i]==arr[j])
{
printf("\n The array element %d is equal to array element %d\n", arr[i],arr[j]);
}
i++;
continue;
}
}
return 0;
}
On entering this input-
Enter 10 positive integers:
10
20
30
40
50
60
40
80
20
90
The output I get is-
The array element 20 is equal to array element 20
The array element 40 is equal to array element 40
The array element 40 is equal to array element 40
The array element 20 is equal to array element 20
Now, there are two problems with this code-
As you can see, the program prints out matching array elements twice. This is because, the way I've structured the program, once the variable i loops through the array from the first to last element, and then j loops through from the last to first element. So each prints out the matching array element once, leading to two sets of values.
My second question is- In my code, I've hard-coded the length of the array in the for loops(0 to 9 for an array of 10 elements). What change can be done so that the length of the array, as entered by the user, can directly be used in the for loops?
I've read that, in C, array dimensions(when declaring) cannot be a variable. So, a declaration like this(which was my first thought) wouldn't work-
int n; // n is no. of elements entered by the user
int arr[n];
I'm a newbie to programming, so my apologies if the question sounds/is too simple, low-quality.
Thank You.
1)You can traverse the array for half times for getting the prints only once. Instead of for(j=9;j>=0;j--) you can use for(j=9;j>=9/2;j--).
2)
int n;
int arr[n].
Recent Compilers support this statement. If you don't like to use this, you can go for dynamic memory allocation for the array.
My second question is- In my code, I've hard-coded the length of the array in the for loops(0 to 9 for an array of 10 elements). What change can be done so that the length of the array, as entered by the user, can directly be used in the for loops?
Use dynamic memory allocation. Use malloc().
So code will be
{
int num_elements;
int* arr;
printf("Enter number of elements\n");
scanf("%d", &num_elements);
arr = (int *) malloc(num_elements * sizeof(int)); // Use this 'arr' for holding input data from user
// Your remaining code comes here
free(arr); // Free the pointer in the end of program
}
the variable length creation works for me:
#include<stdio.h>
int main(){
int a, i;
scanf("%i", &a);
int blah[a];
for (i = 0; i < a; i++){
printf("/n%i", blah[a]);
}
}
The other way would be to create the maximum length array and than simply use first n elements.
As the previous answer states it is up to you to make sure you are checking each element only once therefore stopping at the element n/2. It is probably important that n/2 is rounded to the closest smaller integer, so at first glance odd numbers of arguments may be differently handled. But as it is omitting only the middle element it is identical to itself.
For your first query
for(i=0;i<n/2;i++)
{
if(a[i]==a[n-(i+1)])
{
printf("\n The array element %d is equal to array element %d\n",a[i],a[n-(i+1)]);
}
}
For your second query you can use condition i<(n/2) (which runs the loop (n/2)-1 times) For your case where n = 10 it will run from 0 to 4.
If you want to loop from 0 to 9 you can use
for(i=0;i<n;i++)
For making array of n elements where n is a variable either make an array of elements that is always greater than n or do it by making a dynamic array.
http://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html
corrected:
#include<stdio.h>
int main()
{
int i=0, size; // size of array
int k=0; // counter
printf("enter size of array\n");
scanf("%d", &size); // ask user for desired size
int *arr = malloc(size * sizeof(int)); // allocate memory for array
printf("\n Enter 10 positive integers: \n"); // fill your array of size size
for(k=0;k<size;k++)
scanf("%d",&arr[k]);
k = 0; // reset this counter
for(i=0; i<size/2; i++) // check only for half of it
{
if(arr[i] == arr[size-i-1]) // try it with paper and pincil
{
printf("match arr[%d]=arr[%d]=%d\n", i,size-i-1, arr[i]);
k++;
}
}
if(k==0) printf("No matching");
return 0;
}