Need help creating a parallel array in C [closed] - c

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Just a disclaimer: I am a complete noob when it comes to C programming and this might be embarrassingly easy but I can't think it out myself and haven't found anything otherwise helpful. Anyways, this program below is supposed to put names (last, first) and ages into arrays and then alphabetize them. The problem I have is creating a sort of parallel array to match ages with their respective names after sorting them alphabetically. Does anyone have any suggestions? I was thinking of somehow tying the age array into my defined functions, but I still can't wrap my head around that either. Thanks in advance!
#include <stdio.h>
#include <string.h>
#define NAME_LENGTH 50
#define MAX_NAMES 50
int alpha_first(char *list[], int min_sub, int max_sub);
void select_sort_str(char *list[], int n);
int
main(void)
{
int i = 0;
int numpeople;
char names[MAX_NAMES][NAME_LENGTH] = { 0 };
char ages[MAX_NAMES][NAME_LENGTH] = { 0 };
char skip_line;
char *alpha[MAX_NAMES] = { 0 };
printf("Enter number of people <0..50>\n> ");
scanf("%d", &numpeople);
do
{
scanf("%c", &skip_line);
}
while (skip_line != '\n');
for(i = 0; i < numpeople; ++i)
{
printf("Enter name %d (lastname, firstname) ", i+1);
gets(names[i]);
printf("Enter age %d: ", i+1);
gets(ages[i]);
}
for(i = 0; i < numpeople; ++i)
{
alpha[i] = names[i];
select_sort_str(alpha, numpeople);
}
printf("\n\n%-30s\n\n", "Original List");
for (i = 0; i < numpeople; ++i)
printf("%-30s\n", names[i]);
printf("\n\n%-30s\n\n", "Alphabetical Order");
for (i = 0; i < numpeople; ++i)
printf("%-30s\n", alpha[i]);
return 0;
}
int
alpha_first(char *list[],
int min_sub, int max_sub)
{
int first, i;
first = min_sub;
for (i = min_sub + 1; i <= max_sub; ++i)
if (strcmp(list[i], list[first]) < 0)
first = i;
return (first);
}
void
select_sort_str(char *list[], int n)
{
int fill, index_of_min;
char *temp;
for (fill=0; fill<n-1; ++fill)
{
index_of_min = alpha_first(list, fill, n - 1);
if (index_of_min != fill)
{
temp = list[index_of_min];
list[index_of_min] = list[fill];
list[fill] = temp;
}
}
}

Use a structure:
typedef struct
{
char *first_name;
char *last_name;
int age;
} person;
When you create your array, create an array of person; Create a new person, fill in its fields, add it to your array. Now you have all of the data you need in one nice little package.

Most problems in computer science are solved by introducing an extra level of indirection.
In this case, observe that select_sort_str() is sorting an array of pointers to strings. Suppose instead you construct an array of index values, initialised to 0..numpeople-1, and then you sort those indexes into the order of the corresponding names. So, in alpha_first(), as well as taking char* list[] let it also take int index[] and the comparison becomes:
if (strcmp(list[index[i]], list[index[first]]) < 0)
and similarly select_sort_str(), in which you don't swap the entries in the list[] but in the index[]. Then to read the entries in alpha order, you use the extra level of indirection:
names[index[i]]

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

Write a function that finds the top 5 max values in array of structures?

