Creating array of structure - c

I have been busy with a question from a C book. The question is simple but it has some specific parts.
I would like to ask a question about arrays.
My question is about the best way with creating an array of a structure. The question wants these all;
Firstly create an array of structure. Secondly, create a linked list which connects these arrays with a restp pointer.
I want to divide my question into sub parts. First part is array of structure...
How can I create an array of a structure. I've made a research about this. And here is my way:
I'm creating a structure for my array of structure:
struct student{
int id;
struct courseList_node_s *restp;
};
And my linked list for completing rest of question:
typedef struct courseList_node_s{
char course[6];
int credit,
section;
struct courseList_node_s *restp;
}courseList_node_t;
I have implemented some function to handle this student schedule.
In my get_studentList function;
I declared my array as this;
struct student *ansp[size];
And making memory allocation;
ansp[i] = malloc(sizeof(struct student));
And lastly assigning a value;
ansp[i]->id =id;
Now, my problem is while creating an array, I couldn't make it as an ordered array. For instance, the user can type 1111, 1222, 1232, and then 1011. So, my first element of array which is ansp[0] = 1011, and ansp[1] = 1111.
I couldn't figure out.
Can you give me an algorithm which consist these(Creating an ordered array of structure).
Lastly, sorry for my bad English and I may made some grammatical mistakes...
Thanks in advance.

To order the elements, you will need to sort them. In C, you probably want to use qsort (in C++ there are easier ways). You will need to define a comparison function on struct student * and call qsort on your array with it.
See this example for inspiration. Note that your array is an array of structure pointers, the example is an array of direct structures (which is maybe what you wanted anyway?).

Can you give me an algorithm which consist these(Creating an ordered array of structure).
If you want to create an orderd array of structures, you probably want to build a tree.
There are libraries for that, but to learn and understand, you can Google 'Binary trees in C' or something like that, e.g.:
http://www.macs.hw.ac.uk/~rjp/Coursewww/Cwww/tree.html
Trees will allow your user to insert non-sorted values and retrieve them in sorted order (also, search them more quickly).

