Multiple definition and file management - c

I'm writing a program for vocabulary training, for myself. And the program itself should be available in different languages, atm in German and English.
What I want is to have a main file which manage all and two separate files for the functions in the right language.
I compile all the files with:
gcc vocTrainer.c german_menue.c english_menue.c -o v.exe
But I get an error of multiple definition even though I only include one of the language files depending on your input.
Multiple defintion of 'orderOfVoc'
First defined here: collect2.exe error: ld returned 1 exit status
My code:
vocTrainer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "german_menue.h"
#include "english_menue.h"
int main(void)
{
char selectLang[1]; //store 1 for English or 2 for German
system("cls"); //clear screen
memset(selectLang,0,1); //set all fields in the array to 0
while(selectLang[1] != 1 && selectLang[1] != 2)
{
//select your language
printf("Choose language - Sprache auswaehlen:\n(1) - Englisch/English\n(2) - Deutsch/German\n");
scanf("%d",&selectLang[1]);
system("cls");
}
//language query
if(selectLang[1] == 2)
{
#include "german_menue.c"
}
else
{
#include "english_menue.c"
}
printf("Test of select Order: %d",orderOfVoc());
return 0;
}
german_menue.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "german_menue.h"
int orderOfVoc()
{
char selectOrder[1]; /*store the choosen order of vocabulary.
1 for one after another 2 for a random sequence of words*/
printf("Wie sollen die Vokabeln abgefragt werden?\n(1) - Der Reihe nach\n(2) - Zufaellig\n");
scanf("%d",&selectOrder[1]);
return selectOrder[1];
}
english_menue.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "german_menue.h"
int orderOfVoc()
{
char selectOrder[1]; /*store the choosen order of vocabulary.
1 for one after another 2 for a random sequence of words*/
printf("How do you want to learn the vocabulary?\n(1) - Vocabulary in order\n(2) - Random order\n");
scanf("%d",&selectOrder[1]);
return selectOrder[1];
}
german_menue.h
#ifndef GERMAN_MENUE_H //include guards
#define GERMAN_MENUE_H
extern int orderOfVoc();
#endif //GERMAN_MENUE_H
english_menue.h
#ifndef ENGLISH_MENUE_H //include guards
#define ENGLISH_MENUE_H
extern int orderOfVoc();
#endif //ENGLISH_MENUE_H

Primary Issue: In your code,
if(selectLang[1] == 2)
{
#include "german_menue.c"
}
else
{
#include "english_menue.c"
}
is not doing what you're thinking. There are may issues, like
#include is compile time operation (during preprocessing state) and essentially cannot be controlled at runtime.
You don't include source files. You compile and link them together. Your compilation statement looks correct. Just leave out the above mentioned code snippet from your code.
Just to add a bit detail regarding the reason behind the error you received, is because, you have #includeed the source files (which is essentially adding the source code of that .c file in vocTrainer.c file itself) and again, at compile time, you're putting the .c files. Thus, after compilation, at linking state, compiler sees more than one occurrences of orderOfVoc() which is why compiler is complaining.
Solution:
You remove different definition of orderOfVoc() function. Make use of the user selected value. Pass the value to the orderOfVoc() as an argument, and execute accordingly.
Secondary Issue(s): Apart from above issue(s), in your code, with a definition like
char selectLang[1];
writing
scanf("%d",&selectLang[1]);
is wrong, because
selectLang[1] is out of bound access. Array index in C starts from 0.
%d is not the correct formart specifier for char.
FWIW, char selectLang[1]; is functionally equivalent with char selectLang;
A modified version (not tested) for aforesaid approach:
select_menue.h
#ifndef SELECT_MENUE_H //include guards
#define SELECT_MENUE_H
//according to {store 1 for English or 2 for German}
#define ENGLISH 1
#define GERMAN 2
extern int orderOfVoc(int);
#endif //SELECT_MENUE_H
select_menue.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "select_menue.h"
int orderOfVoc(int lang)
{
int selectOrder = 0;
switch (lang)
{
case ENGLISH:
printf("How do you want to learn the vocabulary?\n(1) - Vocabulary in order\n(2) - Random order\n");
scanf("%d",&selectOrder); //add possible error check
break;
case GERMAN:
printf("Wie sollen die Vokabeln abgefragt werden?\n(1) - Der Reihe nach\n(2) - Zufaellig\n");
scanf("%d",&selectOrder); //add possible error check
break;
}
return selectOrder;
}
vocTrainer.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "select_menu.h"
int main(void)
{
int selectLang = 0; //array not required, initialize in single statement
//store 1 for English or 2 for German
while(selectLang != 1 && selectLang != 2)
{
//select your language
printf("Choose language - Sprache auswaehlen:\n(1) - Englisch/English\n(2) - Deutsch/German\n");
scanf("%d",&selectLang);
}
printf("Test of select Order: %d",orderOfVoc(selectLang));
return 0;
}

