Related
I have a small program in C that uses the asm() function to use assembly instructions. However, at the time of compilation, it gives me a link error that I can't correct. Indeed as the use of -m32 is necessary in order to use the instruction 'move' I think that it is wrong 'lib' to use.
main.c:
#include <stdio.h>
#include "myJump.h"
static struct ctx_s pctx_buf;
int main() {
int prod1;
prod1 = mul(0);
printf("prod1 = %d\n", prod1);
int prod2;
prod2 = tryIt(&pctx_buf, shintMule, 0);
printf("prod2 = %d\n", prod2);
}
myJump.c:
#include "myJump.h"
#include <stdio.h>
#include <assert.h>
#define CTXMAGIC 0x73478336
static int thr;
static struct ctx_s pctx_buf;
int mul(int d) {
int i;
switch (scanf("%d", &i)) {
case EOF:
return 1;
case 0:
return mul(d + 1);
case 1:
if (i) {
return i * mul(d + 1);
} else {
return 0;
}
}
return 0;
}
int tryIt(struct ctx_s *pctx, funct_t *f, int arg) {
copyBuf(*pctx);
asm("movl %0, %%esp"
:
:"r"(pctx->ctx_esp));
asm("movl %0, %%ebp"
:
:"r"(pctx->ctx_ebp));
pctx->ctx_magic = CTXMAGIC;
return f(arg);
}
void copyBuf(struct ctx_s pctx){
pctx_buf.ctx_ebp = pctx.ctx_ebp;
pctx_buf.ctx_esp = pctx.ctx_esp;
pctx_buf.ctx_magic = pctx.ctx_magic;
}
int throwIt(struct ctx_s *pctx, int r) {
assert( pctx->ctx_magic == CTXMAGIC );
thr = r;
asm("movl %%esp, %0"
:"=r"(pctx->ctx_esp));
asm("movl %%ebp, %0"
:"=r"(pctx->ctx_ebp));
return thr;
}
int shintMule(int d) {
int i;
switch (scanf("%d", &i)) {
case EOF:
return 1;
case 0:
return mul(d + 1);
case 1:
if (i) {
return i * mul(d + 1);
} else {
throwIt(&pctx_buf, 0);
}
}
}
MAKEFILE:
all : main
main : main.o myJump
main.o : main.c myJump.h
gcc -c -O2 -Wall -march='x86-64' main.c
myJump : myJump.o
myJump.o : myJump.c myJump.h
gcc -c -O2 -Wall -march='x86-64' -m32 myJump.c
clean :
rm *.o main
The error after make all:
gcc -c -O2 -Wall -march='x86-64' main.c
gcc -c -O2 -Wall -march='x86-64' -m32 myJump.c
cc myJump.o -o myJump
/usr/bin/ld : architecture i386 du fichier d'entrée « %B » est incompatible avec la sortie ЛZV�U
/usr/bin/ld : /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o : dans la fonction « _start » :
(.text+0x20) : référence indéfinie vers « main »
collect2: error: ld returned 1 exit status
make: *** [<commande interne> : myJump] Erreur 1
EDIT1: pass to 64bits
main.c:
the printf it's for debug
#include <stdio.h>
#include "myJump.h"
int main() {
int prod1;
prod1 = mul(0);
printf("prod1 = %d\n", prod1);
printf("0");
struct ctx_s pctx_buf;
int prod2;
printf("1");
prod2 = tryIt(&pctx_buf, shintMule, 0);
printf("10");
printf("prod2 = %d\n", prod2);
}
myJump.c:
#include "myJump.h"
#include <stdio.h>
#include <assert.h>
#define CTXMAGIC 0xDEADBEAF
static int thr;
static struct ctx_s pctx_buf;
int mul(int d) {
int i;
switch (scanf("%d", &i)) {
case EOF:
return 1;
case 0:
return mul(d + 1);
case 1:
if (i) {
return i * mul(d + 1);
} else {
return 0;
}
}
return 0;
}
int tryIt(struct ctx_s *pctx, funct_t *f, int arg) {
copyBuf(*pctx);
asm("mov %0, %%rsp"
:
:"r"(pctx->ctx_rsp));
asm("mov %0, %%rbp"
:
:"r"(pctx->ctx_rbp));
pctx->ctx_magic = CTXMAGIC;
return f(arg);
}
void copyBuf(struct ctx_s pctx){
pctx_buf.ctx_rbp = pctx.ctx_rbp;
pctx_buf.ctx_rsp = pctx.ctx_rsp;
pctx_buf.ctx_magic = pctx.ctx_magic;
}
int throwIt(struct ctx_s *pctx, int r) {
assert( pctx->ctx_magic == CTXMAGIC );
thr = r;
asm("mov %%rsp, %0"
:"=r"(pctx->ctx_rsp));
asm("mov %%rbp, %0"
:"=r"(pctx->ctx_rbp));
return thr;
}
int shintMule(int d) {
int i;
switch (scanf("%d", &i)) {
case EOF:
return 1;
case 0:
return mul(d + 1);
case 1:
if (i) {
return i * mul(d + 1);
} else {
throwIt(&pctx_buf, 0);
}
}
return 0;
}
im supposed to be able to print all of the countries in the printfunction and pass it to the second if statement, but it doesn't seem to be printing . I know it's the
printf("%s\n", ctryList[numCountries].countryName);
part but i don't know what's wrong with it.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
const int MAX_COUNTRY_NAME_LENGTH = 50;
typedef struct CountryTvWatch_struct {
char countryName[50];
int tvMinutes;
} CountryTvWatch;
void PrintCountryNames(CountryTvWatch ctryList[], int numCountries)
{
int i;
for(i = 0; i < numCountries; i++)
{
printf("%s\n", ctryList[numCountries].countryName);
}
return;
}
int main(void) {
// Source: www.statista.com, 2010
const int NUM_COUNTRIES = 4;
CountryTvWatch countryList[NUM_COUNTRIES];
char countryToFind[MAX_COUNTRY_NAME_LENGTH];
bool countryFound = false;
int i = 0;
strcpy(countryList[0].countryName, "Brazil");
countryList[0].tvMinutes = 222;
strcpy(countryList[1].countryName, "India");
countryList[1].tvMinutes = 119;
strcpy(countryList[2].countryName, "U.K.");
countryList[2].tvMinutes = 242;
strcpy(countryList[3].countryName, "U.S.A.");
countryList[3].tvMinutes = 283;
printf("Enter country name: \n");
scanf("%s", countryToFind);
countryFound = false;
for (i = 0; i < NUM_COUNTRIES; ++i) { // Find country's index
if (strcmp(countryList[i].countryName, countryToFind) == 0) {
countryFound = true;
printf("People in %s watch\n", countryToFind);
printf("%d minutes of TV daily.\n", countryList[i].tvMinutes);
}
}
if (!countryFound) {
printf("Country not found, try again.\n");
printf("Valid countries:\n");
PrintCountryNames(countryList, NUM_COUNTRIES);
}
return 0;
}
the following proposed code:
incorporates the comments to the question
properly checks for I/O errors
lets the user know what countries are available to chose from
is appropriately spaced, both horizontally and vertically, for readability
performs the desired functionality
cleanly compiles
documents why each header file is included
and now the proposed code:
#include <stdio.h> // scanf(), printf()
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <string.h> // strcmp()
#include <stdbool.h> // bool, true, false
#define MAX_COUNTRY_NAME_LENGTH 50
#define NUM_COUNTRIES 4
struct CountryTvWatch_struct
{
char countryName[ MAX_COUNTRY_NAME_LENGTH ];
int tvMinutes;
};
typedef struct CountryTvWatch_struct CountryTvWatch;
// prototypes
void PrintCountryNames( CountryTvWatch ctryList[], int numCountries );
int main(void)
{
// Source: www.statista.com, 2010
CountryTvWatch countryList[NUM_COUNTRIES];
char countryToFind[ MAX_COUNTRY_NAME_LENGTH+1];
strcpy(countryList[0].countryName, "Brazil");
countryList[0].tvMinutes = 222;
strcpy(countryList[1].countryName, "India");
countryList[1].tvMinutes = 119;
strcpy(countryList[2].countryName, "U.K.");
countryList[2].tvMinutes = 242;
strcpy(countryList[3].countryName, "U.S.A.");
countryList[3].tvMinutes = 283;
// let user know what countries are available and how they are spelled
PrintCountryNames(countryList, NUM_COUNTRIES);
printf("Enter country name: \n");
// Note: following statement
// checks for error
// includes a MAX_CHAR modifier that is one less than
// the length of the input field
if( 1 != scanf("%49s", countryToFind) )
{
perror( "scanf failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
bool countryFound = false;
for ( int i = 0; i < NUM_COUNTRIES; ++i )
{ // Find country's index
if (strcmp(countryList[i].countryName, countryToFind) == 0)
{
countryFound = true;
printf("People in %s watch\n", countryToFind);
printf("%d minutes of TV daily.\n", countryList[i].tvMinutes);
break; // exit the search loop early
}
}
if (!countryFound)
{
printf("Country not found, try again.\n");
printf("Valid countries:\n");
PrintCountryNames(countryList, NUM_COUNTRIES);
}
return 0;
}
void PrintCountryNames( CountryTvWatch ctryList[], int numCountries )
{
for( int i = 0; i < numCountries; i++ )
{
printf("%s\n", ctryList[ i ].countryName);
}
}
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.
i have a http client written in c , and in some section i get the time and fill in in buffer , i checked all the input values are valid , but when the function runs it gives segmentation fault , Line number 77 , the line :
strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));
i tested the inputs by debugger and non of them is problematic
After compiling run with this command
./COMPILED_FILE_NAME https://stackoverflow.com/ -d 1:1:1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#define HEADER "-h"
#define TIME_STAMP "-d"
#define PROTOCOL "http://"
#define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT"
#define DEFAULT_PORT 80
#define BUFFER_SIZE 256
typedef struct sockaddr_in sockaddr_t;
void printError(int flag,char * name);
int parseUrl(char * url,char** host,int * portt ,char ** path);
int checkString(const char * date);
int parseDate(char* date,int * day,int * hour,int* minute);
void freeData();
int socketConnect(char * host,int port,char * page,char* requestType , char * dateRequest );
char * host; // the url with out any addititons
char * path; // the path after the url
int main(int argc,char * argv[])
{
time_t now;
now = time(NULL);
char timebuf[BUFFER_SIZE/2];
int headrFlag=0;
int timeFlag=0;
int day=0,hour=0,minute=0;
// char * host;//=(char*)malloc(sizeof(char)*128);
// char * path;//=(char*)malloc(sizeof(char)*128);
char requestType[BUFFER_SIZE];
char dateRequest[BUFFER_SIZE];
bzero(dateRequest,sizeof(dateRequest));
strcpy(requestType,"GET");
int port=DEFAULT_PORT;
if(argc >1 && argc <=5) // the host at least their
{
// checking the incoming args
int i = 1;
for(;i<argc;i++)
{
if(strcmp(argv[i],HEADER)==0)
{
if(headrFlag==0)
{
headrFlag=1;
strcpy(requestType,"HEAD");
}
else
{
printError(0,"");
break;
}
}
else if(strcmp(argv[i],TIME_STAMP)==0)
{
// take the date from the next i , if not there as error
if(timeFlag==0)
{
timeFlag=1;
if(i+1!=argc && parseDate(argv[i+1],&day,&hour,&minute)!=-1) // there is date "thing" after the flag
{
now=now-(day*24*3600+hour*3600+minute*60); //where day, hour and min are the values
//from the input
strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));
//timebuf holds the correct format of the time
sprintf(dateRequest,"If-Modified-Since: %s\n",timebuf);
i++;
continue;
}
else
{
printError(1,"");
}
}
else
{
printError(0,"");
}
printError(0,"");
break;
}
else // the host
{
if(parseUrl(argv[i],&host,&port,&path)<0)
{
printError(1,"");
}
}
}
// connect after every thing is valid
if(host!=NULL){socketConnect(host,port,path,requestType,dateRequest);}else{printError(0,"");}
}
else
{
printError(1,"");
}
return 0;
}
void printError(int flag,char * name)
{
// 0 wrong command usage
//1 wrong input
//2 system call failure
if(flag==0)
{
printf("Usage: client [-h] [-d <time-interval>] <URL>\n");
}
else if(flag==1) // wrong input
{
printf("wring input\n");
}
else // flag ==2 , sys calls
{
perror(name);
}
freeData();
exit(-1);
}
// handles the validation of the url
int parseUrl(char * url,char** host,int * portt ,char ** path)
{
char * det=":";
char * det1="/";
char * port;
char * temp;
char * pathValue;
int pathSize=0,hostSize=0;
int addSize=0;
int portNumber=80;
char * urlToParse;
if((temp=strstr(url,PROTOCOL))!=NULL && temp==url) // checking http://
{
temp=&temp[strlen(PROTOCOL)];
urlToParse=temp;
if(strlen(urlToParse) <=1)
return -1;
}
else
{
return -1;
}
if((temp=strstr(temp,det))!=NULL) // checking port
{
int len1 = strlen(temp)-1; // length from the : to the end
addSize=len1;
char * temp1;
if((temp1=strstr(temp,det1))!=NULL)
{
pathSize= strlen(temp1);
pathValue=temp1;
int portLength= len1-pathSize;
port = (char*)malloc(sizeof(char)*portLength+1);
if(port==NULL)
{
printError(2,"malloc");
}
port[portLength]='\0';
strncpy(port,++temp,portLength);
if(checkString(port)<0)
return -1;
portNumber=atoi(port);
free(port);
addSize=len1+1;
}
}
else // no port
{
temp=urlToParse;
if((temp=strstr(temp,det1))==NULL) // checking filepath
{
return -1;
}
else
{
pathValue=temp;
pathSize=strlen(temp);
addSize=pathSize;
}
}
hostSize=strlen(urlToParse)-addSize;
*host =(char*)malloc(sizeof(char)*(hostSize+1));
if(*host==NULL)
{
printError(2,"malloc");
}
**host=NULL;
* path =(char*)malloc(sizeof(char)*(pathSize+1));
if(*path==NULL)
{
printError(2,"malloc");
}
**path=NULL;
// *path=pathValue;
strcpy(*path,pathValue);
*portt=portNumber;
strncpy(*host,urlToParse,hostSize);
return 0;
}
// checks if the number is valid
int checkString(const char * date)
{
if(date==NULL || strcmp(date,"")==0)
{
return -1;
}
int len = strlen(date);
if(strlen(date)>1 && strncmp(&date[0],"-",1)==0 )
{
date++;
}
while(date && strcmp(date,"")!=0)
{
if(isdigit(*(date++))==0)
{
return -1;
}
}
return 1;
}
// converts from chars to int
int parseDate(char* date,int * day,int * hour,int* minute)
{
char * det=":";
// int days,hours,minutes;
char * dayss = strtok(date,det);
char * hourss = strtok(NULL,det);
char * moinutss = strtok(NULL,det);
if(dayss ==NULL || hourss==NULL||moinutss==NULL)
{
return -1;
}
if(checkString(dayss)<0 || checkString(hourss)<0 || checkString(moinutss)<0 )
return -1;
*day = atoi(dayss);
*hour= atoi(hourss);
*minute=atoi(moinutss);
return 1;
}
// free what ever memory we used
void freeData()
{
if(host !=NULL)
{
free(host);
}
if(path!=NULL)
{
free(path);
}
}
// handles the connection to the server
int socketConnect(char * host,int port,char * page,char* requestType , char * dateRequest )
{
struct in_addr serverIp;
struct hostent * hostt =NULL;
hostt= (struct hostent *)gethostbyname(host);
if(hostt==NULL)
{
freeData();
herror("");
printf("\n");
exit(0);
}
struct addr_in** addresses = (struct in_addr **)hostt->h_addr_list;
int i=0;
// char * ss= inet_ntoa(((struct in_addr*)hostt->h_addr)->s_addr);
// serverIp.s_addr=inet_addr(ss);
struct sockaddr_in packet;
packet.sin_family=AF_INET;
packet.sin_port=htons(port);
packet.sin_addr.s_addr=((struct in_addr*) hostt->h_addr)->s_addr;
int socketFd ;
if((socketFd=socket(PF_INET,SOCK_STREAM,0))<0)
{
printError(2,"socket");
}
if(connect(socketFd,(struct sockaddr*)&packet,sizeof(packet))<0)
{
printError(2,"connect");
}
char buffer[BUFFER_SIZE*4];
char * req = malloc(sizeof(requestType)+sizeof(page)+sizeof(dateRequest)+BUFFER_SIZE);
if(req==NULL)
{
freeData(2,"malloc");
}
sprintf(req,"%s http://%s%s HTTP/1.0\r\n%s\n",requestType,host,page,dateRequest);
printf("HTTP request =\n%s\nLEN = %d\n",req,strlen(req));
send(socketFd,req,strlen(req),0);
int sizeOfResponse=0;
int reading=0 ;
do
{
bzero(buffer,sizeof(buffer));
reading= read(socketFd,buffer,sizeof(buffer),0);
if(reading >0)
{
printf("%s",buffer);
sizeOfResponse=sizeOfResponse+strlen(buffer);
}
}
while(reading>0);
printf("\nTotal received response bytes: %d\n",sizeOfResponse);
close(socketFd);
free(req);
freeData();
}
Root cause: you must #include <time.h>.
The reason is that without a declaration in scope the compiler assumes that gmtime() returns int. In reality it returns struct tm *, and apparently on your platform a pointer is wider than the integer.
You should enable all warnings and pay attention to them.
I'm writing a little program in C, for check the HTML file have the right open and close tags?
but i've got some issues...
i have a file what contains the all possible tags, named tags.txt(those are only the first ones):
<a>
</a>
<abbr>
</abbr>
<area>
</area>
<aside>
</aside>
and i have the htmlfile.html, what I have to check:
<!--#echo var="date" -->
<area>
</area>
<area>
</area>
secondly, i want to replace the comments like this to the sysdate
like , the format is OK i can do it, but the prog puts in the file
this
my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define MAX_SIZE 512
void menu();
void check();
void datumos();
int main(int argc,char *argv[])
{
menu();
return 0;
}
void menu()
{
char menu[MAX_SIZE];
while(1 < 2)
{
printf("\npress a button:\n\n");
printf("\tFile HTML check..............:c\n");
printf("\t<!--#echo var="date" -->...........:d\n");
printf("\tExit:\tCTRL + C\n");
scanf("%s",menu);
if( strcmp(menu,"c") == 0 )
{
check();
}
else if( strcmp(menu,"d") == 0 )
{
datumos();
}
}
}
void check()
{
FILE *htmlfile;
FILE *checkfile;
htmlfile = fopen("htmlfile.html","w");
checkfile = fopen("tags.txt","r");
char line[MAX_SIZE];
char htmlline[MAX_SIZE];
char tags[189][30];
int i=0;
printf("\tcheck__1\n");
while(fgets(line,sizeof(line),checkfile) != NULL)
{
int j;
for(j=0; j<sizeof(line); ++j)
{
tags[i][j]=line[j];
}
++i;
}
printf("\tcheck__2\n");
int k=0; char htmlfiletags[MAX_SIZE][30];
while(fgets(htmlline,sizeof(htmlline),htmlfile) != NULL)
{
char currentline[sizeof(htmlline)];
int j=0;
if( currentline[j]=="<" )
{
while(currentline[j]!=">")
{
htmlfiletags[k][j]=currentline[j];
++j;
}
strcat(htmlfiletags[k][j+1],">");
++k;
}
}
printf("\tcheck__3\n");
int n;
for(n=0; n<sizeof(htmlfiletags); ++n)
{
int j; int howmanytimesnot=0;
for(j=0; j<sizeof(tags); ++j)
{
printf("\tcheck__3/1\n");
if(strcmp(htmlfiletags[n],tags[j])==0)
{
printf("\t%d\n", howmanytimesnot);
++howmanytimesnot;
}
}
printf("\tcheck__3/3\n");
if(!(howmanytimesnot<sizeof(tags)))
{
printf("\tcheck__3/4\n");
printf("the file is not wellformed");
exit (1);
}
}
printf("\tcheck__4\n");
}
void copy_file(const char *from,const char *to)
{
FILE *fr;
FILE *t;
fr = fopen(from,"r");
t = fopen(to,"w");
char line[MAX_SIZE];
char row[MAX_SIZE];
while(fgets(line,sizeof(line),fr) != NULL)
{
sscanf(line,"%s",row);
fprintf(t,"%s\n",row);
}
fclose(fr);
fclose(t);
remove("tempfile.html");
}
void datumos()
{
time_t now = time(NULL);
struct tm *t = localtime(&now);
char date_time[30];
strftime( date_time, sizeof(date_time), "%x_%X", t );
FILE *htmlfile;
FILE *tempfile;
htmlfile = fopen("htmlfile.html","r");
tempfile = fopen("tempfile.html","w");
char line[MAX_SIZE];
//char datecomment[]="<!--#echo var=date -->";
while(fgets(line,sizeof(line),htmlfile) != NULL)
{
if( strcmp(line,"<!--#echo var="date" -->") == 0 )
{
char row[40];
strcpy(row,"<!--");
strcat(row, date_time);
strcat(row,"-->");
printf("%s",row);
fputs(row,tempfile);
}
else
{
fputs(line,tempfile);
}
}
fclose(htmlfile);
fclose(tempfile);
copy_file("tempfile.html","htmlfile.html");
}
it dies in this, in the inner for loop, in the if at the 200th check... i dont know why...
int n;
for(n=0; n<sizeof(htmlfiletags); ++n)
{
int j; int howmanytimesnot=0;
for(j=0; j<sizeof(tags); ++j)
{
printf("\tcheck__3/1\n");
if(strcmp(htmlfiletags[n],tags[j])==0)
{
printf("\t%d\n", howmanytimesnot);
++howmanytimesnot;
}
}
printf("\tcheck__3/3\n");
if(!(howmanytimesnot<sizeof(tags)))
{
printf("\tcheck__3/4\n");
printf("the file is not wellformed");
exit (1);
}
}
Thanks for all reply!!
G
Your code is very complicated, it has several issues.
Here's one:
for(j=0; j<sizeof(tags); ++j)
this will not do what I believe you expect; sizeof(tags) is not the array length of tags (which is declared as char tags[189][30];), it's the total size of the variable. So, this loop will go from 0 to 189 * 30 - 1, i.e. 5669, and thus index way out beyond the end of array.
Also, the idea to use sizeof here in any way is wrong, since the content of tags comes from a file and it thus impossible for the compiler to know. Remember that sizeof is evaluated at compile-time, for expressions like these.
You need to have a variable (e.g. size_t num_tags) that you increment for each line parsed from the tags file, and that you later use to iterate over tags.
Do not use regex, or some kind of string parsing, to parse HTML. Instead search the web, or this site, for a c library to parse html. Then check the parsed HTML file for the tags. This will ease the development a lot as you don't have to parse the files yourself.
i've fixed some things, but
- i still cant check the file's htmltags, dies at the same loop, i've fixed allocation of the tags array
- when in the htmlfile are 2 or more different comments and i'm replacing the comment the program replaces it with the sysdate, but the program copy the another comments badly, like =>
the code is now:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#define MAX_SIZE 512
void menu();
void check();
void datumos();
int main(int argc,char *argv[])
{
menu();
return 0;
}
void menu()
{
char menu[MAX_SIZE];
while(1 < 2)
{
printf("\npress a button:\n\n");
printf("\tFile HTML check..............:c\n");
printf("\t<!--#echo var="date" -->...........:d\n");
printf("\tExit:\tCTRL + C\n");
scanf("%s",menu);
if( strcmp(menu,"c") == 0 )
{
check();
}
else if( strcmp(menu,"d") == 0 )
{
datumos();
}
}
}
void check()
{
FILE *htmlfile;
FILE *checkfile;
htmlfile = fopen("htmlfile.html","r");
checkfile = fopen("tags.txt","r");
char line[MAX_SIZE];
char htmlline[MAX_SIZE];
int i2=0;
printf("\tcheck__1\n");
while(fgets(line,sizeof(line),checkfile) != NULL)
{
++i2;
}
char tags[i2][20];
int i=0;
printf("\tcheck__11\n");
while(fgets(line,sizeof(line),checkfile) != NULL)
{
int j;
for(j=0; j<sizeof(line); ++j)
{
tags[i][j]=line[j];
}
++i;
}
printf("\tcheck__2\n");
int k=0; char htmlfiletags[MAX_SIZE][30];
while(fgets(htmlline,sizeof(htmlline),htmlfile) != NULL)
{
char currentline[sizeof(htmlline)];
int j=0;
if( currentline[j]=="<" )
{
while(currentline[j]!=">")
{
htmlfiletags[k][j]=currentline[j];
++j;
}
strcat(htmlfiletags[k][j+1],">");
++k;
}
}
printf("\tcheck__3\n");
int n;
for(n=0; n<sizeof(htmlfiletags); ++n)
{
int j; int howmanytimesnot=0;
for(j=0; j<sizeof(tags); ++j)
{
//printf("\tcheck__3/1\n");
if(strcmp(htmlfiletags[n],tags[j])==0)
{
// printf("\t%d\n", howmanytimesnot);
++howmanytimesnot;
}
}
printf("\tcheck__3/3\n");
if(!(howmanytimesnot<sizeof(tags)))
{
printf("\tcheck__3/4\n");
printf("the file is not wellformed");
exit (1);
}
}
printf("\tcheck__4\n");
}
void copy_file(const char *from,const char *to)
{
FILE *fr;
FILE *t;
fr = fopen(from,"r");
t = fopen(to,"w");
char line[MAX_SIZE];
char row[MAX_SIZE];
while(fgets(line,sizeof(line),fr) != NULL)
{
sscanf(line,"%s",row);
fprintf(t,"%s\n",row);
}
fclose(fr);
fclose(t);
remove("tempfile.html");
}
void datumos()
{
time_t now = time(NULL);
struct tm *t = localtime(&now);
char date_time[30];
strftime( date_time, sizeof(date_time), "%x_%X", t );
FILE *htmlfile;
FILE *tempfile;
htmlfile = fopen("htmlfile.html","r");
tempfile = fopen("tempfile.html","w");
char line[MAX_SIZE];
char* datecomment="<!--#echo var=\"date\" -->";
while(fgets(line,sizeof(line),htmlfile) != NULL)
{
int i3; int db=0;
for(i3=0; i3<strlen(datecomment); ++i3)
{
if(line[i3]==datecomment[i3])
{
++db;
}
}
if(db==strlen(datecomment))
{
char row[30];
strcpy(row,"<!--");
strcat(row, date_time);
strcat(row,"-->\n");
fputs(row,tempfile);
}
else
{
fputs(line,tempfile);
}
}
fclose(htmlfile);
fclose(tempfile);
copy_file("tempfile.html","htmlfile.html");
}
the currentline it's not necessary,and i've fixed the compares too
while(fgets(htmlline,sizeof(htmlline),htmlfile) != NULL)
{
int j=0;
if( htmlline[j]=='<' )
{
while(htmlline[j]!='>')
{
htmlfiletags[k][j]=htmlline[j];
++j;
}
strcat(htmlfiletags[k][j+1],">");
++k;
}
}
-in addition, the another problem to replace only the suitable comments, and dont hurt the different ones still dont work
"so it replaces
<!--#echo var="date" --> to the sysdate, it's ok, but when there are different comments like
<!--#include something -->, it wont be copied back well, in the htmlfile will be only <!--#include"
ideas?