C++ program crashed when loading array of objects - file

Hello i'm trying to fill an array of objects from a text file in c++ , but i have a crash every time i run the program. I'm i at the right direction here? Is there any more eficient way to do it?
main.cpp
#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include "Item.h"
using namespace std;
void readItems(FILE *products, Item pList[]);
FILE *products;
int main()
{
Item pList[5];
readItems(products,pList);
return 0;
}
void readItems(FILE *products, Item pList[]){
products = fopen("data.txt", "r");
int i = 0;
fread(&pList[i], sizeof(pList), 1, products);
while (!feof(products))
{
i++;
fread (&pList[i], sizeof(pList), 1, products);
}
fclose(products);
}
Item.cpp
#include "Item.h"
#include <stdio.h>
#include <string>
#include <conio.h>
#include <iostream>
using namespace std;
Item::Item()
{
code = 0;
description = "";
price = 0;
}
Item::Item(int code1,string description1,float price1)
{
code = code1;
description = description1;
price = price1;
}
void Item::printData(){
cout<<endl<<"Code:"<<code<<"\tName:"<<description<<"\tPrice:"<<price;
}
void Item::setData(int code1,string description1,float price1){
code = code1;
description = description1;
price = price1;
}
int Item::getCode(){
return code;
}
float Item::getPrice(){
return price;
}
Item::~Item()
{
//dtor
}
The new code is like that , but it prints a set of some chars of the txt file with some weird symbols .
void readItems(FILE *fin, Item list[]){
int i=0;
products = fopen("items.txt","r");
fread(&list[i],sizeof(list[i]),1,products);
list[i].printData();
while(!feof(products) && i<5){
fread(&list[i],sizeof(list[i]),1,products);
list[i].printData();
i++;
}
fclose(products);
}

Try replacing
while (!feof(products))
{
i++;
fread (&pList[i], sizeof(pList), 1, products);
}
with
while (!feof(products) && (i < 5))
{
i++;
fread (&pList[i], sizeof(pList), 1, products);
}

Related

error: dereferencing pointer to incomplete type when trying to use handlers