#include is a preprocessor directive that includes the contents of the file named at compile time.
The code that conditionally includes stuff is executed at run time...not compile time. So both files are being compiled in. ( You're also including each file twice, once in the main function and once above it, which is just confusing and probably wrong, but we'll ignore that for now. )
You can't really conditionally include stuff at run time. You can use other preprocessor directives (#ifdef, etc. ) to conditionally include one or the other file at compile time, but for your purposes you really need to have some sort of global flag that each function in the included files uses to determine if it should display english or german, etc.
Internationalization of strings is a whole topic in itself. There are lots of ways to handle it, and some libraries to make it easier depending on your platform.
Here's one way you could handle the same scenari:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "german_menue.h"
char *getLocalizedString(int stringId)
{
// Pseudo-Code, not real C++
// Also ignores memory issues and deallocating strings when done
char *localizedString = LoadGermanOrEnglishStringBasedOnGlobalVarForLanguage(stringId);
return localizedString ;
}
int orderOfVoc()
{
int stringId = 1;//should be constant for this message
char *localizedString = getLocalizedString(stringId);
printf("%s", localizedString);
scanf("%d",&selectOrder[1]);
return selectOrder[1];
}

Related

Memory Allocation Error with C? Code works when unused variable is defined; crashes otherwise

I'm a novice C programmer and am completely stuck on debugging a program that relies on the CFITSIO package [sorry in advance if I get the terminology wrong below]. I have two fits that I am reading in: 1. "BFmask.fits", 2. "DFmask.fits". These are two files that either have a 1 or a 0 as elements.
These are defined as double precision pointers as below:
double *maskdark,*maskbright;
Memory allocation is as follows:
maskdark=malloc(size*sizeof(double)); //dark mask
maskbright=malloc(size*sizeof(double)); //bright mask
where "size" is a long variable with a value of 490000
THE PROBLEM: When I execute the program, it apparently does not properly read in BFmask.fits or DFmask.fits (i.e. does not properly read in entries for maskbright or maskdark).
HOWEVER, when I declare a third variable called 'mask' (i.e. double *mask;), then the program DOES execute properly.
What is the cause and solution to this problem?
How do I avoid similar ones in the future?
I have checked dozens of times to make sure this variable is not used anywhere in the program. This makes no sense to me.
#include <stdio.h>
//For declaration of open, close
#include <sys/stat.h>
#include <fcntl.h>
#include <math.h>
#include <unistd.h>
#include <time.h>
//GSL Matrix STuff
#include <gsl/gsl_vector.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_eigen.h>
#include <gsl/gsl_blas.h>
//CFITSIO
#include <fitsio.h>
int main ()
{
long sizetotdm,cmwfsbrightindex,cmwfsdarkindex;
long size,sizex,sizey;
double *maskdark,*maskbright;
//double *mask; //if I uncomment this, then the program works properly somehow
fitsfile *fptr;
float nullval;
int status, anynull;
cmwfsbrightindex=0;
cmwfsdarkindex=0;
sizex=700; sizey=700; size=sizex*sizey;
/* Define Masks for Dark Field and Bright Field */
maskdark=malloc(size*sizeof(double)); //dark mask
maskbright=malloc(size*sizeof(double)); //bright mask
/* Read in Dark and Bright Field Mask files */
sprintf(s_file,"./06_21_19_mask/BFmask.fits");
fits_open_file(&fptr,s_file,READONLY,&status);
fits_read_img(fptr,TDOUBLE,1,size,&nullval,maskbright,&anynull,&status);
sprintf(s_file,"./06_21_19_mask/DFmask.fits");
fits_open_file(&fptr,s_file,READONLY,&status);
fits_read_img(fptr,TDOUBLE,1,size,&nullval,maskdark,&anynull,&status);
for (i=0;i<size; i++)
{
if (*(maskbright+i)==1)
{
cmwfsbrightindex+=1;
}
if (*(maskdark+i)==1)
{
cmwfsdarkindex+=1;
}
}
printf("the number of pixels is %ld %ld \n",cmwfsbrightindex,cmwfsdarkindex);
}
Results should be ...
the number of pixels is 24212 24952 //this happens when I define an unused variable
The results are ...
the number of pixels is 0 0 //this happens when I comment out the unused variable

C-Checking if input (float) is purely integer or float