I'd solved the problem with helps #Keith Randall and
lserni
I have implemented both binary search tree and array of structure.
First way, sorting array with qsort:
I had to create a compare function:
int compare(const void *p1, const void *p2){
return (* (struct student **) p1)->id - (* (struct student **) p2)->id;
}
And my other helper functions;
void get_studentList(struct student **listp,int size){
int id,i;
struct student *ansp[size];
for(i=0;i<size;i++){
printf("Enter student's id to exit enter -1> ");
scanf("%d", &id);
ansp[i] = malloc(sizeof(courseList_node_t));
ansp[i]->id = id;
ansp[i]->restp = NULL;
}
qsort (ansp, size, sizeof(struct student *), compare);
for(i=0;i<size;i++){
listp[i] = ansp[i];
}
}
courseList_node_t * insert_studentSchedule(courseList_node_t *headp, int size){
courseList_node_t *cur_nodep;
if(headp == NULL){
cur_nodep = scan_course();
headp = cur_nodep;
} else {
headp->restp = insert_studentSchedule(headp->restp,size);
}
return (headp);
}
And my display function;
void display_schedule(struct student **headp, int size){
courseList_node_t *cur_nodep;
int i = 0;
while(i< size){
cur_nodep = headp[i]->restp;
printf("Student id > %d\n", headp[i]->id);
while(cur_nodep != NULL){
printf("Course name> %s\t", cur_nodep->course);
printf("Course credit> %d\t", cur_nodep->credit);
printf("Course section> %d\n", cur_nodep->section);
cur_nodep = cur_nodep->restp;
}
i++;
}
}
Second way, Binary Search Tree:
I changed typedef parts of my header file as this:
typedef struct tree_node_s{
int id;
struct courseList_node_s *restp;
struct tree_node_s *leftp, *rightp;
}tree_node_t;
And my macro to formalize a standart pattern in dynamic allocation of nodes:
#define TYPED_ALLOC(type) (type *)malloc(sizeof(type))
And my implementation of creating a binary search tree:
/*
* Insert a new id in a binary search tree.
* Pre: rootp points to the root node of a binary search tree
*/
tree_node_t * get_studentTree(tree_node_t *rootp, int newId)
{
if (rootp == NULL){
rootp = TYPED_ALLOC(tree_node_t);
rootp->id = newId;
rootp->restp = NULL;
rootp->leftp = NULL;
rootp->rightp = NULL;
} else if ( newId == rootp->id){
/* */
} else if (newId < rootp->id){
rootp->leftp = get_studentTree(rootp->leftp, newId);
} else {
rootp->rightp = get_studentTree(rootp->rightp, newId);
}
return (rootp);
}
This parts are not related with this question. I gave them because I want to share the partial solution of real question.
/*
* Its aim to add courses to restp component of subtree
* It may have some problems. And you can omit it. Because it not related with this question
* Pre: elementp not empty
*/
courseList_node_t * add_course(courseList_node_t *nextp, courseList_node_t *elementp){
if(nextp->restp == NULL){
nextp->restp = elementp;
} else {
nextp->restp = add_course(nextp->restp,elementp);
}
return (nextp);
}
/*
* It is not neccessary to first call get_studentTree function. It simply creates a linked list which consist of student class/lecture schedule.
* Pre: ele and id not empty
* Post: Tree returned includes all schedule and retains binary search tree properties.
*/
tree_node_t * insert_studentSchedule(tree_node_t *rootp,courseList_node_t *ele, int id){
if (rootp == NULL){
rootp = get_studentTree(rootp, id);
rootp->restp = TYPED_ALLOC(courseList_node_t);
strcpy(rootp->restp->course, ele->course);
rootp->restp->credit = ele->credit;
rootp->restp->section = ele->section;
}
else if(rootp->id == id){
if ( rootp->restp == NULL ){
rootp->restp = TYPED_ALLOC(courseList_node_t);
strcpy(rootp->restp->course, ele->course);
rootp->restp->credit = ele->credit;
rootp->restp->section = ele->section;
} else {
rootp->restp = add_course(rootp->restp, ele);
}
} else if ( id < rootp->id ){
if ( rootp->leftp != NULL )
rootp->leftp = insert_studentSchedule(rootp->leftp, ele, id);
} else if ( id > rootp->id ) {
if ( rootp->rightp != NULL )
rootp->rightp = insert_studentSchedule(rootp->rightp, ele, id);
}
return (rootp);
}
/*
* Course scanning function
*/
courseList_node_t * scan_course(void){
courseList_node_t *cur_coursep;
char courseName[6];
cur_coursep = (courseList_node_t *)malloc(sizeof(courseList_node_t));
printf("Welcome to course scanning part>\n");
printf("Enter the name of course> ");
scanf("%s", courseName);
strcpy(cur_coursep->course, courseName);
printf("Enter the credit of course> ");
scanf("%d", &cur_coursep->credit);
printf("Enter the section of course> ");
scanf("%d", &cur_coursep->section);
cur_coursep->restp = NULL;
return (cur_coursep);
}
/*
* My way to print binary search tree with all elements
*/
void display_schedule(tree_node_t *rootp){
courseList_node_t *cur_course;
if(rootp == NULL)
return;
display_schedule(rootp->leftp);
if (rootp->restp == NULL)
printf("Tree with id: %d element has no member!", rootp->id);
else {
cur_course = rootp->restp;
while (cur_course != NULL){
printf("Student Id> %d\n", rootp->id);
printf("Course name> %s\t", rootp->restp->course);
printf("Course credit> %d\t", rootp->restp->credit);
printf("Course section> %d\n", rootp->restp->section);
cur_course = cur_course->restp;
}
}
display_schedule(rootp->rightp);
}
It may not full solution of book question but with your helps, It is solution of essential parts. If you found a mistake. Feel free to add a comment.

Related

Linked list in C, names overwrite

