SIGSEGV on strftime (libc.so.6) using gcc (GCC) 5.3.0 - c

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.

Related

How to pass value of names in struct array as reference in C?

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);
}
}

C how to run a loop in the background

I am making a "Clicker-Game". It's my first real game that I'm doing alongside school. I got all of the game code complete but I want to have a loop in the background that adds geldps(money per second) after every second.
I tried threads but I don't really understand it and we won't learn that until next year, so I´m asking, if anyone can either tell me a better way to make a loop in the background that runs independent from the main program, and can just add geldps to geld every second. Thanks.
PS: I am sorry for the German variables. Ask me if you don't know what sth means or anything, and it´s probably not very well organised and everything.
#include <stdio.h>
int geldps=0,geld=0;
int main()
{
int stand=0, oil=0, Mine=0, Bank=0,standzahl=100, Minezahl=500, Bankzahl=1000, oilzahl=10000, Werkzeug=0, Werkzeugzahl=10;
char input, input2;
float faktor;
do
{
system("cls");
faktor=1+Werkzeug/10;
printf("%c%c%c%c%c%c%c%c%c%c%c\n",201,205,205,205,205,205,205,205,205,205,187);
printf(" %d$\n",geld);
printf("%c%c%c%c%c%c%c%c%c%c%c\n",200,205,205,205,205,205,205,205,205,205,188);
printf(" Space to get money\n U to go to Upgrades\n Escape to leave");
input=getch();
if(input==32)
{
geld=geld+faktor;
continue;
}
if(input == 117 || input == 85)
{
system("cls");
do
{
system("cls");
printf(" 0 - Tools(10 for 1 more Money)(%d)(%d$)\n 1 - Lemon Stands(%d)(%d$)\n 2 - Mines(%d)(%d$)\n 3 - Banks(%d)(%d$)\n 4 - Oil Refinerys(%d)(%d$)\nBackspace to go back", Werkzeug, Werkzeugzahl, stand, standzahl, Mine, Minezahl, Bank, Bankzahl, oil, oilzahl);
input2=getch();
if(input2== 48)
{
if(geld<Werkzeugzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",Werkzeugzahl,geld);
system("pause");
continue;
}
geld=geld-Werkzeugzahl;
Werkzeug++;
Werkzeugzahl=Werkzeugzahl+Werkzeugzahl/10;
}
if(input2== 49)
{
if(geld<standzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",standzahl,geld);
system("pause");
continue;
}
geld=geld-standzahl;
stand++;
standzahl=standzahl+standzahl/10;
}
if(input2== 50)
{
if(geld<Minezahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",Minezahl,geld);
system("pause");
continue;
}
geld=geld-Minezahl;
Mine++;
Minezahl=Minezahl+Minezahl/10;
geldps=geldps+1;
}
if(input2== 51)
{
if(geld<Bankzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",Bankzahl,geld);
system("pause");
continue;
}
geld=geld-Bankzahl;
Bank++;
Bankzahl=Bankzahl+Bankzahl/10;
geldps=geldps+10;
}
if(input2== 52)
{
if(geld<oilzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",oilzahl,geld);
system("pause");
continue;
}
geld=geld-oilzahl;
oil++;
oilzahl=oilzahl+oilzahl/10;
geldps=geldps+100;
}
}
while(input2!=8);
}
}
while(input!=27);
return 0;
}
update: I was procrastinating and cleaned and improved your code. At the end of this answer.
If all you need is for a number to be consistently incremented based on time, add a function that updates a value based on time.
Here's an example showing not only how to do that but also how to compartmentalize your code into functions and how to use better code formatting and variable names.
#include <stdio.h> // printf()
#include <time.h> // time()
#include <stdlib.h> // random()
#include <unistd.h> // sleep()
int updateValue(int lastValue, int amountPerSecond) {
static time_t lastTime = -1;
time_t currentTime = time(NULL);
int newValue = lastValue;
if (lastTime != -1) {
newValue += amountPerSecond * (currentTime - lastTime);
}
lastTime = currentTime;
return newValue;
}
void seedRandom() {
// Don't use this in production code.
srandom(time(NULL));
}
int sleepRandomly() {
const int SLEEP_RANGE_IN_SECS = 5;
// sleep( 0..5 seconds )
int timeToSleep = random() % (SLEEP_RANGE_IN_SECS + 1);
sleep(timeToSleep);
return timeToSleep;
}
int main() {
const int AMOUNT_PER_SECOND = 5;
int value = 0;
// How many times to run the loop
int numCycles = 5;
seedRandom();
// Initialize the updateValue() start time
value = updateValue(value, AMOUNT_PER_SECOND);
while (numCycles--) {
int amountSlept = sleepRandomly();
int newValue = updateValue(value, AMOUNT_PER_SECOND);
printf("Slept %d seconds.", amountSlept);
printf("Value updated: %10d + (%d secs * %4d amount/secs) = %10d\n",
value, amountSlept, AMOUNT_PER_SECOND, newValue);
value = newValue;
}
return 0;
}
Cleaned up version of your code, and then I just kept improving it.
#include <stdio.h> // printf()
#include <string.h> // strlen()
#include <stdarg.h> // vsnprintf()
#include <unistd.h> // STDIN_FILENO
#include <sys/time.h> // gettimeofday()
#include <time.h>
#include <termios.h>
#include <errno.h>
#include <signal.h>
// TODO: convert the menus to tables:
// key - desc count cost effect
// TODO: add all income sources in a list so it's easy to add more
// without changing code
// TODO: the current pricing is off
// TODO: convert to C++ so we can use classes
// TODO: only use one menu, it's nicer to use
// one global value so we can ensure that we restore
// stdin's terminal settings
struct termios g_oldStdinTermios;
int g_keepGoing = 1;
typedef struct {
int count;
int zahl;
int zahlIncrement;
int geldPerSecondIncrement;
} IncomeSource;
typedef struct {
char lastMessage[100];
// try to avoid global variables, pass them instead
// one variable per line
int geld;
int geldPerSecond;
int geldPerClick;
IncomeSource werkzeug;
IncomeSource stand;
// Use consistent capitalization: sound be "mine"
IncomeSource mine;
IncomeSource bank;
IncomeSource oil;
} Values;
void setLastMessage(Values *values, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
(void) vsnprintf(values->lastMessage, sizeof(values->lastMessage), fmt, ap);
va_end(ap);
}
void clearLastMessage(Values *values) {
// clear lastMessage after valid choice
values->lastMessage[0] = '\0';
}
void initializeValues(Values *values) {
clearLastMessage(values);
// use spaces around assignment and operators
values->geldPerSecond = 0;
values->geld = 10000;
// count, cost, cost increment (1/n), geldPerSecond increment
values->werkzeug = (IncomeSource){0, 10, 10, 0};
// BUG: number of stands doesn't increase geld per second
// or geld per click
values->stand = (IncomeSource){0, 100, 10, 0};
values->mine = (IncomeSource){0, 500, 10, 1};
values->bank = (IncomeSource){0, 1000, 10, 10};
values->oil = (IncomeSource){0, 10000, 10, 100};
values->geldPerClick = 1 + values->werkzeug.count / 10;
}
void clearScreen() {
// use ANSI escape sequences
const char *ANSI_MOVE_TO_1_1 = "\x1B[1;1H";
const char *ANSI_CLEAR_SCREEN = "\x1B[2J";
printf("%s%s", ANSI_CLEAR_SCREEN, ANSI_MOVE_TO_1_1);
}
char upcase(char c) {
if (c < 'a' || c > 'z') {
return c;
}
return 'A' + (c - 'a');
}
void setNonBlockingBufferingStdinTermios() {
struct termios new_;
tcgetattr(STDIN_FILENO, &g_oldStdinTermios);
new_ = g_oldStdinTermios;
new_.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &new_);
}
void restoreStdinTermios() {
tcsetattr(STDIN_FILENO, TCSANOW, &g_oldStdinTermios);
}
long getElapsedTimeInMs(struct timeval *start) {
struct timeval now;
gettimeofday(&now, NULL);
// in microseconds
long elapsed = ((now.tv_sec - start->tv_sec) * 1000000
+ now.tv_usec - start->tv_usec);
return elapsed / 1000;
}
char getCharacter() {
struct timeval start;
gettimeofday(&start, NULL);
char input = -1;
while (read(STDIN_FILENO, &input, 1) == -1
&& errno == EAGAIN
&& getElapsedTimeInMs(&start) < 500) {
}
return upcase(input);
}
void updateGeld(Values *values) {
static time_t lastTime = -1;
time_t currentTime = time(NULL);
if (lastTime != -1) {
values->geld += values->geldPerSecond * (currentTime - lastTime);
}
lastTime = currentTime;
}
void printHeader(Values *values) {
const char *UPPER_LEFT = "\u2554";
const char *UPPER_RIGHT = "\u2557";
const char *LOWER_LEFT = "\u255a";
const char *LOWER_RIGHT = "\u255d";
const char *HORIZONTAL = "\u2550";
const char *VERTICAL = "\u2551";
updateGeld(values);
// Automatically expand the box as the size
// of geld grows.
const int BORDER_WIDTH = 3;
char geldStr[20];
snprintf(geldStr, sizeof(geldStr), "$ %d", values->geld);
// Move code used more than once into its own function
clearScreen();
printf("%s", UPPER_LEFT);
for (int i = 0; i < (2 * BORDER_WIDTH + strlen(geldStr)); i++) {
printf("%s", HORIZONTAL);
}
printf("%s\n", UPPER_RIGHT);
// use spaces around commas
printf("%s %s %s %s\n",
VERTICAL, geldStr, VERTICAL, values->lastMessage);
printf("%s", LOWER_LEFT);
for (int i = 0; i < (2 * BORDER_WIDTH + strlen(geldStr)); i++) {
printf("%s", HORIZONTAL);
}
printf("%s\n", LOWER_RIGHT);
}
void upgrade(Values *values, IncomeSource *source) {
if (values->geld < source->zahl) {
setLastMessage(values, "Not enough money(%d/%d$)",
source->zahl, values->geld);
return;
}
clearLastMessage(values);
values->geld -= source->zahl;
source->count++;
source->zahl += source->zahl / source->zahlIncrement;
values->geldPerSecond += source->geldPerSecondIncrement;
}
char getUpgradeInput(Values *values) {
clearScreen();
printHeader(values);
printf(" 0 - Tools(10 for 1 more Money)(%d)(%d$)\t\t+%d/click\n",
values->werkzeug.count, values->werkzeug.zahl, values->geldPerClick);
printf(" 1 - Lemon Stands(%d)(%d$)\t\t\t+%d/sec\n",
values->stand.count, values->stand.zahl,
values->stand.count * values->stand.geldPerSecondIncrement);
printf(" 2 - Mines(%d)(%d$)\t\t\t\t+%d/sec\n",
values->mine.count, values->mine.zahl,
values->mine.count * values->mine.geldPerSecondIncrement);
printf(" 3 - Banks(%d)(%d$)\t\t\t\t+%d/sec\n",
values->bank.count, values->bank.zahl,
values->bank.count * values->bank.geldPerSecondIncrement);
printf(" 4 - Oil Refinerys(%d)(%d$)\t\t\t+%d/sec\n",
values->oil.count, values->oil.zahl,
values->oil.count * values->oil.geldPerSecondIncrement);
printf(" Q - Back to main menu\n");
printf("> ");
fflush(stdout);
return getCharacter();
}
void upgradeLoop(Values *values) {
char input = ' ';
while (input != 'Q' && g_keepGoing) {
input = getUpgradeInput(values);
switch (input) {
case '0':
upgrade(values, &values->werkzeug);
values->geldPerClick = 1 + values->werkzeug.count / 10;
break;
case '1':
upgrade(values, &values->stand);
break;
case '2':
upgrade(values, &values->mine);
break;
case '3':
upgrade(values, &values->bank);
break;
case '4':
upgrade(values, &values->oil);
break;
case 'Q':
break;
default:
break;
}
}
}
char getMainInput(Values *values) {
printHeader(values);
// make this easier to read in the code...
printf(" _ - [Space] get money\n");
printf(" U - Upgrades\n");
printf(" Q - Quit\n");
printf("> ");
fflush(stdout);
return getCharacter();
}
void mainLoop(Values *values) {
char input = ' ';
// while..do is easier to read and understand than do..while
while (input != 'Q' && g_keepGoing) {
// Encapsulate code in functions to make your program's logic
// easier to follow
input = getMainInput(values);
// Use a switch statement here and use character values
// rather than integers
switch (input) {
case ' ':
values->geld += values->geldPerClick;
clearLastMessage(values);
break;
case 'U':
upgradeLoop(values);
clearLastMessage(values);
case 'Q':
break;
default:
break;
}
};
}
void sigintHandler(int signal) {
printf("SIGINT received, cleaning up.\n");
restoreStdinTermios();
g_keepGoing = 0;
}
int main() {
Values values;
initializeValues(&values);
setNonBlockingBufferingStdinTermios();
signal(SIGINT, sigintHandler);
mainLoop(&values);
restoreStdinTermios();
return 0;
}