I want to check if the user input is purely integer or a float. I attempted to do this by using floor and ceilfand comparing the values to the original x value in a function. However, this seems to be a tad bit problematic as the function keeps returning 0 instead of 1 for certain numbers like 5.5, when floor(5.5)!=5.5 and ceilf(5.5)!=5.5. This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <stdbool.h>
int intchecker(float x)//in a separate file
{
if (floor(x)==x && ceilf(x)==x)
{
//printf("%f",floor(x));
return 0;
}
else {
return 1;
}
}
int main()
{
char line[] = " +----+----+----+----+----+----+----+----+----+----+---+";
char numbers[] = " 0 5 10 15 20 25 30 35 40 45 50";
float balls,slots;
int slot[9];
printf("==========================================================\nGalton Box Simulation Machine\n==========================================================\n");
printf("Enter the number of balls [5-100]: ");
scanf("%f",& balls);
if (balls>100 || balls<5){
printf("/nInput is not within the range. Please try again.");
}
else if (intchecker(balls)==1){
printf("/nInput is not an integer. Please try again.");
}
else {
printf(" This is an integer.");
//some more code here
}
}
I tried placing just the intchecker code in another project, which seems to work fine without any bugs, unlike in the previous project, where when I used a printf statement to check if the floor(x) value was correct, it kept showing different answers, e.g. "-2.000000" when input was 5.2. This is my code for the second project:
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
int main()
{
float x;
scanf("%f",&x);
if (floor(x)==x && ceilf(x)==x){
printf("Integer");
return 0;
}
else {
printf("Non-Integer");
return 1;
}
}
How is it possible that the second code works perfectly when the first code does not? Is something wrong with my way of writing/calling the function?(I am relatively new to functions-only 2 weeks of exposure so far)
I searched online and have seen many answers to check if input is integer or float, even on stackoverflow.com itself, but my wish is not to find out other ways to check if input is integer or float (for if I wished to do that, I could just google it, and there are many such questions on stackoverflow.com as well), but to comprehend why my first code does not work, for, as far as I know, it ought to work well without any of the bugs it is currently facing.
Any help is greatly appreciated!:)
Assuming a missing function declaration:
main.c is missing the prototype for int intchecker(float x) so main.c assumes the old-school prototype of int intchecker(int x) and the code exhibits undefined behavior. Anything could happen.
Add prototype in main.c or put it in separate.h and include that header file here and in separate.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <stdbool.h>
int intchecker(float x);
int main(void) {
...

How to access an integer array from one C file to another?

I have two C files namely 'Main.c' and 'algo.c'. The main.c file contains an array called the index_array and looks as follows:
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include "Main.c"
int algo();
int main(){
int index_array []= {1,2,3,4,5,6};
algo(index_array); //to call the function from the other file
return 0;
}
The other file looks like this:
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
int algo(int index_array){
///contains an algorithm to perform an operation using the array index from the Main.c file
}
Now what I have a doubt is on how do I get access to the array index_array[ ] from the algo.c file? The way I have tried it in the alog.c file does not give me access to it. It instead gives an error saying multiple declarations of 'algo'.
Could somebody give me an idea on this please?
The easiest approach will be to change the algo() function signature to accept two parameters, the array itself and the size. Something like
int algo(int *index_array, int size) { ....
That said, you should change your forward declaration to match the signature of the function definition.
Now, you can call algo from the main.c file like
algo(index_array, sizeof(index_array)/sizeof(index_array[0]));
Note: Please remove #include "Main.c" from your code. Source files are meant to be compiled and linked together to generate the binary.

How to make a function to determine if something is a built in command for the shell I'm writing

I am wrting a shell. I need a function to determine if the command entered in the shell by
the user is a valid builtin command. I'm not sure how to go about doing this.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
int is_builtin(command_t* command) {
// TODO: Iterate through `valid_builtin_commands`
while (valid_builtin_commands[i] != NULL )
i++
if(valid_builtin_commands[i] == command){
return true
}
return -1;
}
im trying to accomplish more along these lines in limited in the libraries i can use.
I have a magic crystal ball which says:
int is_builtin(command_t* command) {
return (command->flags & CMD_BUILT_IN) != 0;
}
Try that! You might have to define flags in the command_t structure, and populate that at the time the command_t object is instantiated from parsing the command input. Also, to supply the CMD_BUILT_IN constant in some header file somewhere.

How to handle multilevel includes in C?

I have second level include that is giving me grief:
Undefined first referenced
symbol in file
function2 /var/tmp//ccAPaWbT.o
ld: fatal: symbol referencing errors. No output written to run
collect2: ld returned 1 exit status
Main file:
#include "functions02.c"
int main(){
int x = funcion2();
}
functions02.c file:
#ifndef FUNCTIONS02_C
#define FUNCTIONS02_C
int funcion2();
#if __INCLUDE_LEVEL__ == 0
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include "functions01.c"
int main() {
return function2();
}
#endif
int function2()
return function1();
}
#endif
functions01.c file:
#ifndef FUNCTIONS01_C
#define FUNCTIONS01_C
int funcion1();
#if __INCLUDE_LEVEL__ == 0
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main() {
return function1();
}
#endif
int function1()
return 10;
}
#endif
I am assuming that this can be fixed manipulated using __INCLUDE_LEVEL__ or manipulating linking on gcc compiling but I can't find forking variant.
First of all is it possible to achieve what I am looking for without putting functions in external header files?
Second what would be the correct way of doing it?
EDIT:
I realized that I had forgotten to add function dependencies to them. That is the includes which are used by functions can not be excluded by adding them just next to main function warped in exclusion if close.
Yes, it is possible to include / exclude any part of the code using compile time flags (and in the code using #if's) as you are trying to do.
In your case, I assume you have not defined __INCLUDE_LEVEL__ flag, hence the linker is not able to find funciton2, so the error.
If you define it, you will have three "main()" :-), it will fail again. So, you need to rework your code a bit.
Also, #include'ing a "C" file is not advisable and not used in practice. I assume you are just trying to experiment & learn, which is fine.

Resources