My code won't build and returns the error of dereferencing when I try to do anything with TournamentKey, like:
TournamentKey new_tournament_key=(TournamentKey)malloc(sizeof(new_tournament_key));
new_tournament_key->tournamentId=tournament_id;
Why is this happening? I think I have added everything, including in the cMake list..
in tournaments.h
#ifndef CHESS_TOURNAMENTS_H
#define CHESS_TOURNAMENTS_H
#include <stdbool.h>
typedef struct tournament_t *Tournament;
typedef struct tournament_key_t *TournamentKey;
MapDataElement copyTournamentData(MapDataElement dataElement);
MapKeyElement copyTournamentKey(MapKeyElement key);
void freeTournamentData(MapDataElement value);
void freeTournamentKey(MapKeyElement key);
int compareTournamentKeys(MapKeyElement key1, MapKeyElement key2);
#endif /* CHESS_TOURNAMENTS_H */
in tournaments.c
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "map.h"
#include "tournaments.h"
#define KEYS_EQUAL 0
#define FIRST_KEY_BIGGER 1
#define SECOND_KEY_BIGGER -1
#define INVALID_KEY 2
struct tournament_t{
int tournamentId;
char* tournamentsPlace;
int numberOfGames;
int tournamentWinner;
int maxGamesPerPlayer;
Map games;
};
struct tournament_key_t{
int tournamentId;
};
MapDataElement copyTournamentData(MapDataElement dataElement)
{
Tournament new_tournament = (Tournament) malloc(sizeof *new_tournament);
if(!new_tournament){
return NULL;
}
new_tournament->tournamentWinner = ((Tournament) dataElement)->tournamentWinner;
new_tournament->numberOfGames = ((Tournament) dataElement)->numberOfGames;
new_tournament->tournamentId = ((Tournament) dataElement)->tournamentId;
new_tournament->maxGamesPerPlayer = ((Tournament) dataElement)->maxGamesPerPlayer;
new_tournament->tournamentsPlace = malloc(strlen(((Tournament) dataElement)->tournamentsPlace)+1);
if (new_tournament->tournamentsPlace) {
memset(new_tournament->tournamentsPlace, '\0', sizeof *new_tournament->tournamentsPlace);
strcpy(new_tournament->tournamentsPlace, ((Tournament) dataElement)->tournamentsPlace);
}
new_tournament->games = mapCopy(((Tournament) dataElement)->games);
return new_tournament;
}
MapKeyElement copyTournamentKey(MapKeyElement key)
{
// TournamentKey temp_key = (TournamentKey)key;
TournamentKey new_key = (TournamentKey)malloc(sizeof *new_key);
if (!new_key){
return NULL;
}
new_key->tournamentId = ((TournamentKey) key)->tournamentId;
return (MapKeyElement)new_key;
}
void freeTournamentData(MapDataElement value)
{
// value is a data element in Tournaments Map i.e. its a tournament.
// First mapDestroy the map of games in the current tournamnet,
// Then free the tournament intself.
Tournament curr_tour = (Tournament)value;
// free(curr_tour->tournamentsPlace);
mapDestroy(curr_tour->games);
free(curr_tour);
}
void freeTournamentKey(MapKeyElement key)
{
free(key);
}
int compareTournamentKeys(MapKeyElement key1, MapKeyElement key2)
{
if(!key1 || !key2)
{
printf("compareTournamentKeys: You have got a NULL key\n");
return INVALID_KEY;
}
TournamentKey new_key1 = (TournamentKey)key1;
TournamentKey new_key2 = (TournamentKey)key2;
if(new_key1->tournamentId > new_key2->tournamentId)
{
return FIRST_KEY_BIGGER;
}
else if(new_key1->tournamentId == new_key2->tournamentId)
{
return KEYS_EQUAL;
}
else
{
return SECOND_KEY_BIGGER;
}
}
and in chess.c
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "map.h"
#include "chess.h"
#include "games.h"
#include "tournaments.h"
#define KEYS_EQUAL 0
#define FIRST_KEY_BIGGER 1
#define SECOND_KEY_BIGGER -1
#define INVALID_KEY 2
struct chess_t{
Map mapOfTournaments;
};
ChessSystem chessCreate()
{
ChessSystem chess_game_system=(ChessSystem)malloc(sizeof(*chess_game_system));
if(!chess_game_system)
return NULL;
chess_game_system->mapOfTournaments=mapCreate(&copyTournamentData,
&copyTournamentKey,
&freeTournamentData,
&freeTournamentKey,
&compareTournamentKeys);
return chess_game_system;
}
int playerGamesPlayed(ChessSystem chess, int tournament_id, int player_id)
{
int num_of_games_played=0;
TournamentKey new_tournament_key=(TournamentKey)malloc(sizeof(new_tournament_key));
new_tournament_key->tournamentId=tournament_id;
Tournament curr_tournament=mapGet(chess->mapOfTournaments, new_tournament_key);
MAP_FOREACH(GameKey, curr_game_key, curr_tournament->games){
if (curr_game_key){
int curr_player_first_id=curr_game_key->firstPlayerId;
int curr_player_second_id=curr_game_key->secondPlayerId;
if(curr_player_first_id == player_id || curr_player_second_id == player_id){
num_of_games_played++;
}
freeGameKey(curr_game_key);
}
}
freeTournamentKey(new_tournament_key);
return num_of_games_played;
}
Why is this happening?
Because struct tournament_key_t { ...} definition is inside tournaments.c, so it's not visible inside chess.c. If you want it to be visible, you could copy it, or you could move it from tournaments.c to tournaments.h, as chess.c does #include "tournaments.h".
typedef struct tournament_key_t *TournamentKey;
Do not use typedef pointers - they are confusing. Prefer to do typedef struct tournament_key_t TournamentKey; and just write the * - your code will be way much clearer and easier.

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

Store filenames in array VC++

I am trying to get all the filenames into an array . But after reading all the filenames the array only have the last filename;
#include <Windows.h>
#include <strsafe.h>
#include <iostream>
int main() {
WIN32_FIND_DATA ffd;
HANDLE handle = INVALID_HANDLE_VALUE;
TCHAR *directory = L"D:/*.*";
LPCWSTR filenames[30] ;
handle = FindFirstFile(directory, &ffd);
int count = 0;
if (handle != INVALID_HANDLE_VALUE) {
OutputDebugString(ffd.cFileName);
do {
filenames[count++] = ffd.cFileName;
OutputDebugString(filenames[count -1]);
} while (FindNextFile(handle, &ffd) != 0);
}
else {
OutputDebugString(L"Nothing to display \n");
}
for (int i = 0; i < 10; i++) {
OutputDebugString(filenames[i]);
}
FindClose(handle);
getchar();
return 0;
}
What is the problem I have in this code ..
Thanks in advance..
LPCWSTR filenames[30];
Above is a character array. It is not an array of strings. It is also too short to contain a filename which can be MAX_PATH long.
Use wchar_t **buf; to create an array of strings, or use std::vector and std::string.
If file handle is invalid then do not close it.
Don't use TCHAR unless it is part of some homework or something. Just use wchar_t for Windows.
#include <Windows.h>
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::wstring> vec;
wchar_t *directory = L"D:/*.*";
WIN32_FIND_DATA ffd;
HANDLE handle = FindFirstFile(directory, &ffd);
if (handle != INVALID_HANDLE_VALUE)
{
do {
vec.push_back(ffd.cFileName);
} while (FindNextFile(handle, &ffd));
FindClose(handle);
}
else
{
OutputDebugString(L"Nothing to display \n");
}
for (unsigned int i = 0; i < vec.size(); i++)
{
OutputDebugString(vec[i].c_str());
OutputDebugString(L"\n");
}
getchar();
return 0;
}

