Undefined function reference in C - c

I've several files with main functions in C, for example, I've files called show.c, delete.c add.c (...). I also have a file, called interpreter.c, which may call one of the files, for example delete.c. Most of these file implement a main function, like the delete.c:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
int main (int argc, char *argv[])
{
int fd, rm;
char *caminho = argv[1]; // argumento inserido no terminal
char caminhod[30]="../TPSOFinal/";
strcat(caminhod,argv[1]);
fd = open(caminhod, O_RDONLY);
rm=unlink(caminhod);
// Verifica se o caminho inserido no input existe
if(rm == 0){
write(1,"Ficheiro eliminado!!!\n", 22);
return 0;
}
else{
write(1,"Erro ao eliminar ficheiro !!!\n", 29);
perror("Erro");
}
return 0;
close(fd);
}
The interpreter:
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <readline/readline.h>
#include <readline/history.h>
#define LER_BUFFER 1024
#define TBUFF 64
#define DELIM "\t\r\n\a"
int mostra(char **args);
int conta(char **args);
int acrescenta(char **args);
int apaga(char **args);
int informa(char **args);
int lista(char **args);
int manual(char **args);
int termina(char **args);
char *comando[] =
{
"mostra <caminho>",
"conta <caminho>",
"acrescenta <caminho> <caminho destino>",
"apaga <caminho>",
"informa <caminho>",
"lista <caminho>",
"manual",
"termina",
" ",
};
int (*fcomandos[]) (char**) =
{
&mostra,
&conta,
&acrescenta,
&apaga,
&informa,
&lista,
&manual,
&termina
};
int ncomandos()
{
return sizeof(comando)/sizeof(char*);
}
void processa(char *linha, char **argv)
{
while(*linha != '\0')
{
while(*linha == ' ' || *linha == '\t' || *linha == '\n')
{
*linha++ = '\0'; //troca caracteres especiais
}
*argv++ = linha; //guarda posição
while (*linha != '\0' && *linha != ' ' && *linha != '\t' && *linha != '\n')
{
linha++;
}
}
*argv = NULL;
}
char *lerlinha (void)
{
char *linha = NULL;
ssize_t tam = 0;
getline (&linha, &tam, stdin);
return linha;
}
char **separa (char *linha)
{
int tam = TBUFF, pos = 0;
char **palavras = malloc (tam *sizeof(char*));
char *palavra;
if (!palavras)
{
perror("Erro");
exit(EXIT_FAILURE);
}
palavra = strtok (linha, DELIM);
while (palavra != NULL)
{
palavras [pos] = palavra;
pos ++;
if (pos >= tam)
{
perror ("Erro");
}
}
palavra = strtok(NULL, DELIM);
palavras [pos] = NULL;
return palavras;
}
int launch (char **args)
{
pid_t pid, wpid;
int estado;
pid = fork();
if (pid == 0)
{
if(execvp(args[0],args)==-1){ perror ("Erro!"); }
exit (EXIT_FAILURE);
}
if (pid <0)
{
perror ("Erro!");
}
else
{
do{wpid = waitpid(pid, &estado, WUNTRACED);}
while (!WIFEXITED(estado)&& !WIFSIGNALED(estado));
}
return 1;
}
//Testa se os comandos existem
int mostra (char **args)
{
if (args[1] == NULL)
{
perror("sem argumentos ");
}
else if (chdir (args[1]) != 0)
{
perror ("Erro!");
}
return 1;
}
int conta ( char ** args)
{
if (args[1] == NULL)
{
perror("Sem argumentos ");
}
else if (chdir (args[1])!= 0)
{
perror ("Erro!");
}
return 1;
}
// Manual dos comandos
int manual (char **args)
{
int i;
printf("\n\nMiguel Oliveira\n");
printf("10260 - LESI\n");
printf("Sistemas Operativos e Sistemas Distribuidos\n");
printf("\nLista de Comandos\n");
for (i=0; i<ncomandos(); i++)
{
printf("%s\n", comando[i]);
}
return 1;
}
int termina (char **args)
{
return 0;
}
//Executa os comandos
int executar (char **args)
{
int i;
if (args[0] == NULL)
{
return 1;
}
for (i=0; i<ncomandos(); i++)
{
if (strcmp(args[0], comando[i])==0)
{
return (*fcomandos[i])(args);
}
}
return launch(args);
}
//Interpretador
void interpretador (void)
{
char *linha;
char **args;
int estado;
do
{
printf("%% ");
linha = lerlinha();
args = separa(linha);
estado = executar(args);
free(linha);
free(args);
} while (estado);
}
int main (void)
{
interpretador();
return EXIT_SUCCESS;
}
I've tried to research for similar problems, and i've found some little possible solutions, but cannot solve my problem, as show on bottom GCC compile mistake

