Unable to Print the Content of a Structure - c

I want to print the content of the book record as defined in the print_book() function. Here is the code. My intention is to use the function to print any struct of type Book.
#include <stdio.h>
#include <string.h>
void print_book(struct Book book);
struct Book
{
int id;
char *title;
char *author;
int pages;
};
int main(void)
{
struct Book book_1;
book_1.id = 23;
strcpy(book_1.title, "Java! A Complete Reference");
strcpy(book_1.author, "Ryna Dahl");
book_1.pages = 876;
print_book(book_1);
return 0;
}
void print_book(struct Book book)
{
printf("BOOK\n");
printf("Book ID: %i\n", book.id);
printf("Book Ttitle: %s\n", book.title);
printf("Book Author: %s\n", book.author);
printf("Number of Pages: %i\n", book.pages);
}
Here is the error I am receiving in the console
muyiwa#muyiwa-HP-Pro-3010-Microtower-PC:~/Documents/C$ clang -o struct_pointer struct_pointer.c
struct_pointer.c:4:24: warning: declaration of 'struct Book' will not be visible outside of this function [-Wvisibility]
void print_book(struct Book book);
^
struct_pointer.c:22:16: error: argument type 'struct Book' is incomplete
print_book(book_1);
^~~~~~
struct_pointer.c:4:24: note: forward declaration of 'struct Book'
void print_book(struct Book book);
^
struct_pointer.c:26:6: error: conflicting types for 'print_book'
void print_book(struct Book book)
^
struct_pointer.c:4:6: note: previous declaration is here
void print_book(struct Book book);
^
1 warning and 2 errors generated.
muyiwa#muyiwa-HP-Pro-3010-Microtower-PC:~/Documents/C$ clang -o struct_pointer struct_pointer.c
struct_pointer.c:4:24: warning: declaration of 'struct Book' will not be visible outside of this function [-Wvisibility]
void print_book(struct Book book);
^
struct_pointer.c:16:17: error: variable has incomplete type 'struct Book'
struct Book book_1;
^
struct_pointer.c:16:12: note: forward declaration of 'struct Book'
struct Book book_1;
^
struct_pointer.c:26:24: warning: declaration of 'struct Book' will not be visible outside of this function [-Wvisibility]
void print_book(struct Book book)
^
struct_pointer.c:26:6: error: conflicting types for 'print_book'
void print_book(struct Book book)
^
struct_pointer.c:4:6: note: previous declaration is here
void print_book(struct Book book);
^
struct_pointer.c:26:29: error: variable has incomplete type 'struct Book'
void print_book(struct Book book)
^
struct_pointer.c:26:24: note: forward declaration of 'struct Book'
void print_book(struct Book book)
^
2 warnings and 3 errors generated.
I have tried all possible means, and on checking other sources, my code looks correct.