Help me, I am just a newbie.
I am currently studying and practicing linked list in C. I want to arrange the names of the instruments according to their sizes.
Problem is, every time I create a new instrument, the names of the previous instruments are overwritten by my newly created instrument but the sizes are not overwritten.
Why and What's happening there?
for example, the first instrument is "FLUTE" and size is 1, it will display those info. But when the 2nd loop comes and I input the second instrument ex., name is "TRUMPET" and size is 3, "FLUTE" gone..! It will display
name: TRUMPET, size: 1 //but the size is still there.
name: TRUMPET, size: 3
//here's my main
int main(void)
{
int add = 1;
int size;
char name[30];
instrument *start = NULL;
instrument *x = NULL;
instrument *y = NULL;
instrument *next = NULL;
while(add != 0)
{
printf("Enter the name of the instrument: ");
scanf(" %29s", name);
printf("Size: ");
scanf(" %d", &size);
next = pos(name, size);
if(start == NULL)
{
start = next;
}
if(x != NULL)
{
x->next = next;
}
x = next;
//for now, I'll just display the instruments instead of sorting them.
displayInstruments(start);
printf("\nDo you want to add more?: ");
scanf(" %d", &add);
}
freeInstruments(start);
return 0;
}
//this is my instrument creator function
instrument* pos(char *name, int size)
{
instrument *i = malloc(sizeof(instrument));
i->name = name;
i->size = size;
i->next = NULL;
return i;
}
//and other codes below here that don't matter for now. . . . . . . .
.
.
.
.
You create space for each instrument, but use the same space (the global variable name) for each of their names.
You are using a single buffer to store the name of each instrument. By default, ints will be copied so that you are correctly storing the size of each instrument. With strings, however, you store a pointer which holds the memory location of string. All of your instrument->name pointers are pointing to the same memory location, so they will all display the most recently added instrument name.
To fix this, change i->name = name to i->name = strdup(name), which will duplicate the string and create it's own personal copy.

allocating in heap memory array of pointers to struct