pointer when I try to initialize in c

typedef struct Email
{
char domain [128];
char local [128];
} Email ;
Email email_in(char s[])
{
Email *result ;
int c=0;
for(c=0;c<128;c++)
{
result->domain[c]='\0';
result->local[c]='\0';
}
char *ss = s;//PG_GETARG_CSTRING(0);
//result = 0;
int i,j, ind1=0, x=0 , dot=0;
int length= strlen(ss);
for(i=0; i<length;i++)
{
if(ss[i]<='Z' && ss[i]>='A' )
{
ss[i]=ss[i]+32;
}
}
;
if ( ((ss[0]<'a') || (ss[0]>'z')) )
{
if((ss[0]<'A') || (ss[0]>'Z'))
perror("Error printed by perror=1");
}
else
{
for ( i=0;i<length;i++)
{
if (ss[i]=='#')
{
result->local[i]=ss[i];
ind1=i+1;
break;
}
else
if(ss[i]=='-' || ss[i]=='.')
if(ss[i-1]=='-' || ss[i-1]=='.')
{
perror("Error printed by perror=4 ");
}
if ( ((ss[i]<'a') || (ss[i]>'z') )&&((ss[i]<'0')||(ss[i]>'9')) )
{
if(((ss[i]<'A') || (ss[i]>'Z')) &&(ss[i]!='-') &&(ss[i]!='.') )
{
printf("%c \n",ss[i]);
perror("Error printed by perror=2");
}
}
if(ss[i]!='#')
result->local [i]=ss[i];
}
for ( j=ind1;j<length;j++)
{
if(ss[j]=='.')
dot= dot+1;
if(ss[j]=='-' || ss[j]=='.')
if(ss[j-1]=='-' || ss[j-1]=='.')
{
perror("Error printed by perror=6 ");
}
if ( (ss[j]<'a') || ((ss[j]>'z' ) ) )
{
if(((ss[j]<'A') || (ss[j]>'Z')) &&(ss[j]!='-') &&(ss[j]!='.') )
perror("Error printed by perror=3 ");
}
result->domain [x]=ss[j];
x=x+1;
}
result->domain[x+1]='\0';
result->domain[x]='\0';
if(dot<1 && dot >2)
perror("invalid domain");
}
return*(result);//PG_RETURN_POINTER(result);
}
void main()
{
char s1[]="tami#openu.ac.il\0";
email_in(s1);
//printf("%s",s1);
}
When it reach result->domain[c]='\0'; its showed me error
"reslut=null"
I need pointer to change in original copy but how to do it?
this function use to validate email address used in PostgreSQL to add new data type
I have zero experience in c or c++
I need help ><
When you do
Email *result ;
you get a pointer to Email but you don't get an Email variable.
In this case you should avoid pointer and use the struct directly. Something like:
#include <stdio.h>
#include <string.h>
typedef struct Email
{
char domain [128];
char local [128];
} Email ;
Email email_in()
{
Email result; // Don't use pointer
strcpy(result.domain, "test_domain");
strcpy(result.local, "test_local");
return result;
}
int main(void) {
Email x=email_in(); // Make the variable x of type Email
printf("%s\n", x.domain);
printf("%s\n", x.local);
return 0;
}
If you prefer working with pointers, you could try something like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Email
{
char domain [128];
char local [128];
} Email ;
Email* email_in()
{
Email* result;
result = malloc(sizeof(Email)); // Allocate memory for an Email and make result point to it
strcpy(result->domain, "test_domain");
strcpy(result->local, "test_local");
return result;
}
int main(void) {
Email* x=email_in(); // Make the variable x of type pointer to Email
printf("%s\n", x->domain);
printf("%s\n", x->local);
free(x); // Free the allocated memory
return 0;
}