memory returned from malloc function is not saving the data

In the below code I am not getting why the win[] is not getting the values. I have commented on the line in the code below where I am confused.
Pls help me guys.
Am I doing any conceptual mistake.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
void winner(int *speed,int *distance,int rats){
float winner=(float)distance[0]/speed[0];
float time;
float *win=malloc(rats * sizeof(float));
memset(win,0,rats*sizeof(float));
for(int i=0;i<rats;i++) {
time=(float)distance[i]/speed[i];
if(time<=winner) {
win[i]=time; /*Problem is here*/
}
}
for(int i=0;i<rats;i++) {
if(win[i]!=0) {
printf("%d\n",i+1);
}
}
free(win);
}
int main() {
int rats;
int *speed,*distance;
scanf("%d",&rats);
speed=malloc(rats * sizeof(int));
distance=malloc(rats * sizeof(int));
for(int i=0;i<rats;i++) {
scanf("%d",&speed[i]);
}
for(int i=0;i<rats;i++) {
scanf("%d",&distance[i]);
}
winner(speed,distance,rats);
free(speed);
free(distance);
return 0;
}
There are at least 3 problems in your code :
you do not change winner if one rat's time if shorter than first one
you do not initialize win[i] for not winners
you do no use the best time to display winning rats
So instead of :
if(time<=winner){
win[i]=time; /*Problem is here*/
}
you should have :
win[i]=time; // always initialize !
if(time<=winner){
winner = time; // keep best time
}
and then instead of
for(int i=0;i<rats;i++){
if(win[i]!=0){
printf("%d\n",i+1);
}
}
you should have :
for(int i=0;i<rats;i++){
if(win[i] == time){ // display all rats having best time
printf("%d\n",i+1);
}
}

How to omit quotation marks usage in char type?

I'm having a really hard time adjusting function to my needs. First of all look at those three files and notice how I have to call f_texture function in main function in order to make it work:
externs.h
#ifndef EXTERNS_H_
#define EXTERNS_H_
extern char t_about[100];
extern int friction;
extern int f_texture(char* ,char*);
#endif
functionA.c
#include <stdio.h>
#include "externs.h"
int main()
{
f_texture("rough","friction");
printf("Friction: %d\n", friction);
f_texture("rough","t_about");
return 0;
}
functionB.c
#include "externs.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
char t_about[100];
int friction;
int f_texture(char* texture,char* what_is_needed)
{
/*Checking if both values are present*/
assert(what_is_needed);
assert(texture);
/*Static array in order to prevent it's disappearance*/
memset(t_about, '\0', sizeof(t_about));
/*Configuring variables for desired texture*/
if (strcmp(texture, "smooth") == 0)
{
strcpy(t_about, "The surface is perfectly smooth, without any "
"protuberances.\n");
friction = 0;
}
else if (strcmp(texture, "rough") == 0)
{
strcpy(t_about, "Rough bumps can be feeled under my fingertips.\n");
friction = 4;
}
/*In case of absent keyword of desired texture it will crash the program*/
else
{
assert(!what_is_needed);
}
/*Returning desired value*/
if (strcmp(what_is_needed, "t_about") == 0)
{
int i=0;
while (t_about[i] != '\0')
{
printf("%c", t_about[i]);
i++;
}
}
else if (strcmp(what_is_needed, "friction") == 0)
{
return friction;
}
/*In case of absent keyword of desired value it will crash the program*/
else
{
assert(!what_is_needed);
}
return 0;
}
And now here is my question: How to rewrite this code to make it possible to call f_texture function without using quotation marks inside? I mean instead of f_texture("abcd","efgh") just to type f_texture(abcd,efgh). I've noticed that this way it's required just after I've wrote this code.
Thanks in advance.
If you don't want to assign string constants to variables or preprocessor object macros, another option is to use preprocessor function macros, using the stringification feature:
#define call_f_texture(a,b) f_texture(#a,#b)
....
call_f_texture(rough,friction);
The C preprocessor will turn this into
f_texture("rough","friction");
You can also use some macros:
#define ROUGH "rough"
#define FRICTION "friction"
#define T_ABOUT "t_about"
int main()
{
f_texture(ROUGH, FRICTION);
printf("Friction: %d\n", friction);
f_texture(ROUGH, T_ABOUT);
return 0;
}
You can do like this,
char rough[]="rough";
char friction[]= "friction";
and call
f_texture(rough, friction);
char a[MAX] = "rouch";
char b[MAX} = "friction";
int main()
{
f_texture();
...
}
int f_texture()
{
/*Checking if both values are present*/
assert(b);
assert(a);
}
or
int f_texture(char* a,char* b)
{
/*Checking if both values are present*/
assert(b);
assert(a);
...
}
int main()
{
char a[MAX] = "rouch";
char b[MAX} = "friction";
f_texture(a,b);
...
}

Resources