You do not "call source files"; source files define functions and variables, and when compiled, ones defined in different files can use each other if they have a declaration (in a header file, usually) or a pointer (via dynamic link methods, like POSIX dlsym()).
Consider this minimal example. First, example.c:
#include <stdlib.h>
#include <stdio.h>
/* We expect someone else to define these */
extern int one(void);
int main(void)
{
printf("one() returned %d.\n", one());
return EXIT_SUCCESS;
}
and helper.c:
int one(void)
{
return 2; /* TODO: It's not one! */
}
You compile each source file to an object file:
gcc -Wall -O2 -c example.c
gcc -Wall -O2 -c helper.c
and then you link them to an executable program:
gcc -Wall -O2 example.o helper.o -o program
which you can run using
./program
Normally, each C source file that provides functions or variables usable outside that file, declares them in a header file. Here's a better example.
degrees.h
#ifndef DEGREES_H
#define DEGREES_H
double radians_to_degrees(double);
double degrees_to_radians(double);
#endif /* DEGREES_H */
The #ifndef, #define, and #endif are used as guards, so that if you #include the file more than once, the functions get declared only once. (The compiler will complain if it sees multiple declarations. Plus, we don't need to use extern here.)
The implementation of the above is then in degrees.c,
#ifndef PI
#define PI 3.14159265358979323846
#endif
double degrees_to_radians(double degrees)
{
return degrees * PI / 180.0;
}
double radians_to_degrees(double radians)
{
return radians * 180.0 / PI;
}
In a program myprog.c in the same project, you would use the above thus:
#include <stdlib.h>
#include <stdio.h>
#include "degrees.h"
int main(void)
{
printf("45 degrees is %.6f radians.\n", degrees_to_radians(45.0));
printf("2 radians is %.3f degrees.\n", radians_to_degrees(2.0));
return EXIT_SUCCESS;
}
and again you'd compile first the two source files to object files,
gcc -Wall -O2 -c degrees.c
gcc -Wall -O2 -c myprog.c
and then link together to a program, say myprog,
gcc -Wall -O2 degrees.o myprog.o -o myprog
which you can then run:
./myprog
It is also possible to compile and link the functions and variables declared in degrees.h to a static (libdegrees.a) or a dynamic (libdegrees.so) library, and install the header file to the standard location, so that your program could instead use #include <degrees.h> and the program link to the library via -ldegrees, but that is better left until you are well comfortable working with multiple files.
Until then, you might find the following Makefile useful
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS :=
PROGS := myprog
all: clean $(PROGS)
clean:
rm -f *.o $(PROGS)
%.o: %.c
$(CC) $(CFLAGS) -c $^
myprog: degrees.o myprog.o
$(CC) $(CFLAGS) $^ -o $#
You can add multiple programs in the PROGS line, separated by spaces, and copy the myprog: lines for each, listing the object files that program needs.
With this, all you need to compile the program is to type make.
This forum eats Tabs, and Makefiles need indentation to use those. So, if you just copy-paste that to a file, it won't work. You can fix it, though, by running
sed -e 's|^ *|\t|' -i Makefile
which removes all initial spaces on each line with a tab in file Makefile.
If you use separate libraries, typically libm (#include <math.h>), you just need to add -lm (dash ell em) to the LDFLAGS line. If you eventually play with dynamic linking, that's -ldl.
If you were to write a graphical program using Gtk+, you'd append `pkg-config --cflags gtk+-3.0` (including the backticks `) to the CFLAGS line, and `pkg-config --libs gtk+-3.0` to the LDFLAGS line, and #include <gtk/gtk.h> to your program.

Related

Using Dynamic library Load returns another result

i have an issue using DLL, i have a code that encrypt strings, buf using dll the result of the function changes.
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cantidad(char *s){
int max=0;
for (int i = 0; s[i] ; i++) {
max=i;
}
return max+1;
}
char* pascal(char *s) {
//char s1[cantidad(s)];
int cuociente;
char *s1=calloc(strlen(s)+1,sizeof(char));
strcpy(s1,s);
if (s == NULL){ //caso que sea nulo.
return NULL;
}
cuociente=cantidad(s)/2;
if(cantidad(s)%2==0){//par
for (int i = 0; i <cuociente-1 ; i++) {
if(i%2==0){ // iteracion impar debido a que esta parte siendo iteracion 1,
s[cuociente-2-i]=s1[cantidad(s)-1-i];
s[cuociente+1+i]=s1[i];
}
if(i%2!=0){// iteracion par
s[cuociente-2-i]=s1[i];
s[cuociente+1+i]=s1[cantidad(s)-1-i];
}
}
}
if(cantidad(s)%2!=0){//impar
for (int k = 0; k <cuociente-1 ; k++) {
if (k%2==0){ //iteracion impar
s[cuociente-2-k]=s1[cantidad(s)-1-k];
s[cuociente+2+k]=s1[k];
}
if (k%2!=0){ //iteracion par
s[cuociente-2-k]=s1[k];
s[cuociente+2+k]=s1[cantidad(s)-1-k];
}
}
}
printf("%s",s);
return s;
}
Using CLion and terminal, if i encrypt "btvenyz tnyvn" the function returns "teytnyz bvvnn" that its the expected result.
But if i use makefile and DLL:
MAKEFILE:
all: shared compile
shared:
gcc -c -Wall -Werror -fpic ./lib/pascal.c
mkdir ./sym
gcc -shared -o ./sym/libpascal.so pascal.o
compile:
mkdir ./bin
gcc -Wall -Werror main.c -o ./bin/hash -ldl
rm -r *.o
clean:
rm -r ./sym ./bin
MAIN WITH DLL:
int main(){
char palabra[256],seq[256];
char (*func_pascal)(char[]);
void *handle_pascal;
char *error;
//PREPARE LIBRARY
handle_pascal= dlopen("../sym/libpascal.so",RTLD_LAZY);
// ERROR
if(!handle_pascal){
fprintf(stderr, "%s \n", dlerror());
exit(EXIT_FAILURE);
}
dlerror();
func_pascal = (char (*)(char[])) dlsym(handle_pascal,"pascal");
error = dlerror();
//ERROR
if(error != NULL){
fprintf(stderr,"%s \n", error);
exit(EXIT_FAILURE);
}
//INPUT
fgets(palabra,256,stdin);
fgets(seq,256,stdin);
printf("STRING: %s\n",palabra);
for (int i = 0; seq[i]; ++i)
{
if (seq[i]=='P')
{
(*func_pascal)(palabra);
printf("ENCRYPTED WORD:%s\n",palabra);
}
}
return 0;
}
Using DLL the output is:
INPUT
btvenyz tnyvn
P
OUTPUT
STRING: btvenyz tnyvn
ynevt
z bnvyntENCRYPTED WORD:ynevt
z bnvynt
Originally there are several encryption codes, where only this one generates error in the output, so I would like to know what I am doing wrong and how to solve it, thank you very much!

Error when compiling C file in GCC (multiple files in one)

The program justifies a string of text. Here is my code (main is justify.c) :
justify.c
#include <string.h>
#include "line.h"
#include "word.h"
#define MAX_WORD_LEN 20
int main(void)
{
char word[MAX_WORD_LEN+2];
int word_len;
clear_line();
for(;;)
{
read_word(word, MAX_WORD_LEN+1);
word_len = strlen(word);
if(word_len ==0)
{
flush_line();
return 0;
}
if (word_len >MAX_WORD_LEN)
word[MAX_WORD_LEN]='*';
if(word_len + 1 > space_remainding())
{
write_line();
clear_line();
}
add_word(word);
}
}
line.c
#include <stdio.h>
#include <string.h>
#include "line.h"
#define MAX_LINE_LEN 60
char line[MAX_LINE_LEN+1];
int line_len=0;
int num_words=0;
void clear_line(void)
{
line[0]='\0';
line_len=0;
num_words=0;
}
void add_word(const char *word)
{
if(num_words>0)
{
line[line_len]= ' ';
line[line_len+1]= '\0';
line_len++;
}
strcat(line,word);
line_len += strlen(word);
num_words++;
}
int space_remainding(void)
{
return MAX_LINE_LEN - line_len;
}
void write_line(void)
{
int extra_spaces, spaces_to_insert, i,j;
extra_spaces= MAX_LINE_LEN - line_len;
for(i=0; i< line_len; i++)
{
if(line[i] != ' ')
putchar(line[i]);
else
{
spaces_to_insert = extra_spaces/ (num_words - 1);
for(j=1; j<=spaces_to_insert +1; j++)
putchar(' ');
extra_spaces -= spaces_to_insert;
num_words--;
}
}
putchar('\n');
}
void flush_line(void)
{
if (line_len > 0)
puts(line);
}
word.c
#include <stdio.h>
#include "word.h"
int read_char(void)
{
int ch= getchar();
if (ch=='\n' || ch == '\t')
return ' ';
return ch;
}
void read_word(char *word, int len)
{
int ch, pos=0;
while((ch=read_char()) == ' ')
;
while(ch != ' ' && ch !=EOF)
{
if (pos<len)
word[pos++]=ch;
ch= read_char();
}
word[pos]= '\0';
}
line.h
#ifndef LINE_H
#define LINE_H
void clear_line(void);
void add_word(const char *word);
int space_remainding(void);
void write_line(void);
void flush_line(void);
#endif // LINE_H
word.h
#ifndef LINE_H
#define LINE_H
void clear_line(void);
void add_word(const char *word);
int space_remainding(void);
void write_line(void);
void flush_line(void);
#endif // LINE_H
When I compile all of them in Code Blocks it gives me no errors. But when I do the same in GCC
gcc -o justify justify.c line.c word.c
I get this:
justify.c:1:1: error: expected identifier or '(' before '<' token
<?xml version="1.0" encoding-"UTF-8" standalone="yes" ?>
I cannot find the error and I'd been staring at this for hours. Please
I'd really appreciate any help I could get.
You are attempting to compile the Codeblocks project file, which should be
called <project_name>.chp in the project directory and is an XML file of the general form:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
...
</Project>
</CodeBlocks_project_file>
Your post does not reveal how you made this strange mistake. It may be that you have broken the project by somehow copying the contents of the .cbp file into justify.c, or by moving the .cbp file to justify.c, or something more obscure.
The five files you have posted if put in the same directory will compile and link without errors
(though not without compiler warnings) with the command.
gcc -o justify justify.c line.c word.c
run in that directory.
Just make sure that the source and header files are saved and have the contents that you expect when you run it. Open and inspect them beforehand with some other editor than Codeblocks.
As a matter of course you should compile with gcc ...-Wall... to enable all warnings and fix any compiler warnings that are issued, as they may mean bugs.
Try to compile with this
gcc -o justify justify.c line.c word.c -I.

Multiple definitions and First defined error

I have written a small C program which is assembled of several files.
When I compile, I get an error for "multiple definitions".
My main.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "general_structs.h"
#define FOREVER for(;;)
#define INPUT_LEN 30
int main()
{
char command[INPUT_LEN];
char *func;
int i;
int t;
FOREVER
{
if(scanf("%s", command) == 1)
{
func = strtok(command, " ");
for(i=0;cmd[i].func != NULL;i++)
{
if(strcmp(func, cmd[i].name) == 0)
{
(*((cmd[i].func)));
t = 1;
}
}
if(t == 1)
{
printf("No such command");
}
}
}
return 0;
}
My mat.c file:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "general_structs.h"
#define LENGTH 100
#define SIXTEEN 16
#define SIZE 4
void read_mat()
{
int i = 0;
int j = 0;
int k = 0;
char tmp_name[LENGTH];
char num_buffer[LENGTH];
char *token;
double num_list[16];
double tmp_num = 0;
scanf("%[^,], %s", tmp_name, num_buffer);
token = strtok(num_buffer, ",");
while(token != NULL)
{
if(strcmp(token, "0") == 0)
{
num_list[i] = 0;
}
else
{
tmp_num = atof(token);
if(tmp_num == 0)
{
printf("Error in parameter: %d\n", (i-1));
break;
}
else
{
num_list[i] = tmp_num;
}
}
i++;
token = strtok(NULL, ",");
}
if(!strcmp(tmp_name, "MAT_A"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[0].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_B"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[1].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_C"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[2].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_D"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[3].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_E"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[4].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_F"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[5].mat[0][i][j] = num_list[k];
k++;
}
}
else
{
printf("No such matrix name.");
}
}
My general_structs.h file:
#define SIZE 4
#define SIZE_NAME 5
#define SIZE_FUNC 10
typedef double matrix[SIZE][SIZE];
matrix MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;
void read_mat(void);
struct
{
char name[SIZE_NAME];
matrix *mat;
} mats[] = {
{"MAT_A", &MAT_A},
{"MAT_B", &MAT_B},
{"MAT_C", &MAT_C},
{"MAT_D", &MAT_D},
{"MAT_E", &MAT_E},
{"MAT_F", &MAT_F},
{"non", NULL}
};
struct
{
char name[SIZE_FUNC];
void (*func)(void);
} cmd[] = {
{"read_mat", read_mat},
{"not_valid", NULL}
};
My make file:
int_loop: my_math.o int_loop.o
gcc -g -ansi -Wall -pedantic my_math.o int_loop.o -o int_loop
int_loop.o : int_loop.c
gcc -c -ansi -Wall -pedantic int_loop.c -o int_loop.o
my_math.o : my_math.c
gcc -c -ansi -Wall -pedantic my_math.c -o my_math.o
I have been trying to solve this issue with various techniques but yet with no success.
The error I recieve is:
gcc -g -Wall -ansi -pedantic main.o mat.o -o mamantest
mat.o:(.data+0x0): multiple definition of `mats'
main.o:(.data+0x0): first defined here
mat.o:(.data+0x70): multiple definition of `cmd'
main.o:(.data+0x70): first defined here
collect2: ld returned 1 exit status
make: *** [mamantest] Error 1
Why does this error occurs? How do I solve this?
Thanks
In the header file you define the variables mats and cmd, meaning both translation units (both source files that includes the header file) will have those defined.
The variables should be defined only in a single place, in a single source file, like
struct mat mats[7] = { ... };
The above defines the array mats, and like I said should be done in only one place.
For the other source file you declare the variables, which can be done in the header file like e.g.
extern struct mat
{
...
} mats[7];
The above declare the variable mats as an array of seven mat structures. It also define the structure so it can be used to e.g. define the array.
After modifications suggested above, the complete header file should look something like
// First header include guards (see https://en.wikipedia.org/wiki/Include_guard)
#ifndef GENERIC_STRUCTS_H
#define GENERIC_STRUCTS_H
#define SIZE 4
#define SIZE_NAME 5
#define SIZE_FUNC 10
typedef double matrix[SIZE][SIZE];
// Declare the variables (note the added use of the extern keyword)
extern matrix MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;
void read_mat(void);
// Define a structure named mat (note added structure tag name)
struct mat
{
char name[SIZE_NAME];
matrix *mat;
};
// Define a structure named command (note added structure tag name)
struct command
{
char name[SIZE_FUNC];
void (*func)(void);
};
// Now declare variables of the previous structures
extern struct mat mats[7];
extern struct command cmd[2];
// End of header include guard
#endif
That header file only declares variables, and can be included in all your source files.
Then in a single source file (for example your main.c file) you do the actual variable definitions:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "general_structs.h"
matrix MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;
struct mat mats[7] = {
{"MAT_A", &MAT_A},
{"MAT_B", &MAT_B},
{"MAT_C", &MAT_C},
{"MAT_D", &MAT_D},
{"MAT_E", &MAT_E},
{"MAT_F", &MAT_F},
{"non", NULL}
};
struct command cmd[2] = {
{"read_mat", read_mat},
{"not_valid", NULL}
};
#define FOREVER for(;;)
#define INPUT_LEN 30
int main()
{
...
}
The important thing you need to learn here is that there is a difference between declaring and defining something.
A declaration is basically telling the compiler that "this thing exists somewhere", and a definition is telling the compiler "this is the thing".
The problem is that unless a thing has already been declared, a definition is also a declaration, and many simply call these combined definitions/declarations just declaration, which muddles the whole concept up a bit.

Undefined reference to a function using argv[1] to pass filename to other function and read data struct

I can't solve the error: undefined reference to lire in function main in proj.c.
collect2: error ld returned 1 exit status
Question structure
Details of question
Code for main functions - allouer (=allocate) and lire (=read) (file is called allocate_plat.c)
proj.c source file - should take filename as argument and read it using function lire
proj.h header file - structure definitions and prototype functions
Makefile - I can't believe this causes the problem but included for completeness
Example txt file to read. For information only
1.This is my first at using multiple source files - the goal is to open a game board for a game like this: http://www.rci-jeux.com/jeux/labychiffres/laby.swf .
I am studying abroad, and have some trouble in technical discussions with the lecturer, and think my understanding of pointers or at least when and where to use * and & is weak - I have already spent some time trying to get the game file passed from the command line of proj.c to allocate_plat.c - I believe this works, but if you spot a mistake please point it out. Code follows - have had guidance for the structures so am confident they are appropriate.
What I have tried - the current situation is the culmination of a few hours ironing out (I hope) bugs with passing the filename argument from proj.c to allocate_plat.c This is the first time I have seen this type of error,and I am not sure where to start.
I have read C++ Undefined reference to function implemented and templated in code and can't see the solution.
2.allocate_plat.c to allocate space and then read the game data (this is by analogy with a matrix data structure used in a weekly assignment, and we have been told we can largely copy that, so it should work, (though for that I only used one source file.)
#include <stdio.h>
#include <stdlib.h>
#include "proj.h"
int allouer(PLATEAU *PLAT, int nl, int nc, int ldep, int cdep, int larr, int carr, int longdem, int sumdem){
int i,succes;
PLAT->grille = (int**)calloc(nl,sizeof(int*));
PLAT->nl = nl;
PLAT->nc = nc;
PLAT->longdem = longdem;
PLAT->sumdem = sumdem;
PLAT->dep.indl = ldep;
PLAT->dep.indc = cdep;
PLAT->arr.indl = larr;
PLAT->arr.indc = carr;
succes = (PLAT->grille != NULL);
for (i=0; succes && i<nl;i++){
PLAT->grille[i]=(int*)calloc(nc,sizeof(int));
succes = (PLAT->grille[i] != NULL);
}
return succes;
}
int lire(char *nom_fichier, PLATEAU *PLAT){
int i,j,succes, c;
PLATEAU jeu;
FILE *fp;
fp = fopen(nom_fichier, "rt");
if(fp==NULL) {
printf("Erreur d'ouverture du fichier\n");
return 0;
}
c = fscanf(fp,"%d %d",&PLAT->nl,&PLAT->nc);//Read first line
if( c != 2){
printf("Erreur de format de fichier\n");
fclose(fp);
return 0;
}
c = fscanf(fp,"%d %d",&PLAT->dep.indl,&PLAT->dep.indc);//Read second line
if( c != 2){
printf("Erreur de format de fichier\n");
fclose(fp);
return 0;
}
c = fscanf(fp,"%d %d",&PLAT->arr.indl,&PLAT->arr.indc);//Read third line
if( c != 2){
printf("Erreur de format de fichier\n");
fclose(fp);
return 0;
}
c = fscanf(fp,"%d %d",&PLAT->longdem,&PLAT->sumdem);//Read fourth line
if( c != 2){
printf("Erreur de format de fichier\n");
fclose(fp);
return 0;
}
//ALLOCATE THE FILE TO THE STRUCT
succes = allouer(PLAT, PLAT->nl, PLAT->nc, PLAT->dep.indl, PLAT->dep.indc, PLAT->arr.indl, PLAT->arr.indc, PLAT->longdem, PLAT->sumdem );
if(succes==0) {
printf("Erreur d'allocation\n");
fclose(fp);
return 0;
}
for(i=0; i< PLAT->nl; i++){
for(j=0; j<PLAT->nc; j++){
c=fscanf(fp, "%d", &PLAT->grille[i][j]);
if(c != 1){
printf("Erreur de format de fichier\n");
fclose(fp);
return 0;
}
}
}
fclose(fp);
return 1;
}
3.Main source file: proj.c
#include <stdio.h>
#include <stdlib.h>
#include "proj.h"
int main(int argc, char* argv[]){
// char nom_fichier[25];
int choix, choix2, succes;
PLATEAU jeu;
if (argc > 1){
char *nom_fichier = argv[1];
lire(nom_fichier, &jeu);
}
return 0;
}
4.My header file: proj.h
#pragma once
typedef struct position_st{//position st is tag for the type: "struct posiition_st"
int indl;//indice of ligne
int indc;//indice of colonne
}POSITION;
typedef struct element_st{
POSITION valeur;
struct element_st *P_suivant;
}ELEMENT;
typedef struct pile_st{
ELEMENT * P_sommet;
} PILE;
//##########PLATEAU STRUCTURE DEFINITION##############
typedef struct plat_st{
//########## INFORMATION INCLUDED IN THE GAME FILES ###################
POSITION dep;//start position
POSITION arr;//finishing position
int longdem;//length of path requested
int sumdem;//total demanded
int nl;//number of rows in grille
int nc;//number of columns in grille
int ** grille;//Playing table
//########## PART TO DO WITH THE CURRENT GAME ###################
int longcur;//current length
int sumcur;//current total
PILE chemin;//the path
}PLATEAU;
//########## FUNCTION PROTOTYPES ########################
//allouer allocates the variables for the game
int allouer(PLATEAU *, int, int, int, int, int, int, int, int);
//lire reads a game from a file
int lire(char *, PLATEAU *);
5.My makefile:
CC = gcc
CFLAGS = -I #-Wall
DEPS = proj.h
OBJ = proj.o allocate_plat.o
%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $# $<
proj: $(OBJ)
gcc $(CFLAGS) -o $# $^
6.Example of the file structure (probably not needed comments would not be in it)
4 4// number of orws and columns in board
1 1//starting coordinates (based at 1)
4 4//ending coordinates (based at 1)
11 96//path length and sum of elements of path required
10 13 2 5//board grid
3 15 9 4
8 6 11 14
7 12 1 16
The error is in the Makefile. With
CFLAGS = -I #-Wall
later
$(CC) $(CFLAGS) -c -o $# $<
will become
gcc -I -c -o proj.o proj.c
...where -c is interpreted as a directory (argument to -I). Did you mean
CFLAGS = -I . #-Wall
?

not able to read data from file using fread

unsigned long int nextOffset, currOffset, len;
nextOffset = read offset from file (eg. 15)
currOffset = read prev offset from file (eg. 0 )
len = nextOffset-currOffset;
str = malloc((int)len);
fread(str,(int)(len)-1,1,dataFile);
str[(int)len]='\0';
rowAddr = ftell(tempDataFile);
fwrite(&rowAddr,sizeof(unsigned long int),1,tempOffsetFile);
fwrite(str,(int)(len)-1,1,tempDataFile);
free(str);
for some reason i'm not able to read from datafile using fread.. i debugged it and what i found was that the striing str is showing random data.. when i did this strlen(str) it shows 1709936.....
what is possibly wrong with this code.. all these files are opeend in binary mode...
What Ptival said.
But the most eggregious problem is that if you allocate n bytes, they are numbered from 0 to n-1. You're setting byte n to zero, and that byte is beyond the end of what you've malloc()ed. So you're probably unintentionally stomping on some other data. C won't keep you from shooting yourself in the foot this way.
Otherwise, based on what you said you needed, there doesn't seem to be much wrong with your code. I fleshed it out a bit, and wrapped it all in a little shell script for easy running. The script:
#!/bin/sh
# pgm 1 generates a binary file.
# pgm 2 dumps a file.
# pgm 3 demos a solution to your problem.
rm -f 1 2 3; \
cat > 1.c <<EOD; cat > 2.c <<EOD; cat > 3.c <<EOD; \
gcc -Wall -Werror 1.c -o 1; \
gcc -Wall -Werror 2.c -o 2; \
gcc -Wall -Werror 3.c -o 3; \
./1; ./2 dataFile.dat; ./3; \
./2 tempDataFile.dat; ./2 tempOffsetFile.dat
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char**argv)
{
unsigned int jndex;
unsigned char buffer[4];
FILE *phyle;
phyle=fopen("dataFile.dat","w+");
if(!phyle)
{
fprintf(stderr,"%s: fopen() fail\n",argv[0]);
exit(1);
}
for(jndex='A';
jndex<='Z';
jndex++
)
{
buffer[0]=jndex;
if(!fwrite(buffer,sizeof(char),1,phyle))
{
fprintf(stderr,"%s: fwrite() fail\n",argv[0]);
}
}
fclose(phyle);
printf("%s complete\n",argv[0]);
return 0;
}
EOD
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char**argv)
{
int jndex;
unsigned char buffer[4];
FILE *phyle;
if(argc!=2)
{
fprintf(stderr,"%s: arg error\n",argv[0]);
exit(1);
}
phyle=fopen(argv[1],"r");
if(!phyle)
{
fprintf(stderr,"%s: fopen fail\n",argv[0]);
exit(1);
}
for(jndex=0;
;
jndex++
)
{
if(!fread(buffer,sizeof(char),1,phyle))
{
break;
}
printf("%02X",buffer[0]);
if(jndex%16==15)
{
printf("\n");
}
else
if(jndex%2==1)
{
printf(" ");
}
}
if(jndex%16)
{
printf("\n");
}
fclose(phyle);
printf("%s %s complete\n",argv[0],argv[1]);
return 0;
}
EOD
#include <stdio.h>
#include <stdlib.h>
FILE *dataPhyle;
FILE *tempDataPhyle;
FILE *tempOffsetPhyle;
void do_one_guy(char *pgmName,
unsigned long int nextOffset,
unsigned long int curOffset
)
{
unsigned long int len;
long rowAddr;
char *str;
len=nextOffset-curOffset;
str=malloc(len);
if(str==NULL)
{
fprintf(stderr,"%s: malloc() fail\n",pgmName);
exit(1);
}
if(fread(str,sizeof(char),len-1,dataPhyle)!=len-1)
{
fprintf(stderr,"%s: fread() fail\n",pgmName);
}
str[len-1]='\0';
printf("record content is %s\n",str);
rowAddr=ftell(tempDataPhyle);
if(fwrite(&rowAddr,1,sizeof(rowAddr),tempOffsetPhyle)!=sizeof(rowAddr))
{
fprintf(stderr,"%s: fwrite(first) fail\n",pgmName);
}
if(fwrite(str,sizeof(char),len-1,tempDataPhyle)!=len-1)
{
fprintf(stderr,"%s: fwrite(second) fail\n",pgmName);
}
free(str);
}
int
main(int argc, char**argv)
{
dataPhyle=fopen("dataFile.dat","r");
if(!dataPhyle)
{
fprintf(stderr,"%s: fopen(\"dataFile.dat\") fail\n",argv[0]);
exit(1);
}
tempOffsetPhyle=fopen("tempOffsetFile.dat","w+");
if(!tempOffsetPhyle)
{
fprintf(stderr,"%s: fopen(\"tempOffsetFile.dat\") fail\n",argv[0]);
exit(1);
}
tempDataPhyle=fopen("tempDataFile.dat","w+");
if(!tempDataPhyle)
{
fprintf(stderr,"%s: fopen(\"tempDataFile.dat\") fail\n",argv[0]);
exit(1);
}
do_one_guy(argv[0],32,16);
do_one_guy(argv[0],12,8);
printf("%s complete\n",argv[0]);
return 0;
}
EOD
The output:
./1 complete
4142 4344 4546 4748 494A 4B4C 4D4E 4F50
5152 5354 5556 5758 595A
./2 dataFile.dat complete
record content is ABCDEFGHIJKLMNO
record content is PQR
./3 complete
4142 4344 4546 4748 494A 4B4C 4D4E 4F50
5152
./2 tempDataFile.dat complete
0000 0000 0F00 0000
./2 tempOffsetFile.dat complete
Hope this helps.

Resources