I'm trying to make simple data base by using structure like
struct Employee{
char* name;
int ID;
int GPA;
int salary;
};
i know how i can allocate one pointer of the struct type in heap by using that
struct Employee* emp=malloc(sizeof(Employee));
my problem now that i'm not very good in allocating processes and i want
to allocate N number of pointer of the struct in the heap and i can't use arrays because the size will not be knows until running time
any suggestions ?
Yes, you need to allocate the memory dynamically, i.e. allocate a new heap block for every new struct Employee.
You can do this for example using realloc when the size changes:
yourArrayPtr=realloc(yourArrayPtr,newsize * sizeof(struct Employee));
The realloc function basically assigns a new amount of memory for the data pointed by its return value. It is a convenient way of expanding, or shrinking a dynamically allocated array. newsize here is the new number of elements of your array, and it is multiplied by the size of one Employee structure, rendering the total amount of space needed for your new array. The return value of realloc is assigned to your array pointer, so that it points specifically to this newly allocated space. In this case it could be used like this:
struct Employee* emp= NULL;
And then when you need it:
int n = 8;
emp = realloc (emp, n * sizeof(struct Employee));
Keep in mind, that you still have to free this memory.
You can now initialize and access this data:
emp[3] = {value1, value2, value3, ...};
As far as structures go, you could also think of another data structure - a linked list, where every structure contains a pointer to its successor. You can read about it here: http://www.cprogramming.com/tutorial/c/lesson15.html
In your case, it would be sth like:
struct Employee{
char* data;
struct Employee* next;
};
As others mentioned, you can use malloc to create as many entries of employee details in heap and store them in a dynamic list(linked list). i have given an example code, you can start from here and extend it, if you want to save the employee details before exiting, you can write it to a binary file and read it back when you run the program again(based on your needs), since once you program exits all the data will be lost.
#include <stdio.h>
#include <stdlib.h>
// Max length for employee name
const unsigned int MAX_NAME_LEN = 100;
typedef struct Employee{
char* name;
unsigned int ID;
int GPA;
float salary;
} EMPLOYEE ;
typedef struct emp_database_entry {
EMPLOYEE data;
struct emp_database_entry *next;
} EMPLOYEE_ENTRY;
typedef EMPLOYEE_ENTRY* EMPLOYEE_DATABASE;
// to create a new employee
EMPLOYEE_ENTRY* createEmployee() {
EMPLOYEE_ENTRY *newEmp = (EMPLOYEE_ENTRY*)malloc(sizeof(EMPLOYEE_ENTRY));
printf("Enter Employee Name:");
newEmp->data.name = (char*)malloc( MAX_NAME_LEN * sizeof(char) );
scanf("%s",newEmp->data.name);
printf("Enter employee ID:");
scanf("%u",&newEmp->data.ID);
printf("Enter employee GPA:");
scanf("%u",&newEmp->data.GPA);
printf("Enter employee salary:");
scanf("%f",&newEmp->data.salary);
newEmp->next = 0;
return (newEmp);
}
// add a new employee to database
EMPLOYEE_DATABASE addEmployee(EMPLOYEE_DATABASE db) {
EMPLOYEE_ENTRY *newEmp = createEmployee();
if(db == NULL) {
// add the first entry
db = newEmp;
} else {
// add it to the top
newEmp->next = db;
db = newEmp;
}
return (db);
}
// Search for Employee using ID
EMPLOYEE_ENTRY* searchEmployee(EMPLOYEE_DATABASE db, unsigned int ID) {
EMPLOYEE_ENTRY *employee = db;
if(employee == NULL) {
printf("There are no Employees in the database\n");
return (NULL);
}
// Search till the end, if a match is found return the
// pointer to employee
while( employee != NULL ) {
if( employee->data.ID == ID )
return (employee);
else
employee = employee->next;
}
return (NULL);
}
void printOneEmployee( EMPLOYEE_ENTRY *employee ) {
printf("Employee Details\n");
printf("Name : %s\n",employee->data.name);
printf("ID : %u\n",employee->data.ID);
printf("GPA : %d\n",employee->data.GPA);
printf("Salary: %f\n\n",employee->data.salary);
}
// Print all employee details
void printAllEmployee( EMPLOYEE_DATABASE db ) {
EMPLOYEE_ENTRY *employee = db;
// traverse till the end and print one by one
while( employee != NULL ) {
printOneEmployee(employee);
employee = employee->next;
}
}
// freeing allocated memory
void freeDatabase(EMPLOYEE_DATABASE db) {
EMPLOYEE_DATABASE employee = 0;
while( db != NULL ) {
employee = db;
db = employee->next;
free(employee->data.name);
free(employee);
}
}
void displayOption( EMPLOYEE_DATABASE db ) {
int option = -1;
while( option != 5 ) {
printf("\nEmployee DataBase\n");
printf("1: Add a Employee\n");
printf("2: Search Employee\n");
printf("3: Print All Employee\n");
printf("4: Exit\n");
printf("Enter a number for the choice: ");
scanf("%d",&option);
if( option > 4 || option < 0 ) {
option = -1;
}
switch( option ) {
case 1:
db = addEmployee(db);
break;
case 2:
int ID;
if(db != NULL){
printf("Enter the Employee ID: ");
scanf("%d",&ID);
printf("Search Result1: ");
printOneEmployee(searchEmployee(db, ID));
}
else
printf("No Employees in the database\n");
break;
case 3:
printAllEmployee(db);
break;
case 4:
freeDatabase(db);
printf("DataBase Deleted\nExiting..");
exit(0);
default:
printf("Invalid Option!. Try Again!.\n");
}
}
}
int main() {
EMPLOYEE_DATABASE db = 0;
displayOption(db);
return (0);
}
Of course you can use arrays if you use C99. In C99 you can do things like:
scanf("%d", &N);
struct Employee emp[N];
emp[0].ID = 123;
if you are using gcc (or MinGW), just be sure to compile with -std=c99
On the other hand, if you just want to create an array on the heap, you can do something like:
scanf("%d", &N);
struct Employee* emp=malloc(N*sizeof(Employee));
emp[0].ID =123;
...
// do not forget to deallocate emp
free(emp);

ATP list in C, reading and saving usernames