How to create AT Commands Parser in C to get the incoming string from USART1?

I want to get the string from USART1 of STM32VLDiscovery (STM32F100X4) and write an AT Command Parser from the string received from USART1.
Below are the concept that I have developed but I am not sure whether it's correct or not.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dosomethinga.h"
void dosomethingB();
void GET_AT_COMMAND(char*);
void takecommand(char *, char *);
int quit;
int main()
{ char buff[15];
char command = '\0';
quit = 0;
while(!quit)
{
printf("Enter your command: ");
scanf("%s", &buff);
if (buff[0] == 'A' && buff[1] == 'T' && buff[2] == '+')
{
GET_AT_COMMAND(buff);
}
}
}
void dosomethingB()
{
printf("dosomethingB called \n");
}
void GET_AT_COMMAND(char *text)
{
int command;
char temp[10] = "";
/*if(text[3] == 'A')
command = 1;
else if(text[3] == 'B')
command = 2;
else if(text[3] == 'Z')
command = 3;
*/
takecommand(text,temp);
if (strcmp(temp, "CALLA") == 0)
command = 1;
if (strcmp(temp, "CALLB") == 0)
command = 2;
if (strcmp(temp, "Z") == 0)
command = 3;
switch(command)
{
case 1:
dosomethingA();
break;
case 2:
printf("herehere.... \n");
dosomethingB();
break;
case 3:
printf("Exiting program.... \n");
quit = 1;
break;
default:
printf("Nothing to do here \n");
}
}
void takecommand(char *mycmd, char *hold)
{
int i;
for(i = 0; i < 10 ; i++)
{
hold[i] = mycmd[i+3];
}
}
Can anyone explain on the steps that I should do? Thanks.
Basicly you should wait an attention "AT" from the input and ignore anything before it.
For example inputs "XYZATZ\r" and "AaatZ\r" should be both handled as a "ATZ" command.
There can also be short pause between 'A' and 'T' (and all other chars of commands too), because human may type those commands.
By the default all commands end to "\r" character.
See more about AT commands from ITU-T documentation. For example from V.250 standard.
There are probably many alternative ways to implement that. The best alternative depends on your needs. If you are going to implement all AT-commands of mobile-terminal, then you should spend more time for the parser. If you want make some test application for few commands, then your implementation could be simple as your provided one.
I have developed this AT command parser, this could be use for reference.
When you get data from UART1 just call this method at_wait_msg() to parse the AT message
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
static const char *AT_HEADER = "AT";
static const char *AT_DEVICE_PROFILE = "DR";
static const char *AT_SET_DEVICE = "SD";
static const char AT_EOF = '\r';
typedef enum {
DeviceProfile,
SetDevice,
Error
} AT_Msg_Type;
typedef struct {
char header[3];
char command[3];
char data[128];
} AT_Msg_Data;
static void at_wait_msg(char text);
static void at_wait_msg_complete(char *text);
static void at_parse_msg(AT_Msg_Data *data);
static AT_Msg_Type at_check_format(AT_Msg_Data *data);
static char _rx_data[512];
static uint16_t _rx_index = 0;
int main()
{
//example data getting from UART1
char text[] = "ATDR\rATSD123456abchelloworld\r1123ATssa\r";
for (int i = 0; i < strlen(text) + 1; i++) {
//to simulate getting data from UART1 byte per byte
at_wait_msg(text[i]);
}
return 0;
}
static void at_wait_msg(char text)
{
_rx_data[_rx_index++] = text;
if (text == AT_EOF) {
at_wait_msg_complete(_rx_data);
_rx_index = 0;
}
}
static void at_wait_msg_complete(char *text)
{
AT_Msg_Data data;
int result = sscanf_s(_rx_data, "%2s%2s%s\r",
data.header, sizeof(data.header),
data.command, sizeof(data.command),
data.data, sizeof(data.data));
if (result >= 2) {
at_parse_msg(&data);
}
}
static void at_parse_msg(AT_Msg_Data *data)
{
AT_Msg_Type type = at_check_format(data);
switch (type) {
case DeviceProfile:
printf("device profile\r\n");
break;
case SetDevice:
printf("settings %s\r\n", data->data);
break;
case Error:
default:
printf("Error\r\n");
break;
}
}
static AT_Msg_Type at_check_format(AT_Msg_Data *data)
{
if (strcmp(data->header, AT_HEADER) != 0) {
return Error;
}
if (strcmp(data->command, AT_DEVICE_PROFILE) == 0) {
return DeviceProfile;
}
if (strcmp(data->command, AT_SET_DEVICE) == 0) {
return SetDevice;
}
return Error;
}

HTML tags check in C

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?

Resources