I want to print the elements from a structure in c, but the send and third print statements give me the warning: format specifies type 'char *' but the argument has type 'char'. I know it has to do with the pointer, but I don't know what I'm doing wrong. I have also modified it to show the 2 structures I am using.
struct student_record{
int student_id;
int student_age;
char first_name;
char last_name; };
struct student_record_node{
struct student_record* record;
struct student_record_node* next;
struct student_record_node* prev; };
void printNode(struct student_record_node *node){
printf("Struct student_record_node: \n");
printf(" student first_name: %s\n", node->record->first_name);
printf(" student last_name: %s\n", node->record->last_name);
printf(" student id: %d\n", node->record->student_id);
printf(" student age: %d\n", node->record->student_age);
printf("\n");}
In the structure declaration of student_record
char first_name;
char last_name;
indicate first_name and last_name are two characters and not character arrays(ie. strings)
When using printf("%s", ELEMENT) , %s requires the memory address of the character array ie. pointer(char *) but since you passed a character instead, it's leading to a syntax error.
To fix your code, edit your structure declaration to make it either a static array of fixed length or dynamically allocate memory to the character pointer in your function.
Try in this way:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#include<string.h>
struct student_record {
int student_id;
int student_age;
char first_name;
char last_name;
};
struct student_record_node {
struct student_record* record;
struct student_record_node* next;
struct student_record_node* prev;
};
void printNode(struct student_record_node *node){
printf("Struct student_record_node: \n");
printf(" student first_name: %c\n", node->record->first_name);
printf(" student last_name: %c\n", node->record->last_name);
printf(" student id: %d\n", node->record->student_id);
printf(" student age: %d\n", node->record->student_age);
printf("\n");
}
int main()
{
struct student_record_node* a = (student_record_node*)malloc(sizeof(student_record_node));
a->record = (student_record*)malloc(sizeof(student_record));
a->next = NULL;
a->prev = NULL;
a->record->first_name = 'f';
a->record->last_name = 'l';
a->record->student_age = 10;
a->record->student_id = 99;
printNode(a);
free(a);
return 0;
}
If you want to set name as string then use char* instead of char and format specifier as %s instead of %c.
Related
In the code below I tried to use printf and scanf to get data from user and store them inside a struct i defined called node.
The programme works fine for the first prompt, but as soon as the user input name, the programme ends with printing Age:salary:
Can anyone help me with this?
On a side note, can anyone also help me to understand how to create a loop to store data in various nodes and store them together? (Not hard-code it one by one)
Thank you very much!!
typedef struct node
{
char *name;
int age;
int salary;
struct node * next;
}node;
int main(void)
{
node *tmp = malloc(sizeof(node));
printf("Name:");
scanf("%s", tmp->name);
printf("Age:");
scanf("%i", &(tmp->age));
printf("salary:");
scanf("%i", &(tmp->salary));
tmp->next = NULL;
free(tmp);
}
Use a char[] for name,
for example:
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
char name[128];
int age;
int salary;
struct node * next;
}node;
int main(void)
{
node *tmp = malloc(sizeof(node));
printf("Name:");
scanf("%s", tmp->name);
printf("Age:");
scanf("%i", &(tmp->age));
printf("salary:");
scanf("%i", &(tmp->salary));
tmp->next = NULL;
free(tmp);
}
If you want to get several users, loop for ever and ask if the user wants to add more data.
I have create a function to print the list
Console:
Name:Foo
Age:12
salary:12
Continue Y/N
Y
Name:Bar
Age:14
salary:14
Continue Y/N
Y
Name:John
Age:30
salary:45
Continue Y/N
N
John, 30, 45
Bar, 14, 14
Foo, 12, 12
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
char name[128];
int age;
int salary;
struct node * next;
}node;
static void printList(node *n)
{
while (n) {
printf("%s, %d, %d\n", n->name, n->age, n->salary);
n = n->next;
}
}
static node *get_nodes(void) {
node *list = NULL;
while (42) {
char c;
node *tmp = malloc(sizeof(node));
printf("Name:");
scanf("%s", tmp->name);
printf("Age:");
scanf("%i", &(tmp->age));
printf("salary:");
scanf("%i", &(tmp->salary));
tmp->next = list;
list = tmp;
printf("Continue Y/N\n");
scanf(" %c", &c);
if (c == 'N')
break;
}
return list;
}
static void clearList(node *node) {
if (node->next) {
clearList(node->next);
}
free(node);
}
int main(void)
{
node *list = get_nodes();
printList(list);
clearList(list);
return 0;
}
You are trying to write to Uninitialized memory
This is a very common problem beginners face.
You are trying to store the name using char *name declaration.
Here name does not point to a valid memory location, that's why You program is not running as expected.
Even if name points to a valid memory address, you must have enough memory allocated to store the data.
You can use
#define BUFFER_SIZE 50
char name[BUFFER_SIZE];
You can use any buffer size as you like, and then store a string of that length - 1 in the name array. -1 is for the null termination character \0.
Using this declaration you are allocating memory of BUFFER_SIZE bytes and the name points to the first byte in that array.
This allocation happens on the stack not in the HEAP
For fix your bug, you should allocate memory of your char *.
First Way, when you create your struct.
typedef struct node
{
char name[200]; // You specify that your char * can save 200 char
int age;
int salary;
struct node * next;
}node;
or you can create init struct function
node *init_node()
{
node *test = null;
test->name = malloc(sizeof(char) * 200);
test->age = 0;
test->salary = 0;
test->node = null;
return test
}
I need to compare to check whether elements are in both stack and linked list or not. I implemented stack using linked list. I created a new method called search_both in a type of void and tried to search.
struct student{
char name[100];
char surname[100];
char roll[10];
char department[50];
struct student *next;
};
struct theStack
{
struct student *head;
struct student *pop;
struct student st;
};
struct theStack myStack;
void search_both()
{
struct student *a;
struct theStack *x;
a=malloc(sizeof *a);
x=malloc(sizeof *x);
if(a&&x)
{
while(strcmp(a->name, x->st.name)==0)
{
while(strcmp (a->surname, x->st.surname)==0)
{
printf("%s %s and %s %s taking both classes",a->name, a->surname,x->st.name,x->st.surname);
a=a->next;
x=x->st.next;
}
}
}
free(a);
free(x);
}
After edit :
I allocated memory for a and x variables as:
a=(struct student*)malloc(sizeof *a);
x=(struct theStack*)malloc(sizeof *x);
After changing it the first loop inside if is became runnable but the other while loop didn't execute. In second while loop I'm trying to compare all surnames What must be the wrong part of second while?
You are not iterating at all, after allocating memory and populating the structs outside the search function:
void search_both( struct student * pStudent, struct theStack * pStack) {
struct sutdent * a = pStudent;
struct theStack * x;
while ( a ) {
x = pStack;
while ( x ) {
if ( strcmp(a->surname,x->st.surname) == 0
&& strcmp(a->name,x->st.name) == 0 )
printf("%s %s and %s %s taking both classes",a->name, a->surname,x->st.name,x->st.surname);
x = x.st->next;
}
a = a->next;
}
}
I created a linked list that hold int and char type data. A function adds the data to the list and the other prints it out. When i only print the int type i get no problems but when i try to also print the char type the program crashes.
So it has to do the way i'm defining the char* in the printing function print_list().
To be more specific my problem is here in print_list() :
printf("\n [%s] \n", ptr -> name);
printf("\n [%s] \n", ptr -> lastn);
So my actual code is (getting 0 errors and 0 warnings but the program crashes):
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// Creating structure for node
struct test_struct
{
int val; // val is member id number
char name;
char lastn;
int age;
struct test_struct *next;
};
// declaring global head and curr pointers
struct test_struct *head = NULL;
struct test_struct *curr = NULL;
// creating a list
struct test_struct* create_list(int val, char* name, char* lastn, int age)
{
printf("\n creating list with head node as [%d] [%s] [%s] [%d] \n", val, name, lastn, age);
struct test_struct *ptr = malloc(sizeof(struct test_struct)); // creating list
if(NULL == ptr) {
printf("\n Node creation failed \n");
return NULL;
}
ptr->val = val;
ptr->name = *name;
ptr->lastn = *lastn;
ptr->age = age;
ptr->next = NULL;
head = curr = ptr;
return ptr;
}
// add member to list
struct test_struct* add_to_list(int val, char *name, char *lastn, int age, bool add_to_end)
{
if(NULL == head) {
return (create_list(val, name, lastn, age));
}
if(add_to_end) {
printf("\n Adding node to end of list with data [%d] [%s] [%s] [%d] \n", val, name, lastn, age);
} else {
printf("\n Adding node to beginning of list with data [%d] [%s] [%s] [%d] \n", val, name, lastn, age);
}
struct test_struct *ptr = malloc(sizeof(struct test_struct));
if(NULL == ptr) {
printf("\n Node creation failed \n");
return NULL;
}
ptr->val = val;
ptr->name = *name;
ptr->lastn = *lastn;
ptr->age = age;
ptr->next = NULL;
if (add_to_end) {
curr-> next = ptr;
curr = ptr;
} else {
ptr -> next = head;
head = ptr;
}
return ptr;
}
//printing the list
void print_list(void)
{
struct test_struct *ptr = head;
printf("\n -----Printing list Start----- \n");
while(ptr != NULL) {
printf("\n [%d] \n", ptr -> val);
printf("\n [%s] \n", ptr -> name);
printf("\n [%s] \n", ptr -> lastn);
printf("\n [%d] \n", ptr -> age);
ptr = ptr->next;
}
printf("\n -----Printing list end---- \n");
return;
}
// main function
int main(void)
{
struct test_struct *ptr = NULL;
// for adding member to list
add_to_list(123, "william", "shakespeare", 30, true);
add_to_list(124, "william", "gibson", 35, true);
add_to_list(125, "chuck", "palahniuk", 40, true);
add_to_list(126, "mario", "puzio", 50, true);
add_to_list(127, "umberto", "eco", 60, true);
add_to_list(128, "ezra", "pound", 125, true);
print_list();
return 0;
}
You have declared name and lastn as single characters
struct test_struct
{
int val; // val is member id number
char name;
char lastn;
int age;
struct test_struct *next;
};
you need to declare them either as fixed size arrays or pointers which point to allocated space to hold the strings. A string is a series of characters terminated by a \0.
struct test_struct
{
int val; // val is member id number
char name[MAXLEN];
char lastn[MAXLEN];
int age;
struct test_struct *next;
};
then copy arguments to the function to the fields in the struct
e.g.
strcpy(ptr->name,name);
strcpy(ptr->lastn,lastn);
printf("\n [%s] \n", ptr -> name);
printf("\n [%s] \n", ptr -> lastn);
%s expects char * not char as both name and lastn are char variables.
And to store name and last name of a person you should prefer char array as single char variable can't store it . Therefore , declare them as char arrays .
Example -
struct test_struct
{
int val; // val is member id number
char name[20]; // or any desired length to store a name
char lastn[20]; // similar as for name
int age;
struct test_struct *next;
};
And then to copy data in it use strncpy-
ptr->name = *name; // strncpy(ptr->name,name,strlen(name));
ptr->lastn = *lastn; // strncpy(ptr->lastn,lastn,strlen(lastn));
I am writing a program that will let user add or delete the car from inventory.Right now,
I am trying to get user to choose a car name instead of explicitly stating name and I created a struct CriteriaSelector in which array name companyList will store value of companies and when I let user choose car name it will copy a string from companyList at a particular index into the char array called carname which will then be copied into carname char array in the CarData object.
The thing is whenever I compile the below code, I get the error saying expected specifier qualifier list before 'companyList' at line 27 and I don't know what to do?
Can anybody help?
#include <stdio.h>
#include <stdlib.h>
#define MAX_WORD_LENGTH 20
typedef struct cardata{
char carname[MAX_WORD_LENGTH];
char carmodel[MAX_WORD_LENGTH];
char caryear[MAX_WORD_LENGTH];
char cartype[MAX_WORD_LENGTH];
int quantity;
}CarData;
struct node{
CarData data;
struct node *next;
struct node *prev;
}*start=NULL;
typedef struct criteriaselector{
const char *companyList[10];
companyList[0] = "Toyota"; <-- This is where error is happening!!(Line 27)
companyList[1] = "Honda";
companyList[2] = "Hyundai";
companyList[3] = "Nissan";
companyList[4] = "Mitsubishi";
companyList[5] = "Volksvagon";
companyList[6] = "Acura";
companyList[7] = "Ford";
companyList[8] = "Dodge"
companyList[9] = "GMC";
}CriteriaSelector;
void insert_first(){
struct node *ptr;
CriteriaSelector criteriaselector;
char carname[MAX_WORD_LENGTH];
char carmodel[MAX_WORD_LENGTH];
char caryear[MAX_WORD_LENGTH];
char cartype[MAX_WORD_LENGTH];
int carQuantity;
int ch;
printf("\nChoose your car");
printf("\n\n\n1.Toyota \n2.Honda \n3.Hyundai \n4.Nissan \n5. Mitsubishi \n6. Volksvagon \n7. Acura \n8. Ford \n9. Dodge \n10. GNC Exit\n");
scanf("%d", &ch);
strcpy(carname,criteriaselector.companyList[ch-1]);
printf("\n\nEnter the car model: ");
scanf("%s", carmodel);
printf("\n\nEnter the car year: ");
scanf("%s", caryear);
printf("\n\nEnter the car type: ");
scanf("%s", cartype);
printf("\n\nEnter the quantity of models: ");
scanf("%d", &carQuantity);
if(start==NULL){
start=(struct node *)malloc(sizeof(struct node));
strcpy(start->data.carname,carname);
strcpy(start->data.carmodel,carmodel);
strcpy(start->data.caryear,caryear);
strcpy(start->data.cartype,cartype);
start->data.quantity=carQuantity;
start->prev=NULL;
start->next=NULL;
}else{
ptr=start;
start=(struct node *)malloc(sizeof(struct node));
strcpy(start->data.carname,carname);
strcpy(start->data.carmodel,carmodel);
strcpy(start->data.caryear,caryear);
strcpy(start->data.cartype,cartype);
start->data.quantity=carQuantity;
start->next=ptr;
}
}
void delete_first(){
struct node *ptr;
char carname[MAX_WORD_LENGTH];
char carmodel[MAX_WORD_LENGTH];
char caryear[MAX_WORD_LENGTH];
char cartype[MAX_WORD_LENGTH];
char modelNumber[MAX_WORD_LENGTH];
int carQuantity;
if(start==NULL){
printf("\n\nLinked list is empty.\n");
}else{
ptr=start;
printf("\nThe car for which the entry is removed is %s \n",ptr->data.carname);
strcpy(start->data.carname,carname);
strcpy(start->data.carmodel,carmodel);
strcpy(start->data.caryear,caryear);
strcpy(start->data.cartype,cartype);
start->data.quantity=carQuantity;
start=start->next;
free(ptr);
}
}
void display()
{
struct node *ptr=start;
int i=1;
if(ptr == NULL){
printf("\nLinklist is empty.\n");
}else{
printf("\nSr. No Make Model Year Type Quantity\n");
while(ptr != NULL){
printf("\n%d.\t%s %s %s %s %d\n", i,ptr->data.carname,ptr->data.carmodel,ptr->data.caryear,ptr->data.cartype,ptr->data.quantity);
ptr = ptr->next;
i++;
}
}
}
int main(void)
{
int ch;
do
{
printf("\n\n\n1. Insert \n2. Delete \n3. Display \n4. Exit\n");
printf("\nEnter your choice: ");
scanf("%d", &ch);
switch(ch)
{
case 1:
insert_first();
break;
case 2:
delete_first();
break;
case 3:
display();
break;
case 4:
exit(0);
default:
printf("\n\nInvalid choice. Please try again. \n");
}
} while(1);
return EXIT_SUCCESS;
}
You can't mix definitions of a struct with initialisation.
typedef struct criteriaselector{
const char *companyList[10];
companyList[0] = "Toyota"; // This bit needs to be elsewhere.
Instead, after you declare an instance of the struct, you'll then need to fill in the values. For example:
typedef struct criteriaselector{
const char *companyList[10];
}
.....
void some_function() {
CriteriaSelector criteriaselector;
criteriaselector.companyList[0] = "Toyota"
.... etc
However, it looks like you were intending to make a constant, rather than describe a structure. Instead of the whole struct definition, you can do:
const char *criteriaselector[10] = {"Toyota", "Honda" ... }
somewhere in global scope. This will declare a "global" array of constant strings.
As an aside, there's a little subtlety with the way that const works here. This declaration says "define an array of pointers to constant chars". This means that you can't change the strings themselves, but you can change the pointers. So, you can't do:
criteriaselector[1][0] = '\0' // changing a character inside a const string
But, you can do:
criteriaselector[1] = "some other string".
This probably isn't what you meant. Instead, we can say "define an array of constant pointers to constant strings", like this:
const char * const criteriaselector[10] = {"Toyota", "Honda" ... }
That way, you won't be able to change the contents of the string, or which strings are pointed to.
The comments on that question that I linked explain this in a bit more detail.
You cannot initialize variables inside a structure. This is because a struct defines a type and not a variable. You can initialize a structure members outside the structure definition using a structure variable (criteriaselector in your case) and .or -> access specifiers.
For eg.,
criteriaselector.companyList[0] = "Ford";
Where: ssize is the input size of the array, student is a globally declared struct, and read_stud is the function i use to read in arrays.
when printed out, s[count].first gives me the correct first name, but s[0] and all values after that are ALSO the same first name instead of the previously inputted value. It's changing the struct values to my most recent input!
struct student //this struct is global
{
int number;
char *first ;
char *last ;
};
struct student read_stud (int number, char *first , char *last) //my read_stud function
{
struct student s;
s.number = number;
s.first = first;
s.last = last;
return s;
}
This is in int main, where I use the function s = calloc(ssize, sizeof (struct student));
for (count = 0; count < ssize ; ++count)
{
printf ("Enter student number, name and last name: \n");
scanf ("%d %s %s", &number, &first, &last);
s[count] = read_stud (number, first, last);
}
A most heartfelt thanks to whoever can fix this for me!
You need to provide storage for the first and last names in your student struct.
If you know what their max lengths are, use char arrays in the struct.
#define MAX_NAME_CHARS (20)
struct student //this struct is global
{
int number;
char first[MAX_NAME_CHARS];
char last[MAX_NAME_CHARS];
};
Otherwise, malloc the strings and remember to free them later.
struct student read_stud (int number, char *first , char *last) //my read_stud function
{
struct student s;
s.number = number;
s.first = strdup(first);
s.last = strdup(last);
return s;
}
Existing code:
for (count = 0; count < ssize ; ++count)
{
printf ("Enter student number, name and last name: \n");
scanf ("%d %s %s", &number, &first, &last);/*1*/
s[count] = read_stud (number, first, last);
}
struct student read_stud (int number, char *first , char *last) //my read_stud function
{
struct student s;
s.number = number;
s.first = first;/*2*/
s.last = last; /*3*/
return s;
}
Because you assign the same value (first & last) and then overwriting with scanf. Try to malloc memory for first and last in your struct:
struct student read_stud(int number, char *first , char *last) //my read_stud function
{
struct student s;
s.number = number;
s.first = malloc(strlen(first) + 1);
strcpy(first, s.first);
s.last = malloc(strlen(last) + 1); /*3*/
strcpy(last, s.last);
return s;
}
And don't forget to free all the allocated memory. (Error checking omitted for brevity.)
struct student *read_stud(int number, char *first , char *last) // my read_stud function
{
struct student *s;
s = malloc(sizeof(struct student));
s->number = number;
s->first = strdup(first);
s->last = strdup(last);
return s;
}
In the main:
char first[256], last[256]; /* 256 as example*/
struct student *s = calloc(ssize, sizeof (struct student *));