How to properly create a C function (including header file) - c

I'm trying to create my own functions in C, and then use #include with a header file. I know how to make the header file, and I've written the .c function. However, when I try to compile the .c, I get an error that says '[Linker error]undefined reference to 'WinMain#16'' and it fails to compile.
Then, if I try to use it in a program, it says '[Warning]no newline at end of file' and then '[Linker error]undefined reference to validf(int, int, int)'.
Can anyone help?
Function Code:
int validf(int current,int max, int zero)
{
if(zero==1)
{
if(current>max || current<0)
{
printf("Invalid Input");
return 0;
}
else
{
return 1;
}
}
else if(zero==0)
{
if(current>max || current<=0)
{
printf("Invalid Input");
return 0;
}
else
{
return 1;
}
}
else
{
printf("Invalid parameters");
return -1;
}
}
Main Code:
#include<stdio.h>
#include<stdlib.h>
#include "validf.h"
int main()
{
int valid=0;
valid=validf(4,5,0);
printf("%d",valid);
system("\npause");
return 0;
}
Header Code:
#ifndef VALIDF_H_
#define VALIDF_H_
int validf(int current,int max,int zero);
#endif

Your program consists of 3 files:
validf.h header file for validf. Contains declaration of validf function
validf.c code file for validf. Contains definition of validf function.
main.c contains the main function. You may have chosen another name for this file.
In your IDE, you should create a project that consists of these files.
You also need to configure the name of the resulting program. I am not familiar with that particular IDE, but it is usually done under Project->Settings->Compile or Build or Link.
This will make your IDE compile the two .c files and then link them into a single program.
If you dont create a project it is probable that the IDE treats each .c file as a different program, which will cause the errors you mention.

Related

Is there a way to make the loading() void begin before the main() function?