I have a problem writing a code that should read usernames and put them in list. Every username should be connected to the number of times it has been entered. The problem occurs when entering the second username, my code places that username in the variable called first (where the first is kept). I guess I've done something wrong with the pointers, but I cannot find what. I am confused, in the end of one while loop the first one is the real first one, and when the program enters while again, variable first changes. How could that be? Please help me.
Thank you :)
typedef struct _user
{
char *name;
int counter;
struct _user *next;
} user;
int main() {
char userName [10];
int found = 0, go_on = 1;
user *first = NULL, *temp, *new;
while (go_on == 1) {
printf ("Username: ");
scanf("%s", userName);
if (first) {
// printf ("The first one in list: %s\n", first->name); - this prints the name of last username entered
for (temp = first; temp; temp = temp->next) {
if (strcmp (temp->name, userName) == 0) {
temp->counter++;
found = 1; }
if (found== 1) break;}
if (!found) {
new = (user*) malloc (sizeof(user));
new->name = userName;
new->counter = 1;
temp = new;
temp->next = NULL; } }
else {
new = (user*) malloc (sizeof(user));
new->name = userName;
new->counter = 1;
first = new;
first->next = NULL; }
printf ("Go on? (1/0)");
scanf("%d", &go_on);
printf ("Current list: ");
for (temp=first; temp; temp = temp->next)
printf("%s %d\n", temp->name, temp->counter);
//printf ("The first one in list: %s\n", first->name); - this prints the correct first
}
}
Your error, I think, is the userName array. You should allocate a new one for each element in your linked list. When you write new->name = userName;, you are not copying the name to the struct, you are making the struct point to your userName[10] array. As such every struct's actual "name" is storing only the single last name scanf-ed. That being said...
I generally prefer to write that kind of code with dedicated tools instead of logically embedding them in a loop construct:
Keeping your struct:
typedef struct _user
{
char *name;
int counter;
struct _user *next;
} user;
I would create a function that, given a properly constructed Sll returns a matching element:
function user *user_match_name(user *user_head, const ch *name)
{
user *cur_user = NULL;
/* look for a match */
for (cur_user = user_head ; cur_user ; cur_user = cur_user->next)
if(!strcmp(name,cur_user->name) return cur_user;
/* no match */
return NULL;
}
Then I usually prefer to have an Sll element builder:
function user *create_user(const ch *name)
{
user *new_user;
if(!(new_user = malloc(sizeof(user))))
printf("Error in allocation"); /* or better malloc error handling */
/* IMPORTANT: PROVIDE MEMORY FOR THE NAMES!!! */
if(!(new_user->name = malloc(sizeof(char)*256))) /* sizeof(char) is useless but I like to explicit it like that. And 256 should be enough a buffer could be better made */
printf("Error in allocation"); /* or better malloc error handling */
strncpy(new_user->name, name,256); /* not sure if I got the argument order right... */
new_user->counter = 0; /* or 1 depending on your prefered convention */
new_user->next = NULL;
return new_user;
}
It ease the debugging like you wouldn't believe! Then it's just a matter of rewriting your main function:
int main() {
char userName [10];
int found = 0, go_on = 1;
user *user_head = NULL, *new_user,*temp;
while (go_on == 1) {
printf ("Username: ");
scanf("%s", userName);
if( (new_user = user_match_name(user_head,userName)) )
++new_user->counter
else
new_user = create_user(userName);
/* Here we push on the Sll */
if(user_head){
new_user->next = user_head;
user_head = new_user;
} else {
user_head = new_user;
}
printf ("Go on? (1/0)");
scanf("%d", &go_on);
printf ("Current list: ");
for (temp = user_head; temp; temp = temp->next)
printf("%s %d\n", temp->name, temp->counter);
//printf ("The first one in list: %s\n", first->name); - this prints the correct first
}
}
Ahhhhhh! Much easier to read. Be mindful of: 1) I didn't compile check the code. The important ideas are there, leverage them. 2) Even in your previous implementation, you are white space vulnerable but that's somewhat another topic.
Or you could cimply fix it by doing:
typedef struct _user
{
char name[10];
int counter;
struct _user *next;
} user;
and strncpy(new->name,userName,10) instead of assigning the pointer.

Why can't I remove a person from an array?