Scopes of Declarations
When something is newly declared in a function parameter, its scope (the portion of source code in which it is visible) is limited to the function declaration. So, in void print_book(struct Book book);, struct Book declares a type that is known only inside that declaration. When the definition of struct Book appears later, it is a different struct Book.
If you put the definition of struct Book first, outside of any function, then its scope is the rest of the translation unit (the file being compiled along with any files it includes with #include). Then, when void print_book(struct Book book);appears later, thisstruct Book` will not define a new type; it will refer to the type that is already in scope.
Lesson: Never make struct Name inside a parameter declaration the first appearance of struct Name in the code.
Note that you do not need to fully define the structure first. Merely putting a struct Book; first would inform the compiler there is a type struct Book with file scope. You could put the definition later (but before the compiler needs to know about the members of the structure).
Allocation of Memory
In this code:
strcpy(book_1.title, "Java! A Complete Reference");
strcpy(book_1.author, "Ryna Dahl");
no memory has yet been allocated for book_1.title or book_1.author. These members are merely pointers that have not been given a value. To use strcpy correctly, you must allocate memory for the strings and set the pointers to point to that memory.
You can just set the pointers to point to the string literals directly:
book_1.title = "Java! A Complete Reference";
book_1.author = "Ryna Dahl";
That sets the members to point to strings that you should treat as constants. If you want to have modifiable memory, you could do this:
// Make temporary pointers to the string literals.
char *Title = "Java! A Complete Reference";
char *Author = "Ryna Dahl";
// Allocate memory for copies, including the terminating null characters.
book_1.title = malloc(strlen(Title) + 1);
book_1.author = malloc(strlen(Author) + 1);
if (!book_1.title || !book_1.author)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
// Copy the strings into the allocated memory.
strcpy(book_1.title, Title);
strcpy(book_1.author, Author);
Generally, if you allocate memory in this way, you should call free to release it when you are done using it. (In general-purpose multiuser operating systems, this can be omitted when the program is terminating, as the operating system will reclaim all memory.)

#include <stdio.h>
#include <string.h>
#define TITLE_SIZE (128)
#define AUTHOR_SIZE (128)
struct Book
{
int id;
int pages;
char title[TITLE_SIZE];
char author[AUTHOR_SIZE];
};
void print_book(struct Book book);
int main(void)
{
struct Book book_1;
book_1.id = 23;
strcpy(book_1.title, "Java! A Complete Reference");
strcpy(book_1.author, "Ryna Dahl");
book_1.pages = 876;
print_book(book_1);
return 0;
}
void print_book(struct Book book)
{
printf("BOOK\n");
printf("Book ID: %i\n", book.id);
printf("Book Ttitle: %s\n", book.title);
printf("Book Author: %s\n", book.author);
printf("Number of Pages: %i\n", book.pages);
}

Related

C- Passing entire structure variable

Here is a simple C programs in structure but i dont quite get what am i doing wrong as the output is not what i desired ,
P1
#include<stdio.h>
struct book
{
char name[10];
char author[10];
int refno;
};
//passing whole structure variable
void display(struct book b)
{
printf("%s %s %d",b.name,b.author,b.refno);
}
int main()
{
struct book b1={"LET US C","YPK",25};
display(b1);
}
Here this one works completely fine with output:
LET US C YPK 25
--------------------------------
Process exited after 0.3952 seconds with return value 0
Press any key to continue . . .
BUT if i try
struct{
// element -1;
//element -2;
//element-3;
}b1;
/*then*/
int main()
{
b1={"LET US C","YPK",25};
display(b1);
It shows error messages:-
1:[Warning] extended initializer lists only available with -std=c++11 or -std=gnu++11
2:[Error] no match for 'operator=' (operand types are 'book' and '<brace-enclosed initializer list>')
3:[Note] candidate is:
4:[Note] book& book::operator=(const book&)
5:[Note] no known conversion for argument 1 from '<brace-enclosed initializer list>' to 'const book&'
The same messsages are shown if i try :
struct book
{
//elements declarations as p1
}b[10];
int main()
{
b[1]={"LET US C","YPK",25};
display(b[1]);
}
OR WITH
struct book
{
//elements declarations as p1
};
int main()
{
struct book b[10];
b[1]={"LET US C","YPK",25};
display(b[1]);
}
So whats the problem?
and actually my main objective was to define array of structure, as in second last and last
method but it does not seem to work so please help>
In C, the syntax {elem1, elem2, elem3, ...} is only valid if you are initializing a structure (or an array) not assigning one. That's why it doesn't work in your example.
When you write b[1]={"LET US C","YPK",25}; you are trying to assign a value not initializing one.
For short:
Initializing is when you give a value to a variable that you are creating at the moment
Assigning is when you give a value to a variable already created.
For you example to work you can write this
struct book
{
char name[10];
char author[10];
int refno;
};
int main()
{
struct book b[10];
b[1]=(struct book){"LET US C","YPK",25};
^^^^^^^^^^^^
display(b[1]);
}
Now, you can declare structure variable anywhere, either right after structure declaration or anywhere in the main function but the point to be noted is when you are defining/assigning any of the variable i have used
(struct book) on the right hand side of assignment operator which helps compiler to understand that b[1] variable belongs to struct book data type, which corrects the error present in the program.
This feature of C language is known as compound literal.

Makefiles and structures in C

EDIT: To try and make things easier for the kind souls trying to help me, here are a couple links that should make things more clear:
Pre-makefile repl
Post-makefile repl
A little background on the assignment: We are supposed to take a program we wrote last week and break up the separate functions into their own files and use a makefile to compile and link and all that stuff. This is my original program (basically, it reads a file of name number and stores them in a struct, then uses the command line arguments to search for a name).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _data {
char* name;
long number;
};
int SCAN(FILE *(*input)) {
int lines = 0;
char word[50];
long num = 0;
while (1) {
fscanf(*input,"%s %ld",word, &num);
lines++;
if (feof(*input)) break;
}
return lines;
}
struct _data *LOAD(FILE *input, int size) {
char* line = NULL;
size_t len = 0;
int i=0;
rewind(input);
struct _data *book = calloc(size,sizeof(struct _data));
for (i = 0;i<size;i++) {
getline(&line, &len, input);
book[i].name = calloc(len+1,sizeof(char));
strcpy(book[i].name,strtok(line," "));
book[i].number = atoi(strtok(NULL, " "));
}
return book;
}
void SEARCH(struct _data *BlackBook, char *name, int size) {
int i;
for (i=0;i<size;i++) {
if (strcmp(name,BlackBook[i].name) == 0) {
printf("*******************************************\n");
printf("The name was found at the %d entry.\n",i+1);
printf("*******************************************\n");
break;
}
//If we reach the end of the array and name was not found
if (i == size-1) {
printf("*******************************************\n");
printf("The name was NOT found.\n");
printf("*******************************************\n");
}
}
}
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
//MAIN DRIVER ===================
int main(int argv, char** argc) {
int size;
char* filename = "hw5.data";
FILE *input = fopen(filename,"r");
size = SCAN(&input);
struct _data *phone_book = LOAD(input,size);
fclose(input);
//Check a name is given. If so, search
if (argv < 2) {
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
} else {
SEARCH(phone_book, argc[1], size);
}
FREE(phone_book,size);
return 0;
}
When I make my makefile, I can get the SCAN and LOAD functions to work appropriately. But, when I try to put either SEARCH or FREE into their own files, my compiler freaks out and I get warnings like:
In file included from hw6-free.c:1:0:
hw6-free.h:9:18: warning: ‘struct _data’ declared inside parameter list
void FREE(struct _data *BlackBook, int size);
^
hw6-free.h:9:18: warning: its scope is only this definition or declaration, which is probably not what you want
hw6-free.c:3:18: warning: ‘struct _data’ declared inside parameter list
void FREE(struct _data *BlackBook, int size) {
^
hw6-free.c:3:6: error: conflicting types for ‘FREE’
void FREE(struct _data *BlackBook, int size) {
^
In file included from hw6-free.c:1:0:
hw6-free.h:9:6: note: previous declaration of ‘FREE’ was here
void FREE(struct _data *BlackBook, int size);
^
hw6-free.c: In function ‘FREE’:
hw6-free.c:6:5: error: invalid use of undefined type ‘struct _data’
free(BlackBook[i].name);
^
hw6-free.c:6:19: error: dereferencing pointer to incomplete type ‘struct _data’
free(BlackBook[i].name);
^
Makefile:20: recipe for target 'hw6-free.o' failed
make: *** [hw6-free.o] Error 1
And reading through it, it looks like the fact my program takes a struct as an argument is my main problem? My 'post-makefile' program looks like:
#include "hw6-main.h"
int main(int argv, char** argc) {
int size;
char* filename = "hw5.data";
FILE *input = fopen(filename,"r");
size = SCAN(&input);
struct _data *phone_book = LOAD(input,size);
fclose(input);
//Check a name is given. If so, search
if (argv < 2) {
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
} else {
SEARCH(phone_book, argc[1], size);
}
FREE(phone_book,size);
return 0;
}
And my makefile looks like:
DEP = hw6-scan.o hw6-load.o hw6-search.o hw6-free.o hw6-main.o
HDR = hw6-scan.h hw6-load.h hw6-search.h hw6-free.h hw6-main.h
NAME = output
all: $(NAME)
output: $(DEP) $(HDR)
gcc $(DEP) $(HDR) -o $(NAME)
hw6-scan.o: hw6-scan.c
gcc -c hw6-scan.c
hw6-load.o: hw6-load.c
gcc -c hw6-load.c
hw6-search.o: hw6-search.c
gcc -c hw6-search.c
hw6-free.o: hw6-free.c
gcc -c hw6-free.c
hw6-main.o: hw6-main.c
gcc -c hw6-main.c
clean:
rm *.o *.gch *.out output testfile
As an example, my hw6-free.c and hw6-free.h look like:
#include "hw6-free.h"
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
and
#include <stdio.h>
#include <stdlib.h>
void FREE(struct _data *BlackBook, int size);
respectively.
And, finally, I defined the struct in the hw6-load.h file, along with a function prototype. Is that also a problem? Should I be defining it elsewhere?
I am SO SORRY for the long post, but I have been working on the for 10 hours and I'm about to throw my computer of a cliff.
THANK YOU FOR YOUR HELP STACK OVERFLOW!
This is an in-depth explanation of the details. It might be a bit too much, but if you keep reading, you may get a much deeper understanding of the language than if you just learn to write code that your compiler is ok with.
You are using your struct before you have declared it. Keep in mind that an #include is just a fancy way of telling your compiler: "Please, paste the contents of this .h file at this spot." The result of this pasting must read like valid code to the compiler.
It is true that the compiler's error message looks a bit weird. It certainly does not say "You used struct _data before you declared it". The reason for this is, that structs are implicitly declared at their first use. So, if you declare a variable with struct foo* bar; and the compiler has never seen a struct foo before, it will immediately consider struct foo as being declared, and a pointer variable to this struct foo of unknown size and shape will be defined. Likewise, when your compiler sees the function declaration
void foo(struct bar *baz);
it sees that it doesn't know a struct bar and implicitly declares one. Because this struct declaration happens inside a function declaration, the resulting type is declared local to the declaration at hand. As such, it is impossible for calling code to pass an argument of the correct type into this function, or even to implement the function in a separate statement. Such a function declaration is always useless. This is what the warning text "its scope is only this definition or declaration, which is probably not what you want" means: The compiler writers knew that such a declaration is bullshit, but it's legal C as far as the standard is concerned, so they compile it, but warn about it.
Ok, let's get to the actual error message. As the compiler tells you, the struct _data was only declared for the function declaration at hand. When your compiler later sees the function implementation, it stumbles across the undeclared struct _data a second time. Again, it implicitly declares a local struct type which is distinct from the previously implicitly declared type. Because those two implicitly declared types are distinct, so are the signatures of the declared functions. However, C mandates that a function can only have one signature, so the compiler produces the error "conflicting types for ‘FREE’".
You can try this out with this simple code:
void foo(struct bar* baz); //warning: local declaration of `struct bar`
void foo(struct bar* baz); //repeated warning + conflicting types error
So, how to fix this?
Simple. Declare your struct before you use it. That way you avoid its implicit declaration. The following code compiles fine:
struct bar; //global declaration of `struct bar`
void foo(struct bar* baz); //`struct bar` is known and the global declaration is used
void foo(struct bar* baz); //same as above, because this uses the same global declaration of `struct bar`, this redeclaration of `foo()` is ok
The declaration of the struct _data belongs into the header file that declares the functions which use struct _data as arguments.
Idiomatic declarations
Usually, types are declared with a typedef. This allows the code to omit the struct keyword when declaring variables. This takes one of two idiomatic forms:
To have a type with public members (pure data, no object in the OO sense), put the struct definition into the header:
typedef struct foo //`struct foo` is declared implicitly here
{ //it is also defined (= inner details are given) right here
int bar; //its member variables are defined
} baz; //this concludes the typedef, giving `struct foo` a second name
//`struct foo` and `baz` are now equivalent.
Usually, the two names will be the same or very similar, so the cleaned definition looks like this:
typedef struct foo {
int bar;
} foo;
//declarations of the functions that use `struct foo`
...
If the type is an object that should keep its data members to itself, the declaration and definitions are split like this:
Inside foo.h:
typedef struct foo foo; //declare that `struct foo` == `foo` exists, but don't give details
//declare the functions working on a `foo`
void foo_bim(foo* me);
void foo_bam(foo* me, ...);
...
Inside foo.c:
#include "foo.h" //so that the compiler may check that the function declarations in the header agree with the implementations in this file
struct foo { //define the size and shape of `struct foo` == `foo`
int bar;
};
//now only this file knows how a `struct foo` actually looks like
//implement the member functions of `foo`
void foo_bim(foo* me) {
...
}
void foo_bam(foo* me, ...) {
...
}
Note that the typedef ... non-struct-name; is purely optional in both cases, and there are quite a few programmers who want to see the struct keyword wherever a struct is used (like a certain Mr. Torvalds). These programmers simply leave off the typedef ... non-struct-name; part, otherwise they use the idioms above in the same way. I have described the full-featured version here, to ensure that you'll not be surprised when you first see the typedef construct.
I'm not sure what you did. But to step back: keep clear in your mind the difference between declarations and definitions. A declaration shows a variable or function signature, but does not create any variables of that type or implement that function. A definition declares a new variable (of some type) or implements a function. A declaration of a type just states that it exists (basically). A definition of a type shows its structure and members.
So, a definition of your type would be:
struct _data {
char* name;
long number;
};
And a declaration of a function would be:
void FREE(struct _data *BlackBook, int size);
and a definition of a function would be:
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
So here're the rules:
Only #include header files in other files, never #include source files.
If a type is needed in more than one file, put its definition into a header file and #include that header file in all source files that use the type.
If a function is used in more than one file, put the declaration of that function into a header file and #include that header file in all the source files that use the function, including the source file containing the definition of the function.
If you follow these rules you'll never run into duplicate definitions at link time: you can't have duplicate definitions if you link each source file only one time and no included file contains a definition.
Type declarations can be useful, and breaking some of these rules can be useful, but for the work you're doing that's probably not worth worrying about.
Try to put header of struct declaration at top of files which uses it and be sure you’ve imported the file which contains struct declaration.

Passing struct to a function to assign values

I am trying to pass a struct to a function residing in a separate file. When passing the struct as an argument, it throws errors.
Test.c
struct student{
int rollNumber;
unsigned char name[20];
int marks;
};
void func(struct student devanshu);
int main(){
struct student devanshu;
func(&devanshu);
printf("--------------------%d\n", devanshu.rollNumber);
printf("--------------------%d\n", devanshu.marks);
printf("--------------------%s\n", devanshu.name);
}
NewTest.c:
void func(struct student devanshu)
{
devanshu.rollNumber = 1;
devanshu.marks = 909;
strcpy(devanshu.name, "abc.xyz");
return;
}
And this is the output that I get:
In file included from test.c:6:0:
newtest.c:10:30: error: parameter 1 (‘devanshu’) has incomplete type
void func(struct student devanshu)
test.c: In function ‘main’:
test.c:23:7: error: incompatible type for argument 1 of ‘func’
func(&devanshu);
^
In file included from test.c:6:0:
newtest.c:10:6: note: expected ‘struct student’ but argument is of type ‘struct student *’
void func(struct student devanshu)
newtest.c:10:30: error: parameter 1 (‘devanshu’) has incomplete type
void func(struct student devanshu)
newtest.c:7:20: error: storage size of ‘devanshu’ isn’t known
struct student devanshu;
If I use the function in the same file i.e in test.c it does not throw any error and works just fine. But when keeping the functions in two different files, it gives me these errors.
Would be thankful if somebody could help me get through. Thanks in advance.
error: parameter 1 (‘devanshu’) has incomplete type
This means that the struct definition isn't visible to the file you use it inside. Unless this is intentional, you need to place the struct definition in a header file and include that by every .c file using the struct.
expected ‘struct student’ but argument is of type ‘struct student *’
You have written the functions incorrectly. It should be void func(struct student* devanshu); and inside the function you should access members with devanshu-> .... Otherwise you just pass a copy of the struct to the function and then change the local copy.
The errors are pretty self explanatory. Take this one:
test.c: In function ‘main’:
test.c:23:7: error: incompatible type for argument 1 of ‘func’
func(&devanshu);
It means you're passing something to func that has a different type to what you've told the compiler that func accepts. You've declared the function to take a struct student
void func(struct student devanshu);
but the function call is passing a pointer to struct student.
func(&devanshu);
The function call is correct as you want the function to have access to the struct you're passing and not a copy. So you'll need to change the function to take a struct student *.
The other errors are because you're not using an include file to store the definition of the struct.
Create a file called "student.h" (or whatever) and move the definition of the struct into it. And also the declaration of the function too.
struct student{
int rollNumber;
unsigned char name[20];
int marks;
};
void func(struct student *);
and at the top of both C files you put
#include "student.h"
which tells the compiler to copy the contents of that file into your C files when you're compiling. It means you have a consistent definition that can be shared by all the files that need it.
Ok, this will work: (Explanation below)
test.h: (New file!)
struct student{
int rollNumber;
char name[20];
int marks;
};
test.c:
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
void func(struct student *devanshu);
int main(){
struct student devanshu;
func(&devanshu);
printf("--------------------%d\n", devanshu.rollNumber);
printf("--------------------%d\n", devanshu.marks);
printf("--------------------%s\n", devanshu.name);
}
NewTest.c:
#include <string.h>
#include "test.h"
void func(struct student *devanshu)
{
devanshu->rollNumber = 1;
devanshu->marks = 909;
strcpy(devanshu->name, "abc.xyz");
return;
}
This
unsigned char name[20];
will give you problems later on strcpy(). Change to just char.
This
void func(struct student devanshu);
is not wrong, but you fall into a trap. Structures in C are always passed by value (copy) of the entire struct. So, if you want func() to modify the original struct, you have to explicitly tell it so:
void func(struct student *devanshu);
Then, in func, you need to change the access syntax to using the -> operater insteadf of '.'
As you are using the struct student in both files, you need to move the declaration of the struct out into a header file. You could (as I did on the very first edit) also repeat the declaration because I was lazy, but the comments are 100% right: That is a very dangerous practice, so I changed that.

Error when passing struct to function in c

When I pass a struct to a function, I get the error: expected ‘struct book’ but argument is of type ‘struct book'. Why is this happening?
#include <stdio.h>
#include <string.h>
struct book
{
int id;
char title[50];
};
int showBooks(struct book x);
int main()
{
struct book
{
int id;
char title[50];
};
struct book book1,book2;
book1.id = 2;
book2.id = 3;
strcpy(book1.title, "c programming");
strcpy(book2.title, "libc refrence");
printf("Book\t\tID\n");
showBooks(book1);
showBooks(book2);
}
int showBooks(struct book x)
{
printf("%s\t%d\n", x.title, x.id);
}
The error:
30:12: error: incompatible type for argument 1 of ‘showBooks’
showBooks(book1);
10:5: note: expected ‘struct book’ but argument is of type ‘struct
book’ int showBooks(struct book x);
31:12: error: incompatible type for argument 1 of ‘showBooks’
showBooks(book2);
10:5: note: expected ‘struct book’ but argument is of type ‘struct
book’ int showBooks(struct book x);
where the error here?
Your two different struct definitions define two different types. Even though they are both called struct book, they are not the same type.
Your variables book1 and book2 have a type of the local struct, but the function expects a struct of the type of the global struct, hence the error.
You could fix the problem by deleting the local struct definition; then book1 will have the type of the global struct etc.
A local variable or parameter that hides a global variable of the same name. This may be confusing. The "struct book" inside the main() hides the global definition of the "struct book".
The variables book1 and book2 are the type of "struct book" with local reference to the main().
The showBooks() use arguments as the book1 or book2 as formal parameters.
The actual parameter uses the global definition of the "struct book" which results in incompatible type.
Comment the local definition and find the difference.

C Structures: Printing a string member produces weird results

I am independently learning C. I have a four member struct as follows:
#define aSize 10
struct Students {
char lastName[aSize];
char firstName[aSize];
int age;
int grade;
}
I have two separate functions (in the main.c file):
void pasteInfo_1(struct Students S1) {}
and
void printStudents(struct Students S1) {}
pasteInfo() uses strcpy() and assignment to assign values to the members; printStudents() then prints the values stored in the members. When I compile the file:
#in makefile
CFLAGS = -lm -o -Wall
gcc main.c $(CFLAGS) main
It compiles with no errors. However, when I call the executable it prints some very weird characters that look like binary/assembly. Any suggestions? Here are the individual functions.
void pasteInfo_1(struct Students S1) {
strcpy(S1.lastName, "Effinger");
}
And here is printStudents:
void printStudents(struct Students S1) {
printf("%s\n",S1.lastName);
}
The function calls in main:
int main() {
struct Students S1;
pasteInfo_1(S1);
printStudents(S1);
}
Re: Modifications.
After adding the changes suggested by user3629249, I got the following errors:
main.c:6:23: warning: ‘struct Students’ declared inside parameter list will not be visible outside of this definition or declaration
void pasteInfo(struct Students * pS1);
^~~~~~~~
main.c:7:27: warning: ‘struct Studens’ declared inside parameter list will not be visible outside of this definition or declaration
void printStudents(struct Studens S1);
^~~~~~~
main.c: In function ‘main’:
main.c:22:14: warning: passing argument 1 of ‘pasteInfo’ from incompatible pointer type [-Wincompatible-pointer-types]
pasteInfo( &S1);
^
main.c:6:6: note: expected ‘struct Students *’ but argument is of type ‘struct Students *’
void pasteInfo(struct Students * pS1);
^~~~~~~~~
main.c:23:17: error: type of formal parameter 1 is incomplete
printStudents(S1);
^~
main.c: At top level:
main.c:26:6: error: conflicting types for ‘pasteInfo’
void pasteInfo(struct Students * pS1)
^~~~~~~~~
main.c:6:6: note: previous declaration of ‘pasteInfo’ was here
void pasteInfo(struct Students * pS1);
^~~~~~~~~
main.c:32:6: error: conflicting types for ‘printStudents’
void printStudents(struct Students S1)
^~~~~~~~~~~~~
main.c:7:6: note: previous declaration of ‘printStudents’ was here
void printStudents(struct Studens S1);
^~~~~~~~~~~~~
It seems from your error messages as though you need to forward declare struct Students and/or pasteInfo. See your textbook for advice on how to do that, if necessary.
I am independently learning C.
What does this mean? Are you reading from a book? If so, which book?
Keep in mind that it's dangerous to learn C by misguided trial and error; what you'll most likely end up learning is something that differs from C in subtle and possibly dangerous ways, and which medications best deal with the headaches you give yourself...
That's the peril of learning by misguided trial and error; you'll run into a lot of undefined behaviour (and implementation-defined behaviour) that will differ from system to system and might not make sense at the time...
You're better off avoiding UB and IB by reading a decent book such as K&R2E, and doing the exercises as you stumble across them.
when the called function plans to (directly) change anything in the caller function, pass the address of the item to the called function. I.E.
int main( void )
{
struct Students S1;
pasteInfo_1( &S1 ); // <-- passing pointer to struct
printStudents( S1 );
}
Then modify the pasteInfo_1()` function to expect a pointer,
void pasteInfo_1( struct Students * pS1 )
{
strcpy( pS1->lastName, "Effinger" );
}
Note the use of vertical alignment of the braces and the use of appropriate horizontal spacing.
The purpose of the vertical alignment and horizontal spacing is to make the code much more readable.
Solved it! Here is the working code:
(Special Thanks to user3629249 and Seb for their advice)
'#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
struct Students
{
char lastName[8];
char firstName[6];
int age;
int grade;
};
void pasteInfo(struct Students *S1);
void printStudnets(struct Students S1);
int main(void)
{
struct Students S1;
pasteInfo( &S1 );
printStudents( S1 );
}
void pasteInfo(struct Students *S1)
{
strcpy(S1->lastName, "Effinger");
}
void printStudent(struct Students S1)
{
printf("%s\n",S1.lastName);
}

Resources