I am very new to C and I am trying to create a sort of loading screen that appears before the actual program runs. I compiled it and it ran perfectly once but after that one time it wont do it anymore. I am wondering if I messed something up? The reason I dont want it in the main function is because I want to allow for returning to the main menu without having to input a name again. Any help would be amazing, like I said I am very new to C. P.S. I can attach the header file if needed. I am not sure what the issue is.
Main file:
#include "periodic-header.h"
void blue() {
printf("\033[0;36m");
}
void lime() {
printf("\033[1;32m");
}
void yellow() {
printf("\033[1;33m");
}
void colorReset() {
printf("\033[0m");
}
loading();
int main(char *userName) {
int choice;
colorReset();
system("cls");
table();
printf("\n\n");
yellow();
printf("\t\t Using the numbers on your keyboard,\n");
printf("\t\t Please select an option:\n\n");
printf("\t\t 1) Examine element\n");
printf("\t\t 2) Input data for element\n");
printf("\t\t 3) Exit program\n");
choose(&choice,3);
switch(choice){
case 1:{
examineElement();
break;
}
case 2:{printf("\t\t Test 2\n");
// addElement();
break;
}
case 3:{
system("cls");
printf("\n\n\t\t Thanks for stopping by %s,\n", userName);
Sleep ( 300 );
printf("\t\t ... hope to see you again soon!\n");
colorReset();
exit(1);
break;
}
default: printf("\t\t Sorry %s, that is not a valid option", userName); break;
}
colorReset();
}
Loading file:
#include "periodic-header.h"
void loading(){
system("cls");
yellow();
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t [ ASPECT ]\n");
colorReset();
blue();
Sleep ( 10000 );
printf("\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t Loading...\n");
Sleep ( 900 );
colorReset();
yellow();
system("cls");
printf("\n\n");
printf("\t\t Welcome...\n");
Sleep ( 300 );
printf("\t\t Please enter your name: ");
char userName [20];
fscanf(stdin, "%20s", userName);
Sleep ( 1300 );
}
Header file:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <conio.h>
#include <string.h>
#include <stdbool.h>
extern char userName[20];
// Prints view of periodic table
void table();
// Manipulates periodic table
void examineElement();
void addElement();
//Not in use yet
void menuSelection();
char selection[2];
// Used to choose what you want to do with the program
int choose();
// Element Credentials
extern char elementName[50];
extern char sb[5];
extern int atm;
extern float atms;
extern char block;
extern char atc[20];
extern char prop[250];
Unfortunately that's not possible, because main(), the entry point for the program, which means it's the function that gets executed when you run your program. However, what you can do is put the contents of main in a separate function and call loading() in main before your program begins. Here's what I'm referring to:
void load() {
// loading screen
}
void program() {
// the program
}
int main() {
load();
program();
}
We can make any function run before main is called if we make it a constructor function.
Constructors can take a "priority" number, so we can have several that are run in a specific order.
Lower priority numbers are reserved for gcc/glibc internal callback functions, so we should add a bias so we don't conflict with them.
Likewise, we can set up a "destructor" function.
Here's some sample code:
#include <stdio.h>
#define ctors ctorx(0)
#define dtors dtorx(0)
#define ctorx(_prio) __attribute__((constructor(_prio + 201)))
#define dtorx(_prio) __attribute__((destructor(_prio + 201)))
void ctorx(0)
loading(void)
{
printf("%s ...\n",__FUNCTION__);
}
void ctorx(-1)
i_am_called_before_loading(void)
{
printf("%s ...\n",__FUNCTION__);
}
void ctorx(1)
i_am_called_after_loading(void)
{
printf("%s ...\n",__FUNCTION__);
}
void dtorx(0)
i_am_called_after_main_has_completed(void)
{
printf("%s ...\n",__FUNCTION__);
}
int
main(void)
{
printf("main: running ...\n");
return 0;
}
Here's the output of the program:
i_am_called_before_loading ...
loading ...
i_am_called_after_loading ...
main: running ...
i_am_called_after_main_has_completed ...
UPDATE:
Can you explain how to make constructors in C? My guess is your code will not work without a C++ compiler. – Brendan
No, this will work regardless.
This is part of gcc. See info gcc for more details.
AFAICT, this [directly] uses the [underlying] mechanism that c++ would use for static/global constructors/destructors. That is, c++ doesn't "own" the mechanism, but is merely a client of a more general mechanism that is made available by ELF and can be used by various different languages.
This has been added in the last few years.
Before that, one could use ELF's .init/.fini section attributes to store pointers to callback functions.
This is how shared libraries (.so files) get callbacks to [hidden] initialization functions. The ELF interpreter (e.g. /lib64/ld-linux-x86-64.so) will find and issue the callbacks when loading the libraries.
Or, for really old code, the init/fini functions had to be called init and fini. For this, we may have had to put the functions into a separate shared library (.so) but, now, that is no longer the case.
AFAIK, the older mechanisms are still available/usable/valid and can be used in parallel to the constructor attribute.
I'm not sure how gcc implements the constructor attribute, but here's a guess:
The attribute gets morphed into a function pointer that gets put into (e.g.) section(gcc_constructor_list). The crt0.o [or equivalent] routine will call things defined in that section.
Another way would be to generate pointers to the functions and use ELF's .init/.fini sections.
Or, the function that issues the calls to gcc_constructor_list could just be an ELF .init function (and, therefore, doesn't need to be in crt0.o at all).
To see what is actually generated, after building the program, we can do readelf -a ./program and in the output there are:
.init and .fini section header. Segment sections of init_array and .fini_array
And, some entries in the "dynamic section" for: INIT_ARRAY, INIT_ARRAYSZ, FINI_ARRAY, and FINI_ARRAYSZ

error function declared but never defined

I have added a library to my c project in codeVision AVR. when I want to use it's functions receive this error:
function 'function name' is declared but never defined.
here is my code:
#include "pid.h"
#include <mega32.h>
PidType _pid;
void main(void)
{
//some uC hardware initializing codes which are removed here to simplify code
PID_Compute(&_pid);
while (1)
{
// Place your code here
}
}
in pid.h:
.
.
bool PID_Compute(PidType* pid);
.
.
and pid.c:
#include "pid.h"
.
.
bool PID_Compute(PidType* pid) {
if (!pid->inAuto) {
return false;
}
FloatType input = pid->myInput;
FloatType error = pid->mySetpoint - input;
pid->ITerm += (pid->ki * error);
if (pid->ITerm > pid->outMax)
pid->ITerm = pid->outMax;
else if (pid->ITerm < pid->outMin)
pid->ITerm = pid->outMin;
FloatType dInput = (input - pid->lastInput);
FloatType output = pid->kp * error + pid->ITerm - pid->kd * dInput;
if (output > pid->outMax)
output = pid->outMax;
else if (output < pid->outMin)
output = pid->outMin;
pid->myOutput = output;
pid->lastInput = input;
return true;
}
the ERROR:
function 'PID_Compute' declared, but never defined.
Where is the problem?
EDIT:
to add the library to my project I placed the .c and .h library files in the same folder that my main project file is:
and then #include "pid.h" in my main file:
#include "pid.h"
#include <mega32.h>
// Declare your global variables here
PidType _pid;
void main(void)
{
.
.
my error and warnings:
EDIT2:
I simplified the code and now can show you the entire code:
main code:
#include "pid.h"
PidType _pid;
void main(void)
{
PID_Compute(&_pid);
while (1)
{
}
}
pid.h:
#ifndef PID_H
#define PID_H
#include <stdbool.h>
typedef struct {
int i;
} PidType;
bool PID_Compute(PidType* pid);
#endif
pid.c:
#include "pid.h"
bool PID_Compute(PidType* pid) {
pid->i = 2;
return true;
}
thank you every body.
As you said, the pid.c was not added to the project.
for those who may face the same problem:
in codeVision AVR we have to add .c file to project from project->configure->files->input files->add
I addec .c file to project and the error went away.
From the screenshot with the tree view of your files it is clear that the file "pid.c" is not part of the project.
Move it into your project. Then it should build without that linker error.
This does not mean the location in the file system. I reference the "virtual" view of the IDE on your project.

How to make Data File Handling functions in a private header file? (To be edited)

EDIT: This question is to be edited, please stop reading. Don't waste your time! Thank you
I’m doing High School Turbo C++. I tried making a header file containing a function to search a binary file.
My Headerfile program is: alpha.h
#ifndef ALPHA_H
#define ALPHA_H
#if !defined __FSTREAM_H
#include<fstream.h>
#endif
#if !defined __PROCESS_H
#include<process.h>
#endif
void searchclass(char* & buf, int, char *);
#endif
According to some research that I did on the internet, I found out that the definitions will go in a separate program not in the main header file. So this is that program: ALPHA.CPP
#include<process.h>
#include<fstream.h>
#include"alpha.h"
//All the Definations of the alpha.h header file go here
void searchclass(char* & buf, int s_var, char * file)
{
ifstream fin;
fin.open(file, ios::binary);
if(!fin)
{
cout<<"Error 404: File not found";
exit(-1);
}
while(!fin.read((char*)buf, sizeof(buf)))
if(buf.getint()==s_var)
cout<<"\n\nRecord Found!";
buf.show();
fin.close();
}
Keep in mind that I'm trying to write a function that can help me search a random binary file storing records in form of classes for some specific int variable. So it should be able to take in an object of any class and perform a search in it.
This is the program I wrote to check my header file. A_TEST.CPP
#include<iostream.h>
#include<conio.h>
#include<fstream.h>
#include"alpha.h"
#include<string.h>
class stu
{ int rn;
char name[20];
public:
void show() //Display Function
{
cout<<"\n\tStudent Details:";
cout<<"\nName: "<<name;
cout<<"\nRoll No.: "<<rn;
}
stu() //constructor
{
rn = 6;
strcpy(name,"Random Name");
}
int getint() //return function
{
return rn;
}
};
char* returnfile()
{ char file[10];
strcpy(file,"file.dat");
return file;
}
void main()
{
clrscr();
int search_var=6;
stu S1;
char file[10];
strcpy(file, "test.dat");
ofstream fout;
fout.open(file, ios::binary);
fout.write((char*)&S1, sizeof(S1));
fout.close();
searchclass((char*)& S1, search_var, file);
getch();
}
On compiling A_TEST.CPP (above program), I get the warning:
Warning A_TEST.CPP 45: Temporary used for parameter 'buf' in call to
'searchclass(char * &,int,char *)'
On linking, it gives me this error:
Linking A_TEST.EXE
Linker Error: Undefined symbol searchclass(char nearnear&,int,char
near) in module A_TEST.CPP
I don't think that the ALPHA.CPP file is getting linked with the alpha.h file, and if I compile ALPHA.CPP file it gives me the following errors:
Error ALPHA.CPP 17: Structure required on left side of . or .*
Error ALPHA.CPP 19: Structure required on left side of . or .*
Warning ALPHA.CPP 21: Parameter 's_var' is never used
In ALPHA.CPP 17 and 19, you can't write code like that, because int type hasn't getint() or show() methods. If you want to check int in the buffer, you should convert pointer into "int*" first, try below code:
int count = fin.read((char*)buf, sizeof(buf));
for (int i = 0; i<(count-4); ++i) {
if (*(int *)(buf + i) == s_var) {
cout << "\n\nRecord Found!";
break;
}
}

connection gwan with aerospike db in C

Hello.
First I'm sorry for my ita-english.
I want use gwan with aerospike but when run the servlet...problem.
I start with this example.c of aerospike. In file example.c I put gwan.h and this is the output ./gwan:
loading
hello.cs: to use .cs scripts, install C#..
hello.lua: to use .lua scripts, install Lua
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Linking example.c: undefined symbol: g_namespace
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To run G-WAN, you must fix the error(s) or remove this Servlet.
Inside example.c:
#include "gwan.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <aerospike/aerospike.h>
#include <aerospike/aerospike_key.h>
#include <aerospike/aerospike_query.h>
#include <aerospike/as_error.h>
#include <aerospike/as_key.h>
#include <aerospike/as_query.h>
#include <aerospike/as_record.h>
#include <aerospike/as_status.h>
#include <aerospike/as_val.h>
#include "example_utils.h"
const char TEST_INDEX_NAME[] = "test-bin-index";
bool query_cb(const as_val* p_val, void* udata);
void cleanup(aerospike* p_as);
bool insert_records(aerospike* p_as);
int
main(int argc, char* argv[])
{
if (! example_get_opts(argc, argv, EXAMPLE_MULTI_KEY_OPTS)) {
exit(-1);
}
aerospike as;
example_connect_to_aerospike(&as);
example_remove_test_records(&as);
example_remove_index(&as, TEST_INDEX_NAME);
if (! example_create_integer_index(&as, "test-bin", TEST_INDEX_NAME))
{
cleanup(&as);
exit(-1);
}
if (! insert_records(&as)) {
cleanup(&as);
exit(-1);
}
if (! example_read_test_records(&as)) {
cleanup(&as);
exit(-1);
}
as_error err;
as_query query;
as_query_init(&query, g_namespace, g_set);
as_query_where_inita(&query, 1);
as_query_where(&query, "test-bin", as_integer_equals(7));
LOG("executing query: where test-bin = 7");
if (aerospike_query_foreach(&as, &err, NULL, &query, query_cb, NULL)
!= AEROSPIKE_OK) {
LOG("aerospike_query_foreach() returned %d - %s", err.code,
err.message);
as_query_destroy(&query);
cleanup(&as);
exit(-1);
}
LOG("query executed");
as_query_destroy(&query);
cleanup(&as);
LOG("simple query example successfully completed");
return 0;
}
bool
query_cb(const as_val* p_val, void* udata)
{
if (! p_val) {
LOG("query callback returned null - query is complete");
return true;
}
as_record* p_rec = as_record_fromval(p_val);
if (! p_rec) {
LOG("query callback returned non-as_record object");
return true;
}
LOG("query callback returned record:");
example_dump_record(p_rec);
return true;
}
void
cleanup(aerospike* p_as)
{
example_remove_test_records(p_as);
example_remove_index(p_as, TEST_INDEX_NAME);
example_cleanup(p_as);
}
bool
insert_records(aerospike* p_as)
{
set
as_record rec;
as_record_inita(&rec, 1);
for (uint32_t i = 0; i < g_n_keys; i++) {
as_error err;
as_key key;
as_key_init_int64(&key, g_namespace, g_set, (int64_t)i);
as_record_set_int64(&rec, "test-bin", (int64_t)i);
if (aerospike_key_put(p_as, &err, NULL, &key, &rec) != AEROSPIKE_OK) {
LOG("aerospike_key_put() returned %d - %s", err.code, err.message);
return false;
}
}
LOG("insert succeeded");
return true;
}
how can connect aerospike with gwan?
Thank you
You need to #pragma link your aerospike library, and make sure all your required header files are in the right place. See G-WAN FAQ or read example code in the G-WAN tarball.
Also, in G-WAN the return code of the main function will be used as HTTP response code, so avoid return -1;.
undefined symbol: g_namespace
the error message is clear. As long as this variable is undefined your C servlet won't compile.
I don't know your library but this variable is probably defined in a library include file - or must be defined by the end user (you). Check the library documentation.
Detailed steps to run Aerospike C-client example with G-WAN,
Download and extract G-WAN server tar on your system
You can start the G-WAN server using ./gwan script present in extracted folder, e.g. ./gwan_linux64-bit/
Get Aerospike C-client from https://github.com/aerospike/aerospike-client-c, and install on your system
Copy example.c to ./gwan_linux64-bit/0.0.0.0_8080/#0.0.0.0/csp/
Make following changes to example.c,
Add following #pragma directive,
#pragma include "/home/user/aerospike-client-c/examples/utils/src/include/"
This will help search example_utils.h, which is necessary for all the example scripts in C-client.
Add following #pragma directive,
#pragma link "/home/user/aerospike-client-c/examples/utils/src/main/example_utils.c"
We shall have to link example_utils.c, as it has definitions of all util functions used in example scripts.
Make changes to the return values. Retun proper HTTP error codes.
Now, you are good to go. Run ./gwan server and access your webservice through browser, http://127.0.0.1:8080/?example.c

Facing error calling enum within header file

I've created the below function(getHobby(Hobbies)) within a header file and when I'm calling this function in the header file itself, I'm getting an error:
conflicting types for 'getHobby'
HobbiesTest.h
enum Hobbies {
SKATING, SPORTS
};
char *getHobby(enum Hobbies hobbie) { <-- Compilation error "conflicing types for
'getHobby'
switch (hobbie) {
case SKATING:
return "SKATING";
case SPORTS:
return "SPORTS";
}
return "INVALIDOPTION";
}
void enumTest(){
printf("\nYour hobby is: %s",getHobby(SKATING));
}
And, when I'm calling the same function from the main file within some method, the same code is working fine.
Main.c
include <HobbiesTest.h>
int main(void) {
enumTest();
return 0;
}
void enumTest(){
printf("\nYour hobby is: %s",getHobby(SKATING));
}
Why I'm getting a compilation error in case of header file?
Put
enum Hobbies {
SKATING, SPORTING
};
At the start of header file. You using this enum before it is defined.

Resources