I've been sitting with this code for three days. The problem is that I have reached the rock bottom and I don't know how I will solve this without any help from you guys. I have a struct with arrays of type char name, surname, persnbr.
struct pers
{
char name[7];
char last_name[10];
char id_nbr[12];
};
I have solved the problem with adding name surname and persnbr in the arrays but now I don't know how to remove them.
This is the queueEn function
void queueEn(person p1){
strcpy(queue[last].name, p1.name);
strcpy(queue[last].last_name, p1.last_name);
strcpy(queue[last].id_nbr, p1.id_nbr);
}
and the queueAdd function
void queueAdd(person person1)
{
if(last<MAX_SIZE_QUEUE){
printf("Name: ");
scanf("%s", person1.name);
printf("Last name: ");
scanf("%s", person1.sur_name);
printf("Id-number: ");
scanf("%s", person1.id_nbr);
last++;
}else {
printf("Queue is full\n");
}
queueEn(person1);
}
This code works excellent.
Now I have the functions queueDe and queueRemove
This is what I've done so far:
void queueDe(person *personPoint){
first = (first + 1)% MAX_SIZE_QUEUE;
*personPoint = queue[first];
strcpy(personPoint->name, queue[first].name);
strcpy(personPoint->last_name, queue[first].last_name);
strcpy(personPoint->id_nbr, queue[first].id_nbr);
}
The thing is that I have to copy the information from array so I assumed that's how you do it. The information will be shown to the user(the person who is the last on the queue(FIFO-structure))
Here is the function remove_from_queue
void queueRemove(person personRem){
if(first < MAX_SIZE_QUEUE){
printf("Name: %s", personRem.name);
printf("Last Name: %s", personRem.last_name);
printf("Id-Number: %s", personRem.id_nbr);
first++;
}else{
printf("Queue is empty");
}
queueDe(&personRem);
}
The variables first and last are equivalent with the end of array and the beginning of array. To delete the last person in the array I have to delete the person on first. Both of the variables are initialized to 0 in the beginning. I've read that I need to initialize the pointer *personPoint to malloc but I don't know how to use it in this specific situation.
When I execute the program and want to delete the person nothing happens.
I'm thankful for an answer.
A circular queue is a reasonable data structure, but you need a clear grasp of your queue 'empty' and queue 'full' conditions. First we will define a circular queue struct, which holds first, last and queue[] array elements,
typedef struct circular_array_queue_s
{
person* queue[MAX_SIZE_QUEUE];
int first;
int last;
} CirQueue;
CirQueue cirq;
Now we can define functions to report whether the queue is empty, full, and to report the count of the number of elements,
int queueEmpty()
{
if( cirq.first == cirq.last ) //queue empty
{
printf("Queue is empty");
return 1;
}
return 0;
}
int queueFull()
{
if( ((cirq.last+1%MAX_SIZE_QUEUE)) == cirq.first ) //queue full
{
printf("Queue is full\n");
return 1;
}
return 0;
}
int queueCount()
{
int count=0;
if( cirq.first<=cirq.last )
count=(cirq.last-cirq.first);
else //if ( cirq.first>cirq.last )
count=(cirq.last+MAX_SIZE_QUEUE)-cirq.first;
return count;
}
The queue operations for enqueue and dequeue are simplified, as you enqueue at the queue last position, and dequeue from the queue first position. Since you have a circular queue, moving the first and last indices is done by incrementing by one, and wrapping at the end (using modulus MAX_SIZE_QUEUE),
person*
queueEn(person* p)
{
//err
if( queueFull() ) { return NULL; } //queue full, fail
cirq.queue[cirq.last] = p;
cirq.last = (cirq.last+1)%MAX_SIZE_QUEUE; //one
return p;
}
person*
queueDe()
{
person* p;
//err
if( queueEmpty() ) { return NULL; } //queue empty, fail
p = cirq.queue[cirq.first];
cirq.queue[cirq.first] = NULL;
cirq.first = (cirq.first+1)%MAX_SIZE_QUEUE;
return p;
}
Walking (iterating) over the entire can be done using a function similar to,
person*
queueIterate()
{
person* p;
int iter;
if( queueEmpty() ) { return NULL; } //queue empty, skip
for( iter=cirq.first; iter!=cirq.last; iter=(++iter)%MAX_SIZE_QUEUE )
{
personPrint(p = cirq.queue[iter]);
}
return p;
}
Adding elements to the queue requires that you create elements to add (malloc), and properly dispose of elements when you remove them (free),
void queueAdd(person person1)
{
if( queueFull() ) { return; } //queue full, cannot add
personRead(&person1);
person* p;
queueEn(personCopy(p=personNew(),&person1));
}
person*
queueRemove(person* personRem)
{
person* p;
if(p = queueDe())
{
if(personRem) {
personCopy(personRem,p); personDel(p);
}
//if you don't give a personRem, you must free person p removed from queue
else
personRem=p;
}
return personRem;
}
You want to test these queue functions,
int
main()
{
person per;
person* perp;
int done=0;
while(!done)
{
queueAdd(per);
if( queueFull() ) done=1;
if( queueCount() >= 3 ) done=1; //just do three
}
queueIterate();
while(!queueEmpty())
{
personPrint(perp=queueRemove(&per));
}
}
Please understand that C strings are null-terminated, so declaring your char[] using an N+1 idiom will clearly communicate the available string size,
typedef struct person_s
{
char name[9+1]; //size to N+1, makes clear the space, "Alexander"(9)
char last_name[10+1]; //room for null-terminator
char id_nbr[12+1]; //you really want to room for null-terminator
} person;
You will find that having functions which encapsulate your member access can make your code more readable, and support a DRY (Dont Repeat Yourself) approach, and hide details which you probably do not want to expose and handle everywhere,
person*
personNew()
{
person* pnew;
if( !(pnew=malloc(sizeof(person))) ) return NULL;
strncpy(pnew->name, ">name", sizeof(pnew->name));
strncpy(pnew->last_name, ">last_name", sizeof(pnew->last_name));
strncpy(pnew->id_nbr, ">id_nbr", sizeof(pnew->id_nbr));
return(pnew);
}
void personDel(person* p)
{
if( !p ) return; //fail, must have valid pointer
free(p);
return;
}
person*
personCopy(person* pd, person* ps)
{
if(!pd || !ps) return;
strncpy(pd->name, ps->name, sizeof(pd->name));
strncpy(pd->last_name, ps->last_name, sizeof(pd->last_name));
strncpy(pd->id_nbr, ps->id_nbr, sizeof(pd->id_nbr));
return(pd);
}
Here are functions to set the member values (often called setters or mutators),
person*
personName(person* p1, char* name)
{
if(!p1 || !name) return p1;
strncpy(p1->name, name, sizeof(p1->name));
return(p1);
}
person*
personLastName(person* p1, char* last_name)
{
if(!p1 || !last_name) return p1;
strncpy(p1->last_name, last_name, sizeof(p1->last_name));
return(p1);
}
person*
personIdNbr(person* p1, char* id_nbr)
{
if(!p1 || !id_nbr) return p1;
strncpy(p1->id_nbr, id_nbr, sizeof(p1->id_nbr));
return(p1);
}
And here are functions to read and print your person struct,
person*
personRead(person* personp) //two
{
if(!personp) return personp;
//you really should allow for more space here
char name[99+1];
char last_name[99+1];
char id_nbr[99+1];
printf("Name: "); scanf("%s", name);
printf("Last name: "); scanf("%s", last_name);
printf("Id-number: "); scanf("%s", id_nbr);
personName(personp,name);
personLastName(personp,last_name);
personIdNbr(personp,id_nbr);
return(personp);
}
void personPrint(person* personp) //five
{
if(!personp) return personp;
printf("Name: %s,", personp->name);
printf("Last Name: %s,", personp->last_name);
printf("Id-Number: %s\n", personp->id_nbr);
}
Note that I used malloc/free and person (pointer to person struct) throughout. You need to learn about pointers if you want to program in C.*

