#include <stdio.h>
#include <string.h>
typedef struct birth{
char *name;
char time[12];
}birth;
void swap(struct birth *a, struct birth *b){
struct birth tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int main(){
int n;
birth list[100], *p, *q;
scanf("%d", &n);
getchar();
for(p = list; p < list + n; p++){
scanf("%s %s", &p->name, &p->time);
}
for(p = list; p < list + n - 1; p++){
for(q = p + 1; q < list + n; q++){
if(strcmp(p->time, q->time) > 0){
swap(p ,q);
}
else if(strcmp(p->time, q->time) == 0){
if(strcmp(p->name, q->name) > 0){
swap(p ,q);
}
}
}
}
for(int i = 0; i < n; i++){
printf("%s %s\n", list[i].name, list[i].time);
}
return 0;
}
I am solving the problem of receiving n, which means the number of students, repeating the number of students, receiving the student's name and date of birth, and printing the names in advance if the date of birth is the same.
However, there was no answer, so I checked using the debugger in vcode, and when I received the input, the date of birth was well entered, but the name was not.
You are trying to read a string using a char pointer that was never initialized.
typedef struct birth{
char *name;
char time[12];
}birth;
...
scanf("%s %s", &p->name, &p->time); // error, &p->name points to nowhere
You should either allocate memory yourself or declare it as a fixed size char array. It would be best to check the string boundaries too:
#define S_NAME 12
#define S_TIME 12
typedef struct birth{
char name[S_NAME];
char time[S_TIME];
}birth;
...
// read string with safety guard
if (fgets(p->name, S_NAME, stdin) != NULL) {
// read name successfully
}
if (fgets(p->time, S_TIME, stdin) != NULL) {
// read time successfully
}
Related
I am writing a search function in C which uses pointers and structs. Search is possible by name using an array called contatcs with ten entries. The array has already been initialized and populated and works as intended.
I have tried to fix the problem by restructuring my code, but it only made matters worse. Maybe there is some flaw in the design logic that I cannot find.
typedef struct
{
char streetname[150];
char city[50];
int zipcode;
}address;
typedef struct
{
char name[50];
int age;
address homeaddress;
}person;
int search (char* name, person *contacts, int size);
[...] // initialization and population of array omitted
int search (char *name, person *contacts, int size)
{
int i;
printf("Input name: ");
char userin = scanf("%s", name);
for(i = 0; i < size; i++)
{
if (strcmp(contacts[i].name, &userin) == 0)
{
printf("Name: %s;", contacts[i].name);
printf(" Age: %d;", contacts[i].age);
printf(" Adress: %s, ", contacts[i].homeaddress.streetname);
printf("%s, ", contacts[i].homeaddress.city);
printf("%d\n", contacts[i].homeaddress.zipcode);
}
}
return 0;
}
I am just trying to call the function. But every time I try to do so, it just doesn't work. I know this question is rather basic, but I can't seem to find the solution.
char userin = scanf("%s", name);
for(i = 0; i < size; i++)
{
if (strcmp(contacts[i].name, &userin) == 0)
You can not use strcmp with a char, userin must be a NUL terminated array of chars
And as pointed out by #JohnBollinger in comments, it seems you want to compare the name, not the result of scanf
How to allocate memory for my char * fields in struct ?
My struct:
struct student{
int score;
char* name;
char* surname;
};
int main(){
struct student st[];
int i;
int n = 5;
for(i = 0; i < n; i++){
printf("Score: \n");
scanf("%d", &st[i].score);
printf("Name \n");
scanf("%s", &st[i].name);
printf("Surname \n");
scanf("%s",&st[i].surname)
}
}
How to malloc to char* name and char* surname ?
I must have an array of struct in form struct student st[].
I don't know, how do this rationally.
void initialise_student( struct student *st, char* name, char* surname)
{
st->name = ( strlen( name ) + 1);
st->surname = (strlen( surname ) +1 );
}
int main(){
int i;
int n = 5;
struct student *st[n] = initialise_student();
for(i = 0; i < n; i++){
printf("Score: \n");
scanf("%d", &st[i].score);
printf("Name \n");
scanf("%s", &st[i].name);
printf("Surname \n");
scanf("%s",&st[i].surname);
}
How to match this ?
For example
#include <stdlib.h>
#include <string.h>
//...
struct student st[1];
char *name = "Marek";
char *surname = "Piszczaniuk";
st[0].name = malloc( strlen( name ) + 1 );
strcpy( st[0].name, name );
st[0].surname = malloc( strlen( surname ) + 1 );
strcpy( st[0].surname, surname );
st[0].score = 100;
You can write separate functions to set the data members name and surname for an element of the array.
For example
_Bool set_name( struct student *st, const char *name )
{
st->name = malloc( strlen( name ) + 1 );
_Bool success = st->name != NULL;
if ( success )
{
strcpy( st->name, name );
}
return success;
}
You need to write an initialise_student(struct student* s) function which calls malloc on the char* members. Perhaps this function also takes the name and surname char* pointers of which you take deep copies?
You then call this function with every member of the st array.
Don't forget to build a corresponding free_student(struct student* s) function.
If you are already using scanf, you can tell the function to allocate the sting for you by using %ms instead of %s, like this:
char *name;
if (scanf("%ms", &name) != 1) {
fprintf(stderr, "error: could not read name\n");
exit(1);
}
EDIT This may not be a valid solution—I forgot that %ms is in POSIX only, not in ISO C.
function find_young() have to receive pointer p as an actual parameter.
And p have to point a struct s which has youngest person.
There is no error message but the program isn't work.
Please give me some advice.
typedef struct
{
char *name;
int age;
} PERSON;
void find_young(PERSON **ip)
{
PERSON s[3] = {{"John", 25}, {"Brandon", 28}, {"Alex", 30}};
int i;
int min = s[0].age;
for(i = 0; i < 3; i++)
{
if(min > s[i].age)
**ip = s[i];
}
}
int main()
{
PERSON *p;
find_young(&p);
printf("The youngest person is %s.\n", p->name);
}
You need to make a number of changes in your code to make it work
1) You need to allocate memory to the struct, and for the char* name in the struct
int main()
{
PERSON *p = malloc(sizeof(PERSON));
p->name = malloc(100);
find_young(&p);
printf("The youngest person is %s with age %d.\n", p->name, p->age);
free(p->name);
free(p);
}
2) Then you need to copy both the name and age values to the passed struct properly
void find_young(PERSON **ip)
{
PERSON s[3] = {{"John", 25}, {"Brandon", 28}, {"Alex", 30}};
int i;
int min = s[0].age; //copying the first value
(**ip).age = s[0].age;
strcpy((**ip).name, s[0].name);
for(i = 1; i < 3; i++) //starting from the next values to compare
{
if(min > s[i].age)
{
(**ip).age = s[i].age;
strcpy((**ip).name, s[i].name);
}
}
}
In your code,
either, for p, before passing &p to the function
or, for *ip, inside the function
you need to allocate memory. Other wise, you'll end up dereferencing invalid pointer, which invokes undefined behavior.
I'm new to C, so this may be a silly question to ask:
What I want to do here is to input the data to the array of pointers to a structure and then print it out. But I get a segmentation fault when running into the insert function.
Below is my code
common.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct book * Book;
struct book{
int id;
char *name;
};
extern int b_insert(Book *b, int id, char *name);
extern int b_print(Book books[], int len);
insert.c
#include "common.h"
int b_insert(Book *b, int id, char *name){
Book p;
p = (Book)malloc(sizeof(struct book));
p->id = id;
strcpy(p->name, name);
*b = p;
printf("success insert book:\n");
printf("\tID: %d Name: %s\n", (*b)->id, (*b)->name);
return 0;
}
int b_print(Book books[], int len){
int i;
printf("Book List\n");
for(i=0; i<len; i++){
printf("books[%d] = ID: %d, Name: %s\n", i, books[i]->id, books[i]->name);
}
return 0;
}
main.c
#include "common.h"
#define MAX 2
int main(){
Book books[MAX];
Book *b=books;
int i;
int id;
char name[10];
for(i=0; i<MAX; i++){
printf("please input new books info\n");
printf("ID: ");
scanf("%d", &id);
printf("Name: ");
scanf("%s", name);
if(b_insert(b, id, name) == -1){
printf("fail to insert\n");
}
b++;
}
b_print(books, MAX);
return 0;
}
Main problem:
Allocate memory for p->name before using
strcpy(p->name, name);
using malloc:
p->name = malloc(10); //Or some other size
Other problems:
Remove the cast here:
p = (Book)malloc(sizeof(struct book));
Why? Here is the answer
if(b_insert(b, id, name) == -1){ will never be true.
Check the result of malloc to check if it was successful in allocating memory.
Check the return value of all the scanfs to see if it was successful in scanning data.
Add a length modifier to the second scanf to prevent buffer overflows:
scanf("%9s", name); /* +1 for the NUL-terminator */
You're not allocating space for name:
int b_insert(Book *b, int id, char *name){
Book p;
p = malloc(sizeof(struct book));
if (p != NULL)
{
p->name = malloc(strlen(name)+1); // It allocates space where the input name will be copied.
if (p->name != NULL)
{
p->id = id;
strcpy(p->name, name);
*b = p;
printf("success insert book:\n");
printf("\tID: %d Name: %s\n", (*b)->id, (*b)->name);
}
else return -1; // No space to allocate string
}
else return -1; // No space to allocate struct
return 0;
}
As mentioned before, allocate space for p->name. You should probably also use something different to read the book title, either scanf format %ms with a pointer to a char pointer, or %9s with your buffer, otherwise the title "war or peace" will also result in a segfault.
Here you create a static variable and the space for it is allocated automatically.
Book p;
You can allocate a space manually when you assign it to pointer, in this line it's not pointer but static variable.
p = (Book)malloc(sizeof(struct book));
What's more if you want to refer to attribute of static variable you should use "." instead of "->". So you have two option. Create a pointer and allocate a space for the structure and then you "->" oraz create static variable.
p->id = id;
I have a data as shown below, it contains the name of person and age respectively, her i have shown just 3 person names and the respective age, i can also have many names with respective age in that string.
I want to parse this string and store the name and corresponding age in a structure, can u please tell me how to parse this name and age. Ex: I want to get Allan 35 and store it in the below structure in name and age field respectively.So and forth for all the names present in that string.
How to parse the string, i tried strstr() but it was of no use for me. Pls can anyone tell how to parse this string.
struct data_base{
char *name;
int age;
};
char data[] = "Name Allan Age 35 Name John Age 50 Name Jim Age 20 ....."
You can use strtok to extract the tokens.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct data_base{
char *name;
int age;
};
#define NAME_TAG "Name "
#define AGE_TAG "Age "
char* getName(char **p){
int tag_size = strlen(NAME_TAG);
if(strncmp(*p, NAME_TAG, tag_size)==0){
char *agep = strstr(*p += tag_size, AGE_TAG);
int len = agep - *p -1;//-1: for space before "Age"
char *name = calloc(len + 1, sizeof(char));
strncpy(name, *p, len);
*p = agep;
return name;
}
return NULL;
}
int getAge(char **p){
int tag_size = strlen(AGE_TAG);
if(strncmp(*p, AGE_TAG, tag_size)==0){
int age = (int)strtol(*p += tag_size, p, 10);
if(**p == ' ')
*p += 1;
return age;
}
return -1;
}
struct data_base *parse(char *data, size_t *size){
char *p = data;
struct data_base *dbp=NULL;
*size = 0;
while(*p){
*size += 1;
dbp = realloc(dbp, sizeof(struct data_base)*(*size));
dbp[*size -1].name = getName(&p);//this is treated as format is correct
dbp[*size -1].age = getAge(&p);
}
return dbp;//realloc(dbp, sizeof(struct data_base)*(*size));
}
int main(void){
char data[] = "Name Allan Age 35 Name John Age 50 Name Jim Age 20";
struct data_base *dbp;
size_t i, size;
dbp = parse(data, &size);
//check print
for(i = 0; i < size ;++i){
printf("Name: %s, Age: %d\n", dbp[i].name, dbp[i].age);
}
//deallocate
return 0;
}
You might want to use sscanf. You'll need %s format for person's name and %d for age.
u can use two pointer to get the begin and end of a word,
use pointer p by strstr to get the place of "Name", then forth 5 to get the begin place of the name , then pointer q by strchr with space to get the end of the name, then you can use strncpy of snprintf to get the exactly name
Create function to handle each record, using sscanf().
// Scan string, return >0 if successful, 0 if done, else error code
int JZ_ScanDB(const char *data, int *Index, struct data_base *Dest) {
if (Dest) {
Dest->age = 0; // Form default answer
Dest->name = 0;
}
if (!data || !Index || !Dest) return -1; // Gremlins in your code
if ((*Index < 0) || (*Index > strlen(data))) return -2; // More gremlins
if (data[*Index] == '\0') return 0; // we are done
char Name[1000];
int retval = sscanf(&data[*Index], "Name %s Age %d %n", Name, &Dest->age, Index);
if (retval != 2) {
return -3;
}
Dest->name = strdup(Name);
return 0;
}
void DoIt() {
char data[] = "Name Allan Age 35 Name John Age 50 Name Jim Age 20";
int i = 0;
struct data_base Person;
int ret;
while ((ret = JZ_ScanDB(data, &i, &Person)) > 0) {
// do something with Person, watch for memory management
}
if (ret) {
// deal with unusual reason for stopping
}
}