Find the top 5 maximum values in array of structures (for C programming)?
I have an array of structures as follows:
struct info {
char name[100];
int number;
}
struct info people[10]
In char name[100] are names of people (up to 10) and they have a corresponding value in int balance:
Jane 10
John 40
Harry 16
Eva -5
...
until it gets to 10 people.
How do I find and print the 5 people who have the highest numbers?
i.e:
John 40
Harry 16
Jane 10
...
I have tried the following code:
int i,j, k=5, max, temp;
//move maximum 5 numbers to the front of the array
for (i=0; i<k; i++) {
max=i;
for (j=i+1; j<10; j++) {
if (people[i].number>people[max].number) {
max=j;
}
}
//swap numbers
temp=people[i].number;
people[i].number=people[max].number;
people[max].number=temp;
//swap names to match swapped numbers so they correspond
temp=people[i].name;
people[i].name=people[max].name;
people[max]=temp;
}
for (i=0; i<k; i++) {
printf("%s %d\n", people[i].name, people[i].number);
}
However, I get an error message on the second swap since its char type. How should I fix this or what else would work for this objective?
Just sort the array and then take the 5 first/last (depending on the sort order) entries of the sorted array.
1st define a compare function:
#include <stdlib.h> /* for qsort() */
#include <stdio.h> /* for printf() */
struct info
{
char name[100];
int number;
};
int cmp_struct_info_desc(const void * pv1, const void * pv2)
{
const struct info * pi1 = pv1;
const struct info * pi2 = pv2;
return pi2->number - pi1->number;
}
2ndly use the Standard C function qsort().
struct info people[] = {
... /* initialise array people here ... */
}
int main(void)
{
size_t number_of_array_elements = sizeof people/sizeof *people;
qsort(people, number_of_array_elements, sizeof *people, cmp_struct_info_desc);
for (size_t s = 0; s < number_of_array_elements; ++s)
{
printf("%zu. = {%d, '%s'}\n", s, people[s].number, people[s].name);
}
}
Starting from OP's code, just swap the structure. #BLUEPIXY. Only a small changed needed for OP's code.
Arrays can not be copied with assignments but objects, like struct info can be assigned.
int i, j, k=5;
//move maximum `k` numbers to the front of the array
for (i=0; i<k; i++) {
int max=i;
for (j=i+1; j<10; j++) {
if (people[i].number > people[max].number) {
max=j;
}
}
//swap info
struct info temp = people[i];
people[i] = people[max];
people[max] = temp;
}
for (i=0; i<k; i++) {
printf("%s %d\n", people[i].name, people[i].number);
}
The easiest and most general way would probably be to first sort the people array. Once this is done just pick the first five elements.
Best way is to sort the array people based on the number attribute iso individual swaps.
If you want to go ahead with current approach use strcpy functions iso "=" operator for name
Rather than keeping track of 5 out of total 10 indices, sorting seems better to me.
You can use qsort to sort the 10 elements and then pick the top 5.
int cmp(void *a,void *b)
{
struct info as=*((struct info*)a);
struct info bs=*((struct info*)b)
return bs.number-as.number; //sorting in descending order
}
and then
qsort(people,10,sizeof people[0],cmp);

Passing structures to functions in C

Define a struct named Book. Each book should have a name with
exactly 3 letters (abbreviation). Each book should also have a page
count (integer), and a price (integer).
Write a program which reads an integer n first, then reads the
names, page counts and prices of n books.
Write a function which takes an array of books, and sorts them
according to their prices. Using that function, your program should
print the names and page counts of each book with the order of their
prices.
My Question
Can someone explain to me how to pass a structure into a function and get this code to work? Or how they would go tackle this question.
struct Book{
char name[3];
int pagec;
int price;
};
void price(int size, struct Book books[size]){
int i,j, tmp;
for(i=0; i<size; i++){
for(j=0; j<size-1; j++){
if(books[j].price < books[j+1].price){
books[j].price = tmp;
books[j].price = books.price[j+1];
books.price[j+1] = tmp;
}
}
}
}
int main(void) {
int n;
scanf("%d", &n);
struct Book books[n];
int i,j;
for(i=0; i<n; i++){
for(j=0; i<1; j++){
scanf("%c", &books[i].name);
scanf("%d", &books[i].pagec);
scanf("%d", &books[i].price);
}
}
price(n, books[n]);
for(i=0; i<n; i++){
printf("%c: %d - %d",books[i].name, books[i].pagec, books[i].price);
}
The part of your question about how to pass a struct seems to have been well answered, let me get on the second part: how I would tackle that question.
What the struct should be is described well, so we can write without much thinking:
/*
Define a struct named: Book.
Each book should have a name with exactly 3 letters (abbreviation).
Each book should also have a page count (integer),
and a price (integer).
*/
typedef struct book {
// three characters plus '\0'
char name[4];
int pagec;
int price;
} book_t;
(No need for a typedef you can leave that part out and use the struct directly with struct books)
They want three functions, one is main() we can use it as one of the three. I think getting the info, allocating the memory etc. is a good use of the main() function here.
/*
Write a program which
reads an integer n first,
then reads the names,
page counts
and prices of n books.
*/
int main()
{
int n, i;
book_t **books;
puts("How many books?");
scanf("%d", &n);
// we need enough memory to safe "n" structs
// at first allocate memory for n pointers
books = malloc(n * sizeof(book_t *));
// at each pointer allocate enough memory for one struct books
for (i = 0; i < n; i++) {
books[i] = malloc(sizeof(book_t));
}
// red the info from stdin
for (i = 0; i < n; i++) {
printf("Name of book (3 letter abbrev.):");
scanf("%3s", books[i]->name);
printf("Number of pages:");
scanf("%d", &books[i]->pagec);
printf("Price of book (incl. taxes):");
scanf("%d", &books[i]->price);
}
// call function to sort them
sort_books(books, n);
// call a function to print the sorted list
print_books(books, n);
// we don't need the memory anymore, so free it
// at first free the individual structs
for (i = 0; i < n; i++) {
free(books[i]);
}
// then free the memory holding all of the pointers
free(books);
exit(EXIT_SUCCESS);
}
The two functions for printing and sorting are similar in argument handling
/*
Write a function which takes an array of books,
and sorts them according to their prices.
Doesn't say something about output, so sort in situ
*/
void sort_books(book_t ** books, int length)
{
// OP had bubble sort, so lets do a bubble sort. Why not?
int i, j;
book_t *tmp;
for (i = 0; i < length - 1; i++) {
for (j = 0; j < length -i - 1; j++) {
if (books[j]->price < books[j + 1]->price) {
tmp = books[j];
books[j] = books[j + 1];
books[j + 1] = tmp;
}
}
}
}
Printing them all is quite straightforward
/*
Using that function, your program should
print the names and page counts of each book with the order of their prices.
*/
void print_books(book_t ** books, int length)
{
int i;
for (i = 0; i < length; i++) {
printf("Name %s, pages %d, price %d\n",
books[i]->name, books[i]->pagec, books[i]->price);
}
}
It doesn't say anything about the exact order, I took the liberty to use a descending order (from highest to lowest). If you want an ascending order (from lowest to highest) change the comparing in the sorting algorithm:
void sort_books(book_t ** books, int length)
{
// OP had bubble sort, so lets do a bubble sort
int i, j;
book_t *tmp;
for (i = 0; i < length - 1; i++) {
for (j = 0; j < length - i - 1; j++) {
// if (books[j]->price < books[j + 1]->price) {
if (books[j]->price > books[j + 1]->price) {
tmp = books[j];
books[j] = books[j + 1];
books[j + 1] = tmp;
}
}
}
}
Please be aware that I omitted all checks! You need to check the returns of malloc() and scanf(), if n is an integer, if all of the other numbers are numbers and so on!
books[n] is one struct Book (or would be, if the array had n+1 elements).
The name of the array is just books, and this is what you should pass to the function:
price(n, books);
So you have your struct
struct Book{
char name[10];
int pagec;
int price;
};
You can pass it in by passing in a pointer to it using the "address of" operator
void receivingFunction(Book* myBook)
{
printf("%s", myBook->name);
}
void sendingFunction()
{
Book myBook;
//set values in myBook
receivingFunction(&myBook);
}
Notice that when you are working with the pointer to book, you access members using the -> operator, not the . operator.
Now that example above is just for passing in a single instance. What if you want to pass in an array? It'll look something like this.
#include <stdio.h>
#include <string.h>
struct Book{
char name[4]; //other answers explain well why I changed this to 4
int pagec;
int price;
};
void BookSorter(struct Book books[10], int booksLength)
{
int i;
for(i = 0; i < booksLength; i++)
{
printf("%s %d %d\n", books[i].name, books[i].pagec, books[i].price);
}
}
int main(void)
{
Book books[10];
//define your values for books here
//mine are junk values since this is just an example
for(int i = 0; i < 10; i++)
{
strncpy(books[i].name, "aaa", 4);
books[i].pagec = 4;
books[i].price = 10;
}
//
BookSorter(books, 10);
}
From here you can modify your bubble sort to iterate through your array instances and swap them. I'm not going to include that part because 1) it is beyond the scope of your original question about passing structs and 2) it really looks like you're doing homework and I don't want to give you all of it. The comments below your question address ways to fix your bubble sort, one I haven't seen yet is that you're just swapping the prices of the books, not the books themselves. Your temp variable should be a struct Book, not an int. Your swapping just swaps the prices of the books, which will lead to them being assigned to the wrong book for the final printing out of the answer, with the books and page counts being left in the same order they were read in. It looks like you used this example code (or maybe one of a million like it), but here it is if you need a reference for implementing bubble sort.

Dynamic Array inside an Dynamic Array [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have here some sample code that has what I think is needed to solve my problem.
Basicaly I need to store inside an array that has a variable amount of entries a variable amount of reasons for it. Is this array[5].b[3] not allowed? Is there any alternative for it?
Thanks in advance
typedef struct {
int a;
char *reasons;
}t_a;
f() {
int space=10,spaceReasons=5;
t_a *array;
array=NULL;
array=realloc(array,sizeof(t_a)*space);
array[5].reasons=realloc(array[5].reasons,sizeof(char)*spaceReasons);
fgets (array[5].reasons[3]),300, stdin);
free(array);
}
Here's a working example:
#include <stdlib.h>
#include <stdio.h>
typedef struct {
int a;
char* reasons;
} t_a;
int main(void) {
int space = 10, spaceReasons = 5;
t_a* array = NULL;
array = realloc(array, sizeof(t_a) * space);
for (int i = 0; i < space; i++) {
array[i].reasons = NULL;
array[i].reasons = realloc(array[i].reasons, sizeof(char) * spaceReasons);
// fill with fgets
fgets (array[i].reasons, spaceReasons, stdin);
}
// print results
for (int i = 0; i < space; i++) {
printf("%s\n", array[i].reasons);
}
// first free all reasons
for (int i = 0; i < space; i++) {
free(array[i].reasons);
}
// then free array
free(array);
}

Frequency Count of Number in an array in C is this code effective and efficient [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have the following code in c for counting frequency of number from array:
#define MAX 10
int flag=0;
void display(int no,int cnt,int visi[]);//function declaration
int main()
{
int arr[]={1,1,1,2,3,4,2,2,3,1};//asume any array or we can enter from user
int visited[MAX];
int i,j,no,cnt=1;
clrscr();
for(i=0;i<10;i++)//loop
{
no=arr[i];
cnt=1;
for(j=i+1;j<10;j++)
{
if(no==arr[j])
cnt++;
}
display(no,cnt,visited);
}
return 0;
}
void display(int no,int cnt,int visited[])
{
int static i;
int j;
if(flag==1)
for(j=0;j<=i;j++)
{
if(visited[j]==no)
goto a;
}
i++;
flag=1;
printf("\n%d=%d",no,cnt);
visited[i]=no;
a:
}
Please help to improve my code or suggest any other technology for effectiveness
is this algorithm effective and efficient or not please give feedback.
You can sort the array first by merge sort (O(n log n)) and then calculate the frequency of a number by single loop like this-:
int j=0;
for( i = 0; i < 9; i++ )
{
if (arr[i] == arr[i+1])
cnt++;
else
{
visited[j] = cnt;
cnt = 0;
j++;
}
}
to count frequency of numbers in array, try this code
#include <stdio.h>
#define MAX 10
int countArray[MAX];
int main()
{
int arr[]={1,1,1,2,3,4,2,2,3,1},i;
for(i=0;i<MAX;i++)
countArray[i]=0;
for(i=0;i<MAX;i++)
countArray[arr[i]]++;
for(i=0;i<MAX;i++)
{
if(countArray[i])
printf("%d %d\n",i,countArray[i]);
}
return 0;
}
You don't say this explicitly, but it looks as if you had an array of non-negative numbers whsoe values is smaller than MAX.
If the range of the numbers is known, you can create an array of counts. Visit each element of the array once and increment the count for that element. Then pass through the array of counts and output it as appropriate.
This method works well if the range of valid numbers and therefore the size of the count array is small. (You have the same problem for your visited array, whose size is the same as the size of an array of counts.)
The example below implements counting with an array of counts. The code also takes care of values that fall outside the valid range of MIN to MAX inclusively.
#include <stdio.h>
#define MIN 1
#define MAX 10
int main()
{
int arr[] = {1, 1, 1, 2, 3, 4, 2, 2, 3};
int narr = sizeof(arr) / sizeof(arr[0]);
int count[MAX + 1 - MIN] = {0};
int uncounted = 0;
int i;
for(i = 0; i < narr; i++) {
if (arr[i] < MIN || arr[i] > MAX) {
uncounted++;
} else {
count[arr[i] - MIN]++;
}
}
for(i = MIN; i < MAX + 1; i++) {
if (count[i - MIN]) {
printf("element %d ocurs %d times.\n", i, count[i - MIN]);
}
}
if (uncounted) {
printf("%d elements were not accounted for.\n", uncounted);
}
return 0;
}
int main()
Is implementation dependant. You do not wan't to use this, some compilers will not accept it.
Use
int main(void)
instead
for(i=0;i<10;i++)//loop
You already defined MAX, so why not use it there. Stuff like this makes code harder to maintain.
The efficiency is dependant on the input values you have. For small arrays with small numbers, this works fine otherwise.

Resources