I got this error when compiling my code in visual studio and i need help please :
Error LNK2005: _cmd already defined in complex.obj
I have the following C Files :
### File name: Main.c ###
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "complex.h"
int main()
{
char command[30];
int i;
FOREVER
if (scanf("%s", command) == 1)
{
for (i = 0; cmd[i].func != NULL; i++)/*searcing the relevant function*/
{
if (strcmp(command, cmd[i].name) == 0)
break;
}
if (cmd[i].func == NULL)
printf("Command does not exist: %s\n", command);
else
(*(cmd[i]).func)();
}
}
and this:
### File name: Complex.h ###
#define FOREVER for(;;)
typedef struct complex
{
double real;
double imag;
}complex;
void read_comp(void);
void print_comp(void);
void add_comp(void);
void sub_comp(void);
void mult_comp_real(void);
void mult_comp_img(void);
void mult_comp_comp(void);
void abs_comp(void);
void halt(void);
void empty_string(void);
void stop(void);
struct STR{
char* name;
void(*func)(void);/*pointer to function*/
}cmd[] = {
{ "read_comp", read_comp },
{ "print_comp", print_comp },
{ "add_comp", add_comp },
{ "sub_comp", sub_comp },
{ "mult_comp_real", mult_comp_real },
{ "mult_comp_img", mult_comp_img },
{ "mult_comp_comp", mult_comp_comp },
{ "abs_comp", abs_comp },
{ "halt", halt },
{ "stop", stop }
};
and this:
### File name: Complex.c ###
#include "complex.h"
void stop(void)
{
exit(1);
}
void read_comp(void)
{
printf("read_comp\n");
}
void print_comp(void)
{
printf("print_comp\n");
}
void add_comp(void)
{
printf("add_comp\n");
}
void sub_comp(void)
{
printf("sub_comp\n");
}
void mult_comp_real(void)
{
printf("mult_comp_real\n");
}
void mult_comp_img(void)
{
printf("mult_comp_img\n");
}
void mult_comp_comp(void)
{
printf("mult_comp_comp\n");
}
void abs_comp(void)
{
printf("abs_comp\n");
}
void halt(void)
{
printf("halt\n");
}
void empty_string(void)
{
printf("Empty sting, Please try again\n");
}
We have here some functions that get some parameters as inputs through the command line. The functions implementation is not finished yet.
Please i need help with solving the error.
Since you define the struct cmd in complex.h it will be instantiated in both object files, which then leads to the linking error.
You should define the struct only in one of the two files and declare it extern it in your header file.
This goes into your header file:
struct STR{
char* name;
void(*func)(void);/*pointer to function*/
};
extern struct STR *cmd;
And this for example in complex.c:
struct STR cmd[] = {
{ "read_comp", read_comp },
{ "print_comp", print_comp },
{ "add_comp", add_comp },
{ "sub_comp", sub_comp },
{ "mult_comp_real", mult_comp_real },
{ "mult_comp_img", mult_comp_img },
{ "mult_comp_comp", mult_comp_comp },
{ "abs_comp", abs_comp },
{ "halt", halt },
{ "stop", stop }
};
Related
in order to set a certain variable (MyVariable) to "TRUE" I have to check that a specific function call order was respected within a system.
For example, I have different functions within the system:
uint8 myFunction1()
{
if (...)
{
return NOT_OK
}
else
{
return OK
}
}
uint8 myFunction2()
{
if (...)
{
return NOT_OK
}
else
{
return OK
}
}
uint8 myFunction3()
{
if (...)
{
return NOT_OK
}
else
{
return OK
}
}
MyVariable = TRUE only if:
OK == myFunction1
OK == myFunction2
OK == myFunction3
exactly this call order was respected.
How to check the call order in C but without touching the body of the functions (like setting some flags´etc.)?
I'm still beginner and experimenting with C :)
Thanks!
This is almost certainly an "XY problem". That is, you think saving the call order is the solution to your actual problem, but your actual problem might be to ensure that the functions can't be called in the wrong order in the first place.
So the most correct way to fix this is to remake the program design. Someone mentioned state machines as one solution. Another solution might be something like an array of function pointers (which is a common implementation of state machines).
That being said, you can do something artificial to track the call order, though I wouldn't really recommend it. Example:
#define CALL_ORDER_N 3
const char* call_order [CALL_ORDER_N] = {NULL};
size_t call_order_i = 0;
static void save_call (const char* func)
{
call_order[call_order_i] = func;
call_order_i++;
if(call_order_i == CALL_ORDER_N)
{
call_order_i = 0;
}
}
Where call_order saves the 3 last function calls as pointers to string literals. The function save_call updates this array, by passing the __func__ constant to it from each function. __func__ is guaranteed to work like a static const char[] so this is safe. You'd do something like this:
void myFunction1 (void)
{
save_call(__func__);
...
}
void myFunction2 (void)
{
save_call(__func__);
...
}
void myFunction3 (void)
{
save_call(__func__);
...
}
And then go through the calls to see if they were in the correct order:
static bool is_call_order_ok (void)
{
const char* expected_order [CALL_ORDER_N] =
{
"myFunction1",
"myFunction2",
"myFunction3"
};
size_t co_i = call_order_i;
for(size_t i=0; i<CALL_ORDER_N; i++)
{
if(strcmp(call_order[co_i], expected_order[i])==0)
{
co_i++;
if(co_i == CALL_ORDER_N)
{
co_i = 0;
}
}
else
{
return false;
}
}
return true;
}
Full example:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define CALL_ORDER_N 3
const char* call_order [CALL_ORDER_N] = {NULL};
size_t call_order_i = 0;
static void save_call (const char* func)
{
call_order[call_order_i] = func;
call_order_i++;
if(call_order_i == CALL_ORDER_N)
{
call_order_i = 0;
}
}
static bool is_call_order_ok (void)
{
const char* expected_order [CALL_ORDER_N] =
{
"myFunction1",
"myFunction2",
"myFunction3"
};
size_t co_i = call_order_i;
for(size_t i=0; i<CALL_ORDER_N; i++)
{
if(strcmp(call_order[co_i], expected_order[i])==0)
{
co_i++;
if(co_i == CALL_ORDER_N)
{
co_i = 0;
}
}
else
{
return false;
}
}
return true;
}
void myFunction1 (void)
{
save_call(__func__);
}
void myFunction2 (void)
{
save_call(__func__);
}
void myFunction3 (void)
{
save_call(__func__);
}
int main (void)
{
printf("Call 1,2,3: ");
myFunction1();
myFunction2();
myFunction3();
printf(is_call_order_ok() ? "Ok\n" : "Failed\n");
printf("Call 3,2,1: ");
myFunction3();
myFunction2();
myFunction1();
printf(is_call_order_ok() ? "Ok\n" : "Failed\n");
printf("Call 1,1,1: ");
myFunction1();
myFunction1();
myFunction1();
printf(is_call_order_ok() ? "Ok\n" : "Failed\n");
return 0;
}
The advanced, more professional version of the above, would be to cook together a mini-API with a single function, in order to give private encapsulation to every single variable. The function save_call would then be a multi-purpose function, that can be used to register expected call order, save function calls, as well as verify if the current registered order is ok.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define CALL_ORDER_N 3
static bool save_call (const char* func, bool verify)
{
bool result;
static const char* call_order [CALL_ORDER_N] = {NULL};
static size_t call_order_i = 0;
static const char* expected_order [CALL_ORDER_N] = {NULL};
size_t i = call_order_i;
if(verify) // special case, verify the order
{
for(size_t expected=0; expected<CALL_ORDER_N; expected++)
{
if(call_order[i] == expected_order[expected])
{
i++;
if(i == CALL_ORDER_N)
{
i = 0;
}
}
else
{
return false;
}
}
return true;
}
if(expected_order[i] == NULL) // register order of calls
{
expected_order[i] = func;
result = true;
}
else // save calls
{
call_order[i] = func;
result = false;
}
call_order_i++;
if(call_order_i == CALL_ORDER_N)
{
call_order_i = 0;
}
return result;
}
void myFunction1 (void)
{
if(save_call(__func__, false))
return ;
printf("Execute stuff in %s.\n", __func__);
}
void myFunction2 (void)
{
if(save_call(__func__, false))
return ;
printf("Execute stuff in %s.\n", __func__);
}
void myFunction3 (void)
{
if(save_call(__func__, false))
return ;
printf("Execute stuff in %s.\n", __func__);
}
int main (void)
{
/* register call order: */
myFunction1();
myFunction2();
myFunction3();
printf("Call 1,2,3:\n");
myFunction1();
myFunction2();
myFunction3();
printf(save_call(NULL, true) ? "Ok\n\n" : "Failed\n\n");
printf("Call 3,2,1:\n");
myFunction3();
myFunction2();
myFunction1();
printf(save_call(NULL, true) ? "Ok\n\n" : "Failed\n\n");
printf("Call 1,1,1:\n");
myFunction1();
myFunction1();
myFunction1();
printf(save_call(NULL, true) ? "Ok\n\n" : "Failed\n\n");
return 0;
}
save_call should of course be properly placed in a .h/.c file pair of its own.
There is no direct and portable way. That being said, debuggers are great at breaking execution flow when a function is reached, so you could either use a debugger, or use debugging functions to be warned when the functions are called (unfortunately nothing portable here).
Alternatively, some linkers allow to hide some identifiers and replace them so with custom (and advanced) link options you could replace all call to those functions with calls to custom wrappers. But here again it would only makes sense for a specific implementation so it is not a C way either.
Anyway, this is such an uncommon requirement that I cannot imagine the actual reasonning behind. Maybe you could give more context about your real problem...
For someone of you maybe a simple question:
How to iterate through an array defined in other c source file.
Here is an example:
Source file producer.c
typedef struct
{
int a;
int b;
}values;
values myvalues[] =
{
{ 2, 5 },
{ 10,15},
{ 20,25},
{ 30,35},
{ 40,45},
};
Source file consumer.c
static void iterateLoop (void)
{
int i;
int x = 5;
for (i = 0; i< (sizeof(myvalues)/sizeof(values)); i++)
{
// Do something with myvalues[i].a;
if (x != myvalues[i].b)
{
// something;
else
{
// something;
}
}
}
This can be done by using callbacks? I need here a 3rd source file which acts as an interface or consumer can access directly the producer?
You can do for example this:
You need a header file values.h
typedef struct
{
int a;
int b;
} values;
Source file producer.c
#include "values.h"
values myvalues[] =
{
{ 2, 5 },
{ 10,15 },
{ 20,25 },
{ 30,35 },
{ 40,45 },
};
int nbofvalues = sizeof(myvalues) / sizeof(myvalues[0]);
Source file consumer.c
#include "values.h"
extern values myvalues[];
extern int nbofvalues;
static void iterateLoop(void)
{
int i;
int x = 5;
for (i = 0; i < nbofvalues; i++)
{
// Do something with myvalues[i].a;
if (x != myvalues[i].b)
{
// something;
}
else
{
// something;
}
}
}
I have following simple QML Combobox:
import QtQuick 2.0
import QtQuick.Controls 1.4
import si.mikroelektronika 1.0
Item
{
id: ueStaffSelector
width: 256
height: 96
ComboBox
{
model: uePeopleModel
editable: false
anchors.fill: parent
} // ComboBox
} // Item
As you can see, I assign uePeopleModel to it, which is working ok already in app. Once the app is executed, I get following QML runtime errors:
file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562:
ReferenceError: modelData is not defined
file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562:
ReferenceError: modelData is not defined
file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562:
ReferenceError: modelData is not defined
file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562:
ReferenceError: modelData is not defined
file:///opt/QtOpenSource55/5.5/gcc_64/qml/QtQuick/Controls/ComboBox.qml:562:
ReferenceError: modelData is not defined
Whole application is constructed in main.cpp:
#include <QtQml>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QTimer>
#include "database/uepeoplemodel.h"
#include "core/ueapplicationstatus.h"
#include "core/uedatabaseconnectionstatus.h"
#include "core/uebluetoothmanager.h"
#include "core/uebluetoothprinterconnectionstatus.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
UeApplicationStatus* ueApplicationStatus=new UeApplicationStatus(qApp);
UePeopleModel* uePeopleModel=new UePeopleModel(qApp);
UeBluetoothManager* ueBtManager=new UeBluetoothManager(qApp);
QObject::connect(uePeopleModel,
SIGNAL(ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::UeTypeDatabaseConnectionStatus)),
ueApplicationStatus,
SLOT(ueSlotDatabaseConnectionChanged(UeDatabaseConnectionStatus::UeTypeDatabaseConnectionStatus)));
QObject::connect(ueBtManager,
SIGNAL(ueSignalBtPrinterConnectionChanged(UeBluetoothPrinterConnectionStatus::UeTypeBluetootPrinterConnectionStatus)),
ueApplicationStatus,
SLOT(ueSlotBtPrinterConnectionChanged(UeBluetoothPrinterConnectionStatus::UeTypeBluetootPrinterConnectionStatus)));
engine.rootContext()->setContextProperty("uePeopleModel",
uePeopleModel);
engine.rootContext()->setContextProperty("ueApplicationStatus",
ueApplicationStatus);
engine.rootContext()->setContextProperty("ueBtManager",
ueBtManager);
engine.addImageProvider(QLatin1String("uePeopleModel"),
uePeopleModel);
qmlRegisterUncreatableType<UeDatabaseConnectionStatus>("si.mikroelektronika",
1,
0,
"UeTypeDatabaseConnectionStatus",
"Database Connection Status");
qmlRegisterUncreatableType<UeBluetoothPrinterConnectionStatus>("si.mikroelektronika",
1,
0,
"UeTypeBluetootPrinterConnectionStatus",
"Bluetooth Printer Connection Status");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
uePeopleModel->ueConnectToDatabase();
ueBtManager->ueStartPairing();
//ueApplicationStatus->ueUpdate(uePeopleModel->ueFetchUsers());
return app.exec();
}
Here is also UePeopleModel header, file UePeopleModel.h:
#ifndef UEPEOPLEMODEL_H
#define UEPEOPLEMODEL_H
#include <QImage>
#include <QVariant>
#include <QStringList>
#include <QHash>
#include <QByteArray>
#include <QSqlError>
#include <QSqlQueryModel>
#include <QSqlRecord>
#include <QModelIndex>
#include <QQuickImageProvider>
#include <QByteArray>
#include <QSqlRecord>
#include <QSqlQuery>
#include "../settings/uedefaults.h"
#include "../core/uedatabaseconnectionstatus.h"
#include "../core/uetypes.h"
#include "../core/ueapplicationstatus.h"
#include "../core/ueuserrecord.h"
class UePeopleModel : public QSqlQueryModel,
public QQuickImageProvider
{
Q_OBJECT
private:
QSqlDatabase m_ueDb;
private:
QSqlDatabase ueDatabase() const
{ return this->m_ueDb; }
void ueSetDatabase(const QSqlDatabase& database)
{ this->m_ueDb=database; }
QImage ueImage(const QString& id) const;
public:
UePeopleModel(QObject *parent=0);
~UePeopleModel();
QVariant data(const QModelIndex &index,
int role) const Q_DECL_OVERRIDE;
QImage requestImage(const QString &id,
QSize *size,
const QSize &requestedSize);
UeTypeRoles roleNames() const;
void ueConnectToDatabase();
UeTypeUsers* ueFetchUsers();
public:
static const int ueRoleName=Qt::UserRole+1;
static const int ueRoleImage=Qt::UserRole+2;
static const int ueRolePassword=Qt::UserRole+3;
signals:
void ueSignalDatabaseConnectionChanged(const UeDatabaseConnectionStatus::UeTypeDatabaseConnectionStatus& newStatus);
};
#endif // UEPEOPLEMODEL_H
and its implementation, file UePeopleModel.cpp:
#include "uepeoplemodel.h"
UePeopleModel::UePeopleModel(QObject* parent)
: QSqlQueryModel(parent),
QQuickImageProvider(QQmlImageProviderBase::Image,
QQmlImageProviderBase::ForceAsynchronousImageLoading)
{
emit this->ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::NOT_CONNECTED);
} // default constructor
UePeopleModel::~UePeopleModel()
{
QString connName=this->ueDatabase().connectionName();
this->ueDatabase().close();
this->ueSetDatabase(QSqlDatabase());
this->ueDatabase().removeDatabase(connName);
emit this->ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::NOT_CONNECTED);
} // default destructor
QVariant UePeopleModel::data(const QModelIndex &index,
int role) const
{
switch(role)
{
case ueRoleImage:
{
return QString::number(index.row());
} break; // case
case ueRoleName:
{
return this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME).toString();
} break; // case
case ueRolePassword:
{
return this->record(index.row()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_APPPASSWORD).toString();
} break; // case
default:
{
return QSqlQueryModel::data(index,
role);
} break; // default
} // switch
return QVariant();
} // data
QImage UePeopleModel::ueImage(const QString &id) const
{
return QImage::fromData(this->record(id.toInt()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE).toByteArray(),
"PNG").scaled(UeDefaults::UeGraphics::PEOPLE_IMAGE_WIDTH,
UeDefaults::UeGraphics::PEOPLE_IMAGE_HEIGHT,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
} // ueImage
QImage UePeopleModel::requestImage(const QString &id,
QSize *size,
const QSize &requestedSize)
{
Q_UNUSED(size)
Q_UNUSED(requestedSize);
// if(size)
// {
// *size=QSize(UeDefaults::UeGraphics::PEOPLE_IMAGE_WIDTH,
// UeDefaults::UeGraphics::PEOPLE_IMAGE_HEIGHT);
// } // if
//return this->ueImage(id);
return QImage::fromData(this->record(id.toInt()).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_IMAGE).toByteArray(),
"PNG").scaled(UeDefaults::UeGraphics::PEOPLE_IMAGE_WIDTH,
UeDefaults::UeGraphics::PEOPLE_IMAGE_HEIGHT,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
} // requestImage
UeTypeRoles UePeopleModel::roleNames() const
{
UeTypeRoles roles;
const int iRoleName=UePeopleModel::ueRoleName;
const int iRoleImage=UePeopleModel::ueRoleImage;
const int iRolePassword=UePeopleModel::ueRolePassword;
roles.insert(iRoleName,
"ueRoleName");
roles.insert(iRoleImage,
"ueRoleImage");
roles.insert(iRolePassword,
"ueRolePassword");
return roles;
} // roleNames
void UePeopleModel::ueConnectToDatabase()
{
if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
Qt::CaseInsensitive))
{
this->ueSetDatabase(QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE));
} // if
this->ueDatabase().setHostName(UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
this->ueDatabase().setDatabaseName(UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
this->ueDatabase().setUserName(UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
this->ueDatabase().setPassword(UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);
if(this->ueDatabase().open())
{
this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
this->ueDatabase());
emit this->ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::CONNECTED);
}
else
{
emit this->ueSignalDatabaseConnectionChanged(UeDatabaseConnectionStatus::NOT_CONNECTED);
} // if
} // ueConnectToDatabase
UeTypeUsers* UePeopleModel::ueFetchUsers()
{
UeTypeUsers* users=new UeTypeUsers();
for(int iIndex=0; iIndex<this->record().count(); iIndex++)
{
users->append(new UeUserRecord(this,
this->record(iIndex).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_ID).toString(),
this->record(iIndex).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_NAME).toString(),
this->record(iIndex).value(UePosDatabase::UeTableIndexes::UeTablePeople::INDEX_APPPASSWORD).toString()));
} // for
return users;
} // ueFetchUsers
Why am I getting this error?
You need to tell the combobox which role to use. Try adding textRole: "ueRoleName" to your ComboBox.
After i call printf for the first time to print out the duplicate it then changes it's mammals pointer to giberish. So when it prints inside the second loop the first mammal comes out fine but then the next in the list is lost. Then every time it exits that loop the next duplicate in the list is lost.
void print_list3() {
Duplicate *next=head3.duppointer;
int i,j;
for(i=0;i<list_length3;i++) {
printf("%c %d %f %f\n",next->species,next->number_of,next->location.lat,next->location.lng);
Mammal mam;
mam=*next->mampointer;
for(j=0;j<next->number_of;j++) {
printf(" %f %f %s\n",mam.location.lat,mam.location.lng,mam.observer.id);
if (mam.pointer!=NULL) {
mam=*mam.pointer;
}
}
if (next!=NULL) {
next=next->duppointer;
}
}
}
Edit: Decided to put all of my code in here, maybe it'll be easier for you guys to find the bug. The problem is with function 2.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "navigation.h"
#include "Mainheader.h"
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <math.h>
int list_length1=0;
int list_length2=0;
int list_length3=0;
Observer head1;
Mammal head2;
Duplicate head3;
/*
*
*/
int main(int argc, char** argv) {
int choice=0;
run_menu();
scanf("%d",&choice);
while(choice<1 || choice>4) {
printf("Invalid choice\n");
scanf("%d",&choice);
}
if(choice==1) {
function1();
}
else if(choice==2) {
function2();
}
else if(choice==3) {
function3();
}
else if(choice==4) {
printf("Exiting!");
}
return (EXIT_SUCCESS);
}
void run_menu() {
printf("1 - Display cetacean Mammals fn1\n"
"2 - Display without duplicates fn2\n"
"3 - Display Pods without duplicates fn3\n"
"4 - Exit\n");
}
void function1(){
int i=0;
get_directories();
Mammal *next;
next=head2.pointer;
for(i=0;i<list_length2;i++) {
location_calculator(next);
if (next!=NULL) {
next=next->pointer;
}
}
print_reallist();
}
void function2(){
int i=0;
get_directories();
Mammal *next;
next=head2.pointer;
for(i=0;i<list_length2;i++) {
location_calculator(next);
if (next!=NULL) {
next=next->pointer;
}
}
remove_duplicates();
print_list3();
}
void function3(){
}
char get_directories() {
char file1[256];
char file2[256];
char obsid[5];
TD td;
FILE *file_no1;
FILE *file_no2;
Observer* obs=malloc(sizeof(*obs));
Mammal* mam=malloc(sizeof(*mam));
//printf("Please Enter Observer File Path: ");
//scanf("%s",&file1);
strcpy(file1,"/ceri/homes1/j/jsc12/CS237/Assignment/cetaceans/data/observers_2.txt");
file_no1=fopen(file1, "r");
fscanf(file_no1,"%d%d%d%d%d%d",&td.day,&td.month,&td.year,&td.hour,&td.minute,&td.second);
while(fscanf(file_no1,"%s%lf%lf",obs->id,&obs->location.lat,&obs->location.lng)==3) {
obs->timedate=td;
Observer *new;
new=create_observer(obs->id,obs->location,obs->timedate);
add_observer(new);
}
fclose(file_no1);
//printf("Please Enter Sighting File Path: ");
//scanf("%s",&file2);
strcpy(file2,"/ceri/homes1/j/jsc12/CS237/Assignment/cetaceans/data/sightings_2.txt");
file_no2=fopen(file2, "r");
while(fscanf(file_no2,"%4s %c %lf%lf",&obsid,&mam->species,&mam->bearing,&mam->range)==4) {
Observer* obs2=find_observer(obsid);
mam->observer=*obs2;
Mammal *new;
new=create_mammal(mam->observer,mam->species,mam->bearing,mam->range);
add_mammal(new);
}
fclose(file_no2);
}
Mammal* create_mammal (Observer obs,char spec,double bear,double ran){
Mammal* b=malloc(sizeof *b);
b->observer=obs;
b->species=spec;
b->bearing=bear;
b->range=ran;
b->pointer=NULL;
return b;
}
void add_mammal (Mammal *n){
n->pointer=head2.pointer;
head2.pointer=n;
list_length2++;
}
Duplicate* create_duplicate (Duplicate* d){
Mammal mam;
int i;
location average;
average.lat=0;
average.lng=0;
mam=*d->mampointer;
Duplicate* b;
b=malloc(sizeof *b);
b->species=d->mampointer->species;
b->number_of=d->number_of;
for(i=0;i<d->number_of;i++) {
average.lat+=mam.location.lat;
average.lng+=mam.location.lng;
if (mam.pointer!=NULL) {
mam=*mam.pointer;
}
}
average.lat/=d->number_of;
average.lng/=d->number_of;
b->location=average;
b->mampointer=d->mampointer;
b->duppointer=NULL;
return b;
}
void add_duplicate (Duplicate *n){
n->duppointer=head3.duppointer;
head3.duppointer=n;
list_length3++;
}
Observer* create_observer (char id[5],location locat,TD timdat){
Observer* b=malloc(sizeof *b);
strcpy(b->id,id);
b->location=locat;
b->timedate=timdat;
b->pointer=NULL;
return b;
}
void add_observer (Observer *n){
n->pointer=head1.pointer;
head1.pointer=n;
list_length1++;
}
Observer* find_observer(char id[5]) {
Observer *next=head1.pointer;
int i=0;
while(i<list_length1) {
if(strcmp(id,next->id)==0) {
return(next);
}
next=next->pointer;
i++;
}
}
void location_calculator(Mammal* m) {
double obslat=m->observer.location.lat;
double obslng=m->observer.location.lng;
double rbear=(m->bearing*M_PI)/180;
m->location.lat=obslat+(m->range*cos(rbear))/60;
m->location.lng=obslng+(m->range*sin(rbear)/cos((obslat*M_PI)/180))/60;
}
void print_reallist() {
Mammal *next=head2.pointer;
int i;
printf("|==========|==========|==========|==========|\n");
printf("|%-10s|%-10s|%-10s|%-10s|\n","Longitude","Latitude","Species","Observer");
printf("|==========|==========|==========|==========|\n");
for(i=0;i<list_length2;i++) {
if (next->species=='P') {
printf("|%-10lf|%-10lf|%-10s|%-10s|\n",next->location.lat,next->location.lng,"Porpoise",next->observer.id);
if (next!=NULL) {
next=next->pointer;
}
}
else {
printf("|%-10lf|%-10lf|%-10s|%-10s|\n",next->location.lat,next->location.lng,"Dolphin",next->observer.id);
if (next!=NULL) {
next=next->pointer;
}
}
}
printf("|==========|==========|==========|==========|\n");
}
void remove_duplicates() {
int i,j;
double distance;
Mammal *next=head2.pointer;
for(i=0;i<list_length2-1;i++) {
Mammal *check=next->pointer;
Duplicate d;
d.mampointer=NULL;
d.number_of=0;
for(j=0;j<(list_length2-i)-1;j++) {
distance=great_circle(next->location, check->location);
if(distance<=0.02 && next->species==check->species) {
Mammal a=*next;
Mammal b=*check;
a.pointer=d.mampointer;
d.mampointer=&a;
b.pointer=d.mampointer;
d.mampointer=&b;
d.number_of++;
d.number_of++;
}
printf("%f\n",distance);
if (check!=NULL) {
check=check->pointer;
}
}
if(d.mampointer!=NULL) {
add_duplicate(create_duplicate(&d));
}
if (next!=NULL) {
next=next->pointer;
}
}
}
void print_list3() {
Duplicate *next=head3.duppointer;
int i,j;
for(i=0;i<list_length3;i++) {
printf("%c %d %f %f\n",next->species,next->number_of,next->location.lat,next->location.lng);
Mammal mam;
mam=*next->mampointer;
for(j=0;j<next->number_of;j++) {
printf(" %f %f %s\n",mam.location.lat,mam.location.lng,mam.observer.id);
if (mam.pointer!=NULL) {
mam=*mam.pointer;
}
}
if (next!=NULL) {
next=next->duppointer;
}
}
}
There are many problems for the first sight.
It is C, but would be better to avoid name 'new'. Identifier 'location' is a struct name and variable name too. Functions char get_directories() and Observer * find_observer() do not always return.
There are five malloc() but no free() calls.
I am afraid that such function declarations will not guarantee string size, a simple pointer is passed:
Observer * create_observer ( char id[5], ..
Return value of fscanf is not checked. 6 is expected but returns actually 1, because no proper format provided. Perhaps try "%2d%2d%2d%2d%2d%2d"!
fscanf(file_no1,"%d%d%d%d%d%d",&td.day,&td.month,&td.year,&td.hour,&td.minute,&td.second);
Same problem with observer lines. How should fscanf know where the end of string and/or double is? Try for instance "%4s %lf %lf"!
while(fscanf(file_no1,"%s%lf%lf",obs->id,&obs->location.lat,&obs->location.lng)==3) {
String obsid is not scanned properly at this point (remove address operator &):
while(fscanf(file_no2,"%4s %c %lf%lf",&obsid,&mam->species,&mam->bearing,&mam->range)==4) {
Function find_observer() would correctly return NULL if obsid not found. Pointer should not be used in this case, so please check obs2 first:
Observer* obs2=find_observer(obsid);
mam->observer=*obs2;
Could you provide code parts with example input to reproduce problem and resolve issue? I had to reverse engineer even to get following structures to compile at all:
struct Loc { double lat; double lng; };
struct TD { int year; int month; int day; int hour; int minute; int second; };
struct Observer { char id[1024]; Loc location; TD timedate; Observer * pointer; };
struct Mammal { char species; double bearing; double range; Observer observer; Mammal * pointer; Loc location; };
struct Duplicate { Mammal * mampointer; int number_of; char species; Loc location; Duplicate * duppointer; };
And great_circle( Loc, Loc ) function is missing either. Replaced by planar distance calculation instead of supposed spheric:
double great_circle( Loc p0, Loc p1 ) { return pow( ( p0.lat - p1.lat ), 2.0 ) + pow( ( p0.lng - p1.lng ), 2.0 ); }
Without trying duplicates it runs fine for me after fixing errors above.
Hello I wrote program that should download web page and save it as a file. It does it but partially only. Have anybody encounterd such a problem?
mainwindow.cpp source file:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QNetworkAccessManager>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
netManager = new QNetworkAccessManager;
setFile("myPage");
}
MainWindow::~MainWindow()
{
netManager->deleteLater();
delete ui;
}
void MainWindow::setFile(QString fileURL)
{
QString savePath;
savePath = QString("D:/page.html");
QNetworkRequest request;
request.setUrl(QUrl(fileURL));
reply = netManager->get(request);
file = new QFile;
file->setFileName(savePath);
file->open(QIODevice::WriteOnly);
connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(onProgress(qint64,qint64)));
connect(netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
connect(reply, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
connect(reply, SIGNAL(finished()), this, SLOT(onReplyFinished()));
}
void MainWindow::onProgress(qint64 bRead, qint64 bTotal)
{
qDebug(QString::number(bRead).toLatin1() + " - " + QString::number(bTotal).toLatin1());
}
void MainWindow::onFinished(QNetworkReply *reply)
{
switch (reply->error())
{
case QNetworkReply::NoError:
{
qDebug("File downloaded");
qDebug() << file->size();
}break;
default:
{
qDebug(reply->errorString().toLatin1());
}
}
if(file->isOpen())
{
file->close();
file->deleteLater();
}
}
void MainWindow::onReadyRead()
{
file->write(reply->readAll());
}
void MainWindow::onReplyFinished()
{
if(file->isOpen())
{
file->close();
file->deleteLater();
}
}
mainwindow.h header source file:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QFile>
#include <QNetworkReply>
#include <QNetworkReply>
#include <QStringList>
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void setFile(QString fileURL);
private slots:
void onFinished(QNetworkReply *);
void onProgress(qint64 bRead, qint64 bTotal);
void onReadyRead();
void onReplyFinished();
private:
Ui::MainWindow *ui;
QNetworkAccessManager *netManager;
QNetworkReply *reply;
QFile *file;
};
#endif // MAINWINDOW_H
I tried to solve it myself but after many tries I failed. I'm beginner in QT, so propably I've made a mistake somewhere, and I don't even see it. Can anybody drive me to a proper way to fix the problem?
You should put this:
connect(netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
before:
reply = netManager->get(request);
Works fine after this modification ;)