void main() {
nodLista* LS=NULL;
FILE* F=fopen("asaceva.txt","r");
if(F!=NULL) {
char buffer[100]; int id;float pret;
fscanf(F,"d",&id);
while(!feof(F)) {
fscanf(F,"f",&pret);
fscanf(F,"s",buffer);
Produs* p= creareProdus(id,pret,buffer);
LS=inserareSfarsit(LS,*p);
fscanf(F,"%d",&id);
}
afisareLista(LS);
}
_getch();
}
afisareLista: displays the list
inserareSfarsit: inserts at the end
I don't understand why it doesn't get the data from the txt file. Can you explain why?
There are a couple of issues in your code:
main not returning integer.
not using fscanf consistently and correctly with placeholders.
you are not checking the return value of fscanf for failure.
NULL should be replaced with nullptr if you have C++11 support available.
The correct code should be like this:
int main() {
nodLista* LS=NULL;
FILE* F=fopen("asaceva.txt","r");
if(F!=NULL) {
char buffer[100]; int id;float pret;
if (!fscanf(F,"%d",&id))
cout << "Error happened: " << ferror(F) << ", error string: " << strerror(errno) << endl;
while(!feof(F)) {
if (!fscanf(F,"%f",&pret))
cout << "Error happened: " << ferror(F) << ", error string: " << strerror(errno) << endl;
if (!fscanf(F,"%s",buffer))
cout << "Error happened: " << ferror(F) << ", error string: " << strerror(errno) << endl;
Produs* p= creareProdus(id,pret,buffer);
LS=inserareSfarsit(LS,*p);
if (!fscanf(F,"%d",&id))
cout << "Error happened: " << ferror(F) << ", error string: " << strerror(errno) << endl;
}
afisareLista(LS);
}
_getch();
return 0;
}
Related
I am writing a config for my program. This config is stored in json format using nlohman json. I am using std::fstream to write json object to file. All was fine, but after some moment my program stopped writing to file.
Here is a minimal reproducible example:
#include <iostream>
#include <nlohmann/json.hpp>
#include <fstream>
#include <iomanip>
bool load(std::fstream &config_fs) {
if (config_fs) {
try {
nlohmann::json json;
config_fs >> json;
std::cout << json << std::endl;
return true;
} catch (std::exception &e) {
std::cout << "54 " << (bool)config_fs << std::endl; // 1
std::cout << "Cannot load config: " << e.what() << std::endl;
return false;
}
}
std::cout << "Cannot load config because file is not open" << std::endl;
return false;
}
bool save(std::fstream &config_fs) {
std::cout << "37 " << (bool)config_fs << std::endl;
if (config_fs) {
nlohmann::json json{{"test", 42}};
std::cout << "39 " << (bool)config_fs << " " << config_fs.is_open() << " " << strerror(errno) << std::endl;
config_fs << std::setw(4) << json << std::endl;
std::cout << "41 " << (bool)config_fs << " " << config_fs.is_open() << " " << strerror(errno) << std::endl;
return true;
}
std::cout << "Cannot save config because file is not open" << std::endl;
return false;
}
int main() {
std::string config_file = "../config_test.json";
std::fstream config_fs(config_file, std::ios::in | std::ios::out);
if (!config_fs) {
std::cout << "Cannot open configuration file " << config_file << ", creating it" << std::endl;
config_fs.open(config_file, std::ios::out);
if (!config_fs) {
std::cout << "Cannot create config file " << config_file << std::endl;
} else {
config_fs.close();
config_fs.open(config_file, std::ios::in | std::ios::out);
}
}
if(!load(config_fs)) {
std::cout << "Cannot load config from " << config_file << ", putting default values" << std::endl;
std::cout << "21 " << (bool)config_fs << std::endl;
save(config_fs);
}
return 0;
}
And here is output of the programm:
54 1
Cannot load config: [json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal
Cannot load config from ../config_test.json, putting default values
21 1
37 1
39 1 1 Success
41 0 1 Success
It means that fstream closes after my write attempt with Success errno and file stays empty!
I do not know what may cause such a behavior. I also could not find any similar questions and i really confused about that.
Please point me, what can be reason for this problem.
Thank you!
UPD: Exception 'std::ios_base::failure[abi:cxx11]'
what(): basic_ios::clear: iostream error was thrown in output_stream_adapter::write_characters(const CharType* s, std::size_t length) after enabling exceptions for fstream with config_fs.exceptions(std::ios::badbit | std::ios::failbit);
I'm writing a simple graph generator that stores the graphs in a MySQL database.
Here's the output:
Connecting to database...Success!
Checking for unfinished vertices...Completed last n = 7
Creating n8 table...Success!
Notice it doesn't print "Generating..." which is part of the same statement. It freezes just like this with 100% CPU. The table does actually get created in the database.
Also, If I start from n = 1, it runs until n7 and then freezes.
Here's the code (not the entire thing, just this part):
int main()
{
int n = 0;
if (initialize(n)) {
int limit = 8;
if (limit >= n) {
for (; n <= limit; n++) {
stringstream qs;
qs << "CREATE TABLE n" << n << " (idbin TEXT("
<< getLengthOfBinaryByN(n) << ") NOT NULL,vertices INT NOT NULL)";
cout << "Creating n" << n << " table...";
if (runQuery(qs.str())) {
cout << "Success!" << endl
<< "Generating all graphs on " << n << " vertices";
generateGraphs(n);
} else {
cout << "Failed!" << endl;
}
}
} else {
cout << "ERROR: Must be greater than or equal to " << n << endl;
return 1;
}
}
return 0;
}
After some research I found that a "deadlock" may be occurring, but I have no idea how to fix that. Any ideas?
Here's the runQuery function if that helps:
/*
runQuery: runs the sql query, assumes that database connected successfully
Parameters: query
returns a bool
*/
bool runQuery(string query)
{
try {
stmt = con->createStatement();
res = stmt->executeQuery(query);
delete stmt;
} catch (sql::SQLException &e) {
if (e.getErrorCode() != 0 && e.getErrorCode() != 1050) {
cout << "# ERR: SQLException in " << __FILE__
<< "(" << __FUNCTION__ << ") on line " << __LINE__ << endl
<< "# ERR: " << e.what()
<< " (MySQL error code: " << e.getErrorCode()
<< ", SQLState: " << e.getSQLState() << " )" << endl;
return false;
}
return true;
}
return true;
}
By attempting to access the TCPSocket inside my "clientArray" I get a Access Violation error. How would I access it properly?
My header file holds the TCPSocket *clientArray.
public:
TCPsocket *clientArray;
SDLNet_SocketSet aSocketSet;
bool serverOn;
It is defined within my constructor:
clientArray = new TCPsocket[maxsockets];
aSocketSet = SDLNet_AllocSocketSet(maxsockets);
It is accessible within another function of mine (it works here without issue):
void ServerSocket::waitingForConnection() {
std::cout << '\r' << flush << "Players connected: " << playersConnected << ". Listening for connection... ";
TCPsocket newsocket = SDLNet_TCP_Accept(serverSocket);
SDL_Delay(1000);
if (!newsocket){
//std::cout << '\r' << flush << "Listening for connection. ";
//std::cout << SDLNet_GetError() << std::endl;
}
else{
std::cout << '\r' << flush << "Socket (client " << slotnum + 1 << ") created successfully. " << std::endl;
clientArray[slotnum] = newsocket;
int n = SDLNet_TCP_AddSocket(aSocketSet, newsocket);
if (n < 0){
std::cout << "Client " << slotnum + 1 << " failed to connect. " << std::endl;
}
else{
char text[10];
std::cout << "Client " << slotnum + 1 << " added to client array successfully." << std::endl;
serverMessage(slotnum, "2 You are successfully connected to the server.");
std::cout << "Sent connection validation to Client " << slotnum + 1 << "." << endl;
std::cout << "Allocating player " << slotnum + 1 << " with player number ." << endl;
serverData(slotnum, '5', slotnum+1);
//ACCESSING IT HERE WITHOUT ISSUE
SDLNet_TCP_Recv(clientArray[slotnum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
slotnum++;
}
//SDLNet_TCP_Close(newsocket);
//SDLNet_TCP_Close(serverSocket);
//code here
}
}
However later on when I try to access it via another function, I get an Access Violation Error :
Unhandled exception at 0x00AED839 in Server.exe: 0xC0000005: Access violation reading location 0x0000000C.
I am calling the problematic function from my Game's Update function as following:
void Game::Update(){
while (g_playersConnected == 2)
{
printGrid();
serverSocket->waitForPlayer((playerTurn-1));
changeTurn();
system("pause");
}
//cout << "Game's Update is running" << endl;
};
This is my other function that is attempting to access the array :
void ServerSocket::waitForPlayer(int playerNum)
{
cout << "Waiting for player " << playerNum + 1 << " (In array : " << playerNum << ")." << endl;
char text[10];
SDLNet_TCP_Recv(clientArray[playerNum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
}
I have not set up Copy constructors or assignment operators and my destructors are just empty blocks at the moment.
ServerSocket::~ServerSocket(){}
Which direction should I go towards solving this issue?
All the best
This question already has answers here:
Passing a char pointer array to a function
(2 answers)
Closed 8 years ago.
Note 1: I am not looking for different solutions to the problem at hand. I'm curious about what actually is happening here.
Note 2: I'm doing this in c++ context, but am assuming that this also applies to C, hence the C tag. (apart from the representation of a null pointer)
This is about c-strings and access to original from a function. I'll use argv and argc to illustrate that the array should be nullptr terminated. I declare them like this:
int argc = 1;
char **argv = (char**) malloc( (argc + 1) * sizeof(char*) );
argv[0] = (char*)"argument 0";
argv[1] = nullptr;
If I declare a function like this: func1(int &f_argc, char **f_argv) I can access all elements inside the function scope, including f_argv[f_argc], which is nullptr, but I cannot modify the original argv to point to a different address as f_argv in the function is a value passed copy of the original pointer. It has a different address in memory.
If I declare the function like this instead: func2(int &f_argc, char ***f_argv), I can access the original argv through *f_argv in the function, but the last element (which should be nullptr) is cut off. This means that if I try to check for the terminating nullptr inside the function, I try to access an element outside the range of the array, resulting in a core dump at runtime.
Q1: Why is f_argv cut off when reaching the nullptr in func2, but not in func1?
Q2: Is there a way to get write access to the original argv from within the function, without removing the terminator?
Edit: (added code to show what I mean)
#include <iostream>
#include <cstring>
void func1(int &f_argc, char **f_argv) {
using std::cout;
using std::endl;
cout << " In function:" << endl;
cout << " argv passed as **f_argv" << endl;
cout << " f_argv = " << f_argv << " , &f_argv = " << &f_argv << endl;
for (int pos = 0; pos < f_argc; pos++) {
if (f_argv[pos] != nullptr) {
cout << " f_argv[" << pos << "] = \"" << f_argv[pos] << "\"" << endl;
} else {
cout << " f_argv is prematurely terminated" << endl;
}
}
if (f_argv[f_argc] == nullptr) {
cout << " f_argv is correctly terminated" << endl;
} else {
cout << " f_argv[" << f_argc << "] = \"" << f_argv[f_argc] << "\"" << endl;
cout << " f_argv is not terminated" << endl;
}
// Intention is to copy argv here, add elements, terminate it with
// nullptr and change original argv to point to copy. This wouldn't
// work in this function, as &f_argv != &argv.
return;
}
void func2(int &f_argc, char ***f_argv) {
using std::cout;
using std::endl;
cout << " In function:" << endl;
cout << " array passed as ***f_argv" << endl;
cout << " f_argc = " << f_argc
<< " , &f_argc = " << &f_argc << endl;
cout << " *f_argv = " << *f_argv
<< " , f_argv = " << f_argv << endl;
for (int pos = 0; pos < f_argc; pos++) {
cout << " about to check: "
<< "if (*f_argv[" << pos << "] != nullptr)" << endl;
if (*f_argv[pos] != nullptr) {
cout << " *f_argv[" << pos << "] = \""
<< *f_argv[pos] << "\"" << endl;
} else {
cout << " *f_argv is prematurely terminated" << endl;
}
}
if (*f_argv[f_argc] == nullptr) {
cout << " *f_argv is correctly terminated" << endl;
} else {
cout << " *f_argv[" << f_argc << "] = \""
<< *f_argv[f_argc] << "\"" << endl;
cout << " *f_argv is not terminated" << endl;
}
// Intention is to copy argv here, add elements, terminate it with
// nullptr and change original argv to point to copy.
return;
}
// --------------------------------------------
int main() {
using std::cout;
using std::endl;
int argc=1;
char **argv = (char**) malloc( (argc + 1) * sizeof(char*) );
argv[0] = (char*)"argument 0";
argv[1] = nullptr;
cout << "Before function call" << endl;
cout << "argv = " << argv << " , &argv = " << &argv << endl;
for (int i = 0; i < argc; i++) {
if (argv[i] != nullptr) {
cout << "argv[" << i << "] = \"" << argv[i] << "\"" << endl;
} else {
cout << "argv is prematurely terminated" << endl;
}
}
if (argv[argc] == nullptr) {
cout << "argv is correctly terminated" << endl;
} else {
cout << "argv[" << argc << "] = \"" << argv[argc] << "\"" << endl;
cout << "argv is not terminated" << endl;
}
// run one of these
//func1(argc, argv);
func2(argc, &argv);
free(argv);
return 0;
}
If running func2, running the program results in a core dump at this line:
if (*f_argv[f_argc] == nullptr) {
The subscript operator has higher precedence than the dereference operator. *f_argv[f_argc] is *(f_argv[f_argc]). What you want is (*f_argv)[f_argc].
Since you are using C++, you should consider taking f_argv by reference - void f(int &f_argc, char **& f_argv);.
cI want to select some text with my cursor using the Mark Function from Console, but my code doesn't work ...
CONSOLE_SELECTION_INFO c;
if(GetConsoleSelectionInfo(&c))
{
while((c.dwFlags & CONSOLE_MOUSE_DOWN) == 0) { if(c.dwFlags) cout << c.dwFlags; }
cout << "SelectionAnchor: " << c.dwSelectionAnchor.X << " " << c.dwSelectionAnchor.Y;
cout << "RectangleSelection: " << c.srSelection.Top << " " << c.srSelection.Left << c.srSelection.Bottom << c.srSelection.Right;
}
else cout << "\n\nError: " << GetLastError();
Whatever I'm selecting or I'm doing, always c.dwFlags will be 0 ...