How to fill an array in C with user input values, when the array is of unknown length [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Dynamic array using ANSI C
I am trying to fill an array with the values that the user is typing. However, I do not know in advance how many values will my array have, or how many values the user will type in. The user types in a value at a time, the value is stored in the array, and then the user is again prompted to type in another value, and so forth, until he types in a negative number. When the user types in a negative number, the program prints out all the positive values that the user has entered so far (NOT the negative one, as it is essentially only used for termination of the program).
My problem is:
1) how to declare the array without knowing in advance how big it will be?
2) how to scan for the user input? For example, I am thinking something like this for scanning the input and assigning the values to the array (this is just a part of the code, not all of it, I just want to know if this part of the code will work when I have completed the program):
...
int working = 0;
int i = 0;
do
{
printf("Enter a positive value \n");
scanf("%d",&x);
if (x >= 0)
{
&array[i] = x;
i++;
}
else
{
printf("You have entered a negative number \n");
working = 1;
}
} while (working = 0);
Is this code correct (of course, it is not a complete program)? Also, how do I declare the array, without knowing how big it will be (I have no way of knowing in advance how many positive values the user will type in before he types in a negative one)
You can allocate an initial array for user input and save it's size into a variable so then you can reallocate the array when it's full. Or you could use linked list to save input, so later you could calculate needed element count and allocate the array.
int arraySize = 256; // Or whatever
int *array = malloc(arraySize * sizeof(int));
if (!array)
{
fprintf(stderr, "Master, please buy more RAM, I can't allocate memory\n");
return;
}
int numberOfElements = 0;
for(;;)
{
printf("Enter a positive value:\n");
scanf("%d",&x);
if (x >= 0)
{
if (numberOfElements == arraySize)
{
arraySize *= 2; // Or whatever strategy you need
array = realloc(array, arraySize * sizeof(int));
if (!array)
{
fprintf(stderr, "Master, please buy more RAM, I can't allocate memory\n");
break;
}
}
array[numberOfElements++] = x;
}
else
{
printf("You have entered a negative number \n");
break;
}
}
Something like. Sorry for the possible mistakes, don't check it.
Better use linked list, array won't help you here.
Check this out if you are not familiar with it - http://cslibrary.stanford.edu/103/LinkedListBasics.pdf
int dataarray [2];
int no;
int count =0;
while(1)
{
printf("Enter No's = ");
scanf("%d",&no);
if(no<0)
break;
*(dataarray+count)=no;
count++;
}
you can use the count further to know how many elements in array.
you can get elements from this array by pointers link
no = *(dataarray+count)
You can use a linked list structure for that. There can be many possible implementations (simple linkedlist, double linkedlist ,etc) if you google you can find many pages about this. Here is an example (not necessarily the most optimized form, but just to give you an idea)
#include <stdio.h>
#include <stdlib.h>
struct datalist
{
int value;
struct datalist *next;
};
typedef struct datalist *linkedList;
void addToList(linkedList *param_valueList, const int param_newValue)
{
if (*param_valueList == NULL)
{
linkedList newItem = (linkedList)malloc(sizeof(struct datalist));
newItem->value = param_newValue;
newItem->next = NULL;
*param_valueList = (linkedList)malloc(sizeof(linkedList));
*param_valueList = newItem;
}
else
{
linkedList newList = (linkedList)malloc(sizeof(struct datalist));
newList->value = param_newValue;
newList->next = NULL;
linkedList tmpList = *param_valueList;
while (tmpList->next != NULL)
tmpList = tmpList->next;
linkedList *listPtr = &tmpList;
(*listPtr)->next = newList;
}
}
void printList(const linkedList param_valueList)
{
linkedList tmpList = param_valueList;
while (tmpList != NULL)
{
printf("%d\n", tmpList->value);
tmpList = tmpList->next;
}
}
int main(int argc, char *argv[])
{
int inputNmbr = 0;
linkedList numberList = NULL;
while (1)
{
printf("print a number: ");
scanf("%d", &inputNmbr);
if (inputNmbr > 0)
addToList(&numberList, inputNmbr);
else
break;
}
printf("Here are the numbers you entered:\n");
printList(numberList);
return 0;
}
Regards,

Resources