This code:
#include<stdio.h>
struct my_structure {
char name[20];
int number;
int rank;
};
int main()
{
int n,i;
scanf("%d",&n);
struct my_structure variable[n];
struct my_structure *ptr;
ptr = &variable;
for(i=0; i<n; i++)
{
scanf("%s",ptr->name);
scanf("%d",&ptr->number);
scanf("%d",&ptr->rank);
}
for(i=0; i<n; i++)
{
printf("NAME: %s\n", ptr->name);
printf("NUMBER: %d\n", ptr->number);
printf("RANK: %d", ptr->rank);
}
return 0;
}
It is not printing correctly. I want to print the 1st input first and then the second. But I'm getting the output like printing only the second input two times.
Two changes you need to do:-
ptr = variable ;
Then you can increase ptr in loop.(The use of scanf is not robust - how to do it better is shown in the end of the answer).
for(i=0;i<n;i++)
{
scanf("%s",ptr->name);
scanf("%d",&ptr->number);
...
ptr++;
}
After that again do the assignment ptr = variable;.
You can also do this (Illustration on the users code)
..
scanf("%s",ptr[i].name);
scanf("%d",&ptr[i].number);
...
printf("%s",ptr[i].name);
printf("%d",ptr[i].number);
Earlier you have type mismatch in assignment. You were assigning a struct my_structure (*)[n] to struct my_structure*. Check the return value of scanf and also check the value n (n>1).
You can do it on your way also:(Illustration on the users code)
struct my_structure (*ptr)[n] = &variable;
for(i=0;i<n;i++)
{
scanf("%s",(*ptr)[i].name);
scanf("%d",&((*ptr)[i].number));
scanf("%d",&((*ptr)[i].rank));
}
...
printf("%s",(*ptr)[i].name);
printf("%d",((*ptr)[i].number));
Correct way to use scanf would be:-(Notice that here 19 is used - otherwise there is a chance of buffer overrun - and this is being checked using this.This is one less than the size of the array because of the \0 character ) (Correct way)
if(scanf("%19s",ptr[i].name) != 1){
/* error in input */
fprintf(stderr,"Error in input\n");
exit(EXIT_FAILURE);
}
Compile your program with all warnings enabled. gcc -Wall -Werror progname.c.
Clearly you don't even need to use this pointer - why would you do that? You can simply use the array itself in the scanf or printf.
Related
There are some problems thatconfuse me:
The callee function needs return a structure, but there is not a structure statment in caller function.
If i have to write the declaration in the calling function,it can not be called packaging function.
If i return a structure pointer by callee function, but the structure is in the stack of the called function and will be destroyed after the end, which is not safe. Sometimes i get some warning or even wrong!
I have a limited ideas but it not good. I put the structure into the heap by malloc and return the void*pointer. But this gave birth to a new problem :after each call to this function, in the caller, I cannot release the heap through the free() function,the complier can not identify variable name of structure pointer. I think it verey dangerous. I want when the callee function quit,it can be released by itself.
This is the first time I came to this website to ask questions and I just came into contact with c language,If there is something stupid please point it out.
I have to write the structure declaration outside. This program for judging prime number, and I want to package the founction "judging_number". I do not want to write the structure declaration when I want to call the founction "judging_number".
Please give me some help, I would be very grateful.
Sorry, this is my fault. I compiled it with clang++, I saved it as *.cpp, but I wrote c code in it.
What I mean is, can I put the declaration in the called function to realize the function modularization, how can I not declare a structure before calling the function? Is there any way I can not write a declaration. Like use founction in stdio.h.It is as convenient as using the functions of the standard library. Only need to write a line of function call and pass parameters, the called function can return multiple results.
#include <stdio.h>
struct boundary{
int L;
int R;
};boundary *range;
int *get_number()
{
int *nPtr = (int *)malloc(sizeof(int));
do
{
printf("Please enter a vaild number for judging prime number.Or enter the number 1 to quit.\r\n");
scanf("%d", nPtr);
if (*nPtr == 1)
{
exit(1);
}
} while (*nPtr < 1);
printf("The object is %d\r\n", *nPtr);
return nPtr;
}
int judg_number(int N,boundary range){
if (N%range.L==0&&N!=2){
printf("The number %d is a composite number.\r\n", N);
}
else{
printf("The number %d is a prime number.\r\n", N);
}
return 0;
}
boundary* get_range(int N){
boundary *Ptr = (boundary *)malloc(sizeof(boundary));
*Ptr = {2,N-1};
printf("The range is between %d and %d .\r\n", Ptr->L, Ptr->R);
return Ptr;
}
int main(int argc,char**argv,char**env){
int*N;
while(1){
N=get_number();
range=get_range(*N);
judg_number(*N, *range);
free(N);
free(range);
}
getchar();
getchar();
return 0;
}
You dont need dynamic memory allocation here. If you want to retun an int, retun an int. If you want to retun a stuct return a struct.
You probably want this:
#include <stdio.h>
#include <stdlib.h>
struct boundary {
int L;
int R;
};
struct boundary range;
int get_number()
{
int n;
do
{
printf("Please enter a vaild number for judging prime number.Or enter the number 1 to quit.\r\n");
scanf("%d", &n);
if (n == 1)
{
exit(1);
}
} while (n < 1);
printf("The object is %d\r\n", n);
return n;
}
int judg_number(int N, struct boundary range) {
if (N % range.L == 0 && N != 2) {
printf("The number %d is a composite number.\r\n", N);
}
else {
printf("The number %d is a prime number.\r\n", N);
}
return 0;
}
struct boundary get_range(int N) {
struct boundary b = { 2, N - 1 };
printf("The range is between %d and %d .\r\n", b.L, b.R);
return b;
}
int main(int argc, char** argv, char** env) {
int N;
while (1) {
N = get_number();
range = get_range(N);
judg_number(N, range);
}
getchar();
getchar();
return 0;
}
BTW:
boundary get_range(int N) {... is invalid in C but valid in C++. In C it should be struct boundary get_range(int N) {...
I wrote a program in C which has a structure named ak.
There is an array of pointers s which stores the address of array p of ak type. After inputting the values, only str is getting printed.
How can I print both str and id using array of pointers?
set 1:
#include<stdio.h>
typedef struct
{
char str[10];
int id;
}ak;
int main()
{
printf("Hey\n");
int i;
ak *s[5],p[5];
for(i=0;i<5;i++)
{
s[i]=&p[i];
printf("Input string:");
scanf("%s",&p[i].str);
printf("Input id:");
scanf("%d",&p[i].id);
}
i=0;
while(i<5)
{
printf("%s\n",s[i].id);
++i;
}
return 0;
}
set 2:
#include<stdio.h>
typedef struct
{
char str[10];
int id;
}ak;
int main()
{
printf("Hey\n");
int i;
ak *s[5],p[5];
for(i=0;i<5;i++)
{
s[i]=&p[i];
printf("Input string:");
scanf("%s",&p[i].str);
printf("Input id:");
scanf("%d",&p[i].id);
}
i=0;
while(i<5)
{
printf("%s\n",s[i]);
++i;
}
return 0;
}
So when I tried set1 code,it gave me error saying:
C:\CPP\c\Prototypes>gcc -o ct structure.c
structure.c: In function 'main':
structure.c:22:32: error: request for member 'id' in something not a structure or union
printf("%s\n",*s[i].id);
^
Screenshot is here:
https://imageshack.com/a/img921/3084/j1rHig.png
When I tried set2 code, it only printed str values.
screenshot is here:
https://imageshack.com/a/img922/614/JHSGZ9.png
Concerning set1 and your problems with printf("%s\n",*s[i].id);.
*s[i].id is equivalent to *(s[i].id), not to (*s[i]).id as you probably supposed. Because the type of s[i] is ak * you cannot get its field id through s[i].id.
You can write (*s[i]).id but a more readable way is to use s[i]->id.
Your printf has an other problem, the format cannot be "%s" because s[i]->id is an int, not a char *
Concerning set2
You do printf("%s\n",s[i]);, and you are surprised because only the string is printed, how can you expect that print the string and the int ?
You request to print a string (format %s) but s[i] is not a string. By chance the struct starts by the field str being a string, so yes you write it, but this is not the right way.
You have to explicitly print each attributes, for instance doing printf("%s %d\n",s[i]->str, s[i]->id);
When I call the test() function, it prompts me to enter the bet for the first player in my struct array. It accepts my entry. On the second round in my for loop, when asking for the bet for the second person in my struct array, an exception is thrown after a value is entered:
Exception thrown at 0x00577F81 (ucrtbased.dll) in lottery.exe:
0xC0000005: Access violation writing location 0x7B7CC9FC.
If there is a handler for this exception, the program may be safely continued.
Here is my code:
void initNames(struct player *p, int size) {
int i;
for (i = 0; i < size; i++) {
printf("Enter player %d's name...\n", (i + 1));
scanf("%s", p[i].name);
}
return;
}
void initScore(struct player *p, int size) {
int i;
for (i = 0; i < size; i++) {
p[i].wins = 0;
p[i].losses = 0;
p[i].funds = 100.00;
}
return;
}
void test(struct player *p, int size) {
int i;
for (i = 0; i < size; i++) {
printf("%s, you have $%.2lf. Place your bet!\n", p[i].name, p[i].funds);
scanf("%lf", p[i].bet);
}
}
void main() {
int size;
struct player *playerPtr;
printf("How many players?");
scanf("%d", &size);
playerPtr = malloc(sizeof(struct player)*size);
initScore(&playerPtr, size);
initNames(&playerPtr, size);
test(&playerPtr, size);
free(playerPtr);
}
Thanks for any help or explanations!
There is a discrepancy between how you have declared the function initNames and how you are calling it in main.
It is declared as -
void initNames(struct player *p, int size);
Which means it expects a pointer to struct player as the first argument and an int as the second.
In main you are calling it as -
struct player *playerPtr;
initNames(&playerPtr, size);
Now the type of playerPtr is struct player* and thus the type of &playerPtr will be struct player**. Thus there is a type mismatch for the arguments. Your compiler should have warned you about this. Always compile with -Wall to see all the warnings and -Werror to treat warnings as errors.
Coming to the fix -
You are not going to modify playerPtr inside any of the functions. So you need not pass struct player**. So change the call to function as -
initNames(playerPtr, size);
Nothing needs to be changed inside the function because the prototype for the function hasn't been changed.
The exact same issues are with the functions initScore and test too. You can fix them in a similar way by changing the first argument to their call.
Now after fixing this too, the program won't be correct.
Look at the line -
scanf("%lf", p[i].bet);
I am assuming bet is declared with type double. You are now passing the double to scanf where a double* is expected. You need to pass the address of bet. So change the line to -
scanf("%lf", &p[i].bet);
I have fixed all the errors and the working version is at
Ideone.
I have assumed a definition for struct player.
To be more sure about the values being read you should always check the return value of scanf as -
int ret = scanf("%lf", p[i].bet);
if(ret == 0) {
// Print appropriate error message that the value entered in not a double and ask the user to retry
} else if (ret == EOF) {
// The input stream has been closed by the user without providing appropriate input, print appropriate error message and abort.
}
// If execution reaches this point, p[i].bet is safe to use.
I am getting garbage value when I display the records.
I have to create a database of students in C using array of structures and without pointers.
Is there any other way of doing this?
How to use array of structures?
#include <stdio.h>
struct student {
char first_name[10],last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student);
void display(struct student);
void main() {
struct student S[10];
int n, i;
printf("Enter the number of records to enter : ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
accept(S[i]);
}
for (i = 0; i < n; i++) {
display(S[i]);
}
}
void accept(struct student S) {
scanf("%s", S.first_name);
scanf("%s", S.last_name);
scanf("%d", &S.roll);
scanf("%s", S.address);
scanf("%f", &S.marks);
}
void display(struct student S) {
printf("\n%s", S.first_name);
printf("\n%s", S.last_name);
printf("\n%d", S.roll);
printf("\n%s", S.address);
}
Everything in C is pass-by-value. Which means you are modifying variable copy in stack frame, while real variable passed as parameter remains untouched.
You have to pass an pointer to variable which you want to modify in function.
// Function declaration
void accept(struct student *);
// Call
accept(&S[i]);
// Usage in function via dereference operator
scanf("%s",S->first_name);
If you would like to enter unknown amount of records, you should use VLA (since c99) or dynamically allocate structures.
VLA
scanf("%d",&n);
struct student S[n];
Dynamic callocation
scanf("%d",&n);
struct student * S = malloc(sizeof(struct student) * n);
Because in your case, if user input more that 9 records you are touching outside of bounds, which has undefined behavior.
There are multiple issues in your code:
The standard prototype for main without arguments is int main(void)
You should allocate the array dynamically with calloc.
you should pass structure pointers to the accept and display functions instead of passing structures by value. Passing the destination structure by value is incorrect as the accept function cannot modify the structure in the main function, which remains uninitialized and causes garbage to be displayed. Note that it is actually undefined behavior to access uninitialized data so the program could behave in even worse ways.
You should provide scanf() with the maximum number of arguments to store into character arrays to avoid potential buffer overflows.
you should verify the return values of scanf() to avoid undefined behavior on invalid input.
you could use the %[^\n] scan set to allow embedded spaces in the address field.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct student {
char first_name[10], last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student *sp);
void display(const struct student *sp);
int main(void) {
struct student *S;
int n, i, j;
printf("Enter the number of records to enter : ");
if (scanf("%d", &n) != 1)
return 1;
S = calloc(sizeof(*S), n);
if (S == NULL) {
return 1;
}
for (i = 0; i < n; i++) {
accept(&S[i]);
}
for (i = 0; i < n; i++) {
display(&S[i]);
}
free(S);
return 0;
}
void accept(struct student *sp) {
if (scanf("%9s%9s&d %19[^\n]%f",
sp->first_name, sp->last_name, &sp->roll,
sp->address, &sp->marks) != 5) {
printf("missing input\n");
exit(1);
}
}
void display(const struct student *sp) {
printf("%s\n", sp->first_name);
printf("%s\n", sp->last_name);
printf("%d\n", sp->roll);
printf("%s\n", sp->address);
printf("%f\n", sp->marks);
printf("\n");
}
I am trying to learn about structs, pointers, and dynamic arrays in C. I don't understand how to create a dynamic array of structs using pointers. My code doesn't work, and I don't know what's wrong with it. I have seen several examples of dynamic arrays, but non with structs. Any help would be appreciated. Please give some explanation, not just code snippets as I do want to understand not just solve this problem.
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
struct *struct_array;
int i,m,n,p;
struct data
{
char inputA[20];
char inputB[20];
};
struct data get_data()
{
struct data thisdata;
printf("Please enter input A\n");
scanf("%s", thisdata.inputA);
printf("Please enter input B\n");
scanf("%s", thisdata.inputB);
return thisdata;
}
void Output(struct data struct_array, int n)
{
int index = 0;
for(i = 0; i<n ;i++)
{
printf("%s ", struct_array[i].inputA);
printf("%s ", struct_array[i].inputB);
}
}
void resizeArray(int n)
{
struct_array = (int*)realloc(n*sizeof(int));
}
void mainMenu()
{
printf("Please select from the following options:\n");
printf("1: Add new students to database\n");
printf("2: Display current student database contents\n");
printf("3: exit the program\n");
scanf("%d", &p);
if(p == 1)
{
printf("Please enter the number of students to register:\n");
scanf("%d", &n);
resizeArray(n);
for(i = n; i<n ;i++)
{
struct_array[i] = get_data();
}
}
else if(p == 2)
{
Output(struct_array, n);
}
else
{
free(struct_array);
exit(0);
}
}
int main()
{
struct_array = (int*)realloc(2*sizeof(int));
mainMenu();
}
You have several errors in your source code:
struct *struct_array; (l. 5)
What does it mean? Did you want to write struct data *struct_array?
printf("%s ", struct_array[i].inputA); (l.32 & l. 33)
The argument struct_array masks the global declaration, and it is not an array. Why did you add this argument?
struct_array = (int *)realloc(n * sizeof(int)); (l. 39)
You have forgotten an argument. Did you want to use malloc instead? Besides, the cast is not necessary (and incorrect!).
Unless you are using an hosted environnment and C99/C11, you should return a value from main.
Your variable index is not used. Why did you declare it?
for(i = n; i < n; i++) (l. 53)
You won't have any iteration here...
The following code works as expected.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* TODO: Avoid global variables. */
struct data *struct_array;
struct data {
char inputA[20];
char inputB[20];
};
/*
* TODO: Try to avoid passing your structure (40 bytes + padding)
* without pointer.
*/
struct data get_data(void)
{
struct data thisdata;
printf("Please enter input A\n");
/* TODO: Avoid using `scanf` for human inputs. */
scanf("%s", thisdata.inputA);
printf("Please enter input B\n");
scanf("%s", thisdata.inputB);
return thisdata;
}
void Output(size_t n)
{
size_t i;
for (i = 0; i < n; i++) {
printf("%s ", struct_array[i].inputA);
printf("%s ", struct_array[i].inputB);
}
}
void resizeArray(size_t n)
{
/* TODO: Handle reallocations errors. */
struct_array = realloc(struct_array, n * sizeof *struct_array);
}
void mainMenu(void)
{
size_t i, n;
int p;
/* TODO: Use a loop ? */
printf("Please select from the following options:\n");
printf("1: Add new students to database\n");
printf("2: Display current student database contents\n");
printf("3: exit the program\n");
scanf("%d", &p);
switch (p) {
case 1:
printf("Please enter the number of students to register:\n");
scanf("%u", &n);
resizeArray(n);
for (i = 0; i < n; i++)
struct_array[i] = get_data();
break;
case 2:
Output(n);
break;
}
}
int main(void)
{
struct_array = malloc(2 * sizeof(int));
mainMenu();
free(struct_array);
return 0;
}
Your definition
struct *struct_array;
is erroneous. You must use the name of your type, the data.
struct data *struct_array;
This way you can allocate the array
struct_array = malloc(MaxNumElements * sizeof(struct data));
and later you should free the memory
free(struct_array);
EDIT: Type definition must occur before the var declaration.
struct data ....
struct data* your_variable;
P.S. If you do not want to type struct keyword each time you use the data type, use the typedef:
typedef struct data_s
{
char inputA[20];
char inputB[20];
} data;
Do you know how to use typedef?
I would suggest it, makes your code easier to understand and you won't have to be typing the word struct a thousand times. Also you could treat the new type similar to the primitive types (ints, chars, etc), just don't forget to use the dot (.) to access the individual fields you might want.
You could type for instance:
typedef struct{
char inputA[20];
char inputB[20];
} data;
Now you could declare variables like this:
data data_variable;
data *pointer_to_data;
And to you could allocate memory as follows:
pointer_to_data = (data*) malloc(sizeof(data)* N);
where N is the amount of struct data you want to allocate. Same works for realloc.
struct_array = (int*)realloc(2*sizeof(int));
By the above statement you are trying to assign address of an int to a pointer of type struct data.
You need to use:
struct_array = (struct data*)realloc(2*sizeof(struct data));