I'm trying to sort by name an array of structs that was read in a binary file but it doesn't compile,
here is what i done:
struct candidate{
char inscr[10];
char name[44];
int year;
int position;
char curse[30];
};
typedef struct candidate Candidate;
Candidate *read_sample_data(const char *filename) {
FILE *fp = fopen(filename, "rb");
if (fp == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", filename);
return 0;
}
fseek(fp, 0, SEEK_END);
size_t sz = ftell(fp);
rewind(fp);
Candidate *aux=(Candidate*)(malloc(sizeof(Candidate)));
Candidate *arr = malloc(sz);
if (arr == 0)
{
fprintf(stderr, "Failed to allocate %zu bytes memory\n", sz);
return 0;
}
printf("%d",sz/sizeof(Candidate));
int i;
for (i = 0; fread(&arr[i], sizeof(Candidate), 1, fp) == 1; i++);
for(i=sz-2;i>=0;i--){ //bubblesort
int j =0;
for(j = 0;j<=i;j++){
if(strcmp( arr[j].inscr, arr[j+1].inscr ) > 0){
aux=arr[j];
arr[j]=arr[j+1];
arr[j+1]=aux;
}
}
}
}
I tested and it reads what i want from the file but i can't sort it.
Ps.: I want to sort it so I can write the sorted array on another binary file.
Not sure how you got your code to compile (did you ignore all the warnings?), but these lines:
aux=arr[j];
arr[j] = arr[j+1];
arr[j+1] = aux;
Should be:
*aux=arr[j];
arr[j] = arr[j+1];
arr[j+1] = *aux;
Related
I need help to read the numbers of a .txt file and put them in an array. But only from the second line onwards. I'm stuck and don't know where to go from the code that i built.
Example of the .txt file:
10 20
45000000
48000000
56000000
#define MAX 50
int main (void){
FILE *file;
int primNum;
int secNum;
int listOfNumers[50];
int numberOfLines = MAX;
int i = 0;
file = fopen("file.txt", "rt");
if (file == NULL)
{
printf("Error\n");
return 1;
}
fscanf(file, "%d %d\n", &primNum, &secNum);
printf("\n1st Number: %d",primNum);
printf("\n2nd Number: %d",secNum);
printf("List of Numbers");
for(i=0;i<numberOfLines;i++){
//Count the number from the second line onwards
}
fclose(file);
return 0;
}
You just need a loop to keep reading ints from file and populate the listOfNumers array until reading an int fails.
Since you don't know how many ints there are in the file, you could also allocate the memory dynamically. Example:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE* file = fopen("file.txt", "rt");
if(file == NULL) {
perror("file.txt");
return 1;
}
int primNum;
int secNum;
if(fscanf(file, "%d %d", &primNum, &secNum) != 2) {
fprintf(stderr, "failed reading primNum and secNum\n");
return 1;
}
unsigned numberOfLines = 0;
// allocate space for one `int`
int* listOfNumers = malloc((numberOfLines + 1) * sizeof *listOfNumers);
// the above could just be:
// int* listOfNumers = malloc(sizeof *listOfNumers);
while(fscanf(file, "%d", listOfNumers + numberOfLines) == 1) {
++numberOfLines;
// increase the allocated space by the sizeof 1 int
int* np = realloc(listOfNumers, (numberOfLines + 1) * sizeof *np);
if(np == NULL) break; // if allocating more space failed, break out
listOfNumers = np; // save the new pointer
}
fclose(file);
puts("List of Numbers:");
for(unsigned i = 0; i < numberOfLines; ++i) {
printf("%d\n", listOfNumers[i]);
}
free(listOfNumers); // free the dynamically allocated space
}
There are a few ways to approach this; if you know the size of the first line, you should be able to use fseek to move the position of the file than use getline to get each line of the file:
int fseek(FILE *stream, long offset, int whence);
The whence parameter can be:
SEEK_SET : the Beginning
SEEK_CUR : the current position
SEEK_END : the End
The other option would to encapsulate the entire file read in a while loop:
char *line = NULL;
size_t linecap = 0;
ssize_t linelen;
int counter = 0;
while((linelen = getline(&line, &linecap, file)) != -1){
if counter == 0{
sscanf(line, "%d %d\n", &primNum, &secNum);
}else{
//Process your line
}
counter++; //This would give you your total line length
}
Participant *readRankingList(const char *filename, int *length) {
length = 0;
int i = 0;
FILE *fp;
fp = fopen(filename, "rb");
Participant *list;
if (fp == NULL) {
fprintf(stderr, "*** open of %s failed ***\n", filename);
return 0;
}
length = fread((void *)list, sizeof(Participant), LIST_LEN, fp);
while (fread(list, sizeof(length), 1, fp) > 0) {
list[i] = list;
i++;
}
free(list);
fclose(fp);
*length = i;
return list;
}
I have a binary file, which I open in this part. Now I want to store it with a dynamic storage.
At the moment I get a
Warning : assignment makes pointer from interfer without a cast
and an
Error: incompatible types when assigning to type Participant from type struct Participant
You must allocate space for the structures with malloc() or calloc(). Seeking to the end of the file will give the number of entries. Reading the entries can be done in a single call to fread.
#include <errno.h>
#include <stdio.h>
#include <string.h>
Participant *readRankingList(const char *filename, int *length) {
Participant *list;
size_t count;
// open the file
FILE *fp = fopen(filename, "rb");
if (fp == NULL) {
fprintf(stderr, "*** open of %s failed: %s ***\n",
filename, strerror(errno));
*length = 0;
return NULL;
}
// get the number of structures
fseek(fp, 0L, SEEK_END);
count = ftell(fp) / sizeof(Participant);
if (count == 0) {
fclose(fp);
*length = 0;
return NULL;
}
// allocate memory for the array of Participants
list = calloc(count, sizeof(*list));
if (list == NULL) {
fclose(fp);
*length = 0;
return NULL;
}
// read the structures, update the length, return the pointer.
rewind(fp);
*length = fread(list, sizeof(Participant), count, fp);
fclose(fp);
return list;
}
I am trying to write a structure to a binary file, the punctuation will be received as a parameter in the insertInFile function, (working with raspberryPi, and store the values of the time reaction with switches). Then I want to read from the file and and store the values on the heap and finally read those values I stored dynamically. I'm having problems with this because either it cannot read properly or it cannot write to the binary file.
typedef enum dificulty {
EASY, MEDIUM, HARD
} Dificulty;
typedef struct player {
char nickname[MAXSIZE];
enum dificulty Dificulty;
float pontuacion;
} Player;
#define LED_CYCLES 5
#define MAX_PLAYERS 2
int insertInFile(float const *const timeReceived, unsigned short *level, char *playerName) {
Player players[MAX_PLAYERS];
int count = 0, i;
FILE *fplayers;
//check if file can be opened
if ((fplayers = fopen("game.bin", "wb")) == NULL) {
fputs("Erro ao abrir ficheiro\n", stderror);
return (-1);
}
//go to the beginning of the file
rewind(fplayers);
//cycle that allows to save int the bin file the struct "Player"
for (i = 0; i < count; i++) {
Player[i].pontuacion = &timeReceived[count];
Player[i].Dificulty = &level;
Player[i].nickname = &playerName;
fwrite(&players, sizeof (Player), count, fplayers);
}
//close the bin file
fclose(fplayers);
return 0;
}
void obtainFromFile() {
Player players;
int count = 0;
FILE *fplayers;
size_t size;
unsigned char *buffer;
int i;
//open file
fp = fopen("game.bin", "rb");
fseek(fp, 0, SEEK_END);
size = ftell(fp); // calculate the size needed
fseek(fp, 0, SEEK_SET);
buffer = (unsigned char *)malloc(size);
if (fplayers == NULL) { // check some error if file == empty
printf("Error\n", stderr);
return (-1);
} else
if (fread(&buffer, sizeof (*buffer), size, fp) != size) // if count of read bytes != calculated size of .bin file -> ERROR
printf("Error\n", stderr);
return (-1);
} else {
for (i = 0; i < size; i++) {
printf("%02x", buffer[i]);
}
}
fclose(fp);
free(buffer);
}
In insertInFile() there is a misunderstanding of the structure use. Writing Player.pontuacion is not right.
To assign a value in an array of struct Player
players[MAX_PLAYERS];, use players[i].Dificulty = (Dificulty)level.
//cicle that allows to save int the bin file the struct "Player"
for (i = 0; i < count; i++) {
players[i].pontuacion = timeReceived[count];
players[i].Dificulty = (Dificulty)(level[count]);
strncpy(players[i].nickname,playerName,MAXSIZE-1);
players[i].nickname[MAXSIZE]='\0';
}
// write count players
fwrite(&(players[0]), sizeof (Player), count, fplayers);
Instead of:
for (i = 0; i < count; i++) {
Player.pontuacion = &timeReceived[count];
Player.Dificulty = &level;
Player.nickname = &playerName;
fwrite(&players, sizeof (Player), count, fplayers);
}
I want to take an array of structs so I can sort it by name and write it on a txt file. But it takes wrong values like strange symbols or numbers. Anyone knows what is wrong?
typedef struct candidato Candidato;
struct candidato {
char inscr[10];
char nome[44];
int periodo;
int posicao;
char curso[30];
};
FILE *fp = fopen(filename, "rb");
if (fp == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", filename);
return ;
}
fseek(fp, 0, SEEK_END);
size_t sz = ftell(fp);
int ncand = sz/sizeof(Candidato);
rewind(fp);
Candidato *arr = malloc(sz);
if (arr == 0)
{
fprintf(stderr, "Failed to allocate %zu bytes memory\n", sz);
return ;
}
printf("%d \n",ncand);
int i;
int cont;
for (i = 0; fread(&arr[i], sizeof(Candidato), 1, fp) == 1; i++){
printf("%s\n",arr[i].nome); //test if it got what I want
}
fclose(fp);
I solved my problem and here's the working code:
FILE *f = fopen (filename, "rb");
if(f==NULL){
printf("Erro na abertura do arquivo. \n");
system("pause");
return;
}
fseek(f, 0, SEEK_END);
int sz = ftell(f);
rewind(f);
Candidato arr[sz/sizeof(Candidato)];
int i;
for (i = 0; fread(&arr[i], sizeof(Candidato), 1, f) == 1; i++) {
printf("%s %i \n",arr[i].nome,arr[i].inscr);
}
I forgot to include the programming language (It should be in the C language).
I need help in doing this program. Sample code will be greatly appreciated.
The program reads a file containing:
a. the number of integers to be sorted, followed by
b. the integers to be sorted (one integer per line) (must be the same with the indicated number of integers).
It will then be sorted out in another text file and a binary file from lowest to highest.
Other specs:
Use dynamic memory allocation
The format in the terminal should be:
./program.out original-file.txt output-file.txt output-file.bin
where program.out is the program itself, original-file.txt is the text file which contains the number of integers to be sorted and the unsorted integers and the output-file.txt and output-file.bin contains the sorted integers.
Error checking:
check if malloc() was returned successfully
the original file will look like:
3 #number of integers to be sorted
3 #the integers-separated by new line
2
1
the output file:
3
1
2
3
Thank you very much in advance :) God Bless!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct tree {
int num, cnt;
struct tree *left, *right;
};
struct tree *add(struct tree *t, int val) {
if (!t) {
if (!(t = malloc(sizeof(struct tree))))
perror("Not enough memory"), exit(-1);
memset(t, 0, sizeof(struct tree));
t->num = val;
++t->cnt;
return t;
}
if (val < t->num)
t->left = add(t->left, val);
else if (val > t->num)
t->right = add(t->right, val);
else
++t->cnt;
return t;
}
int walk(struct tree *t, int (*f)(struct tree *, void*), void *data) {
int rc;
if (!t)
return 0;
rc = walk(t->left, f, data);
rc += f(t, data);
rc += walk(t->right, f, data);
return rc;
}
struct tree *clean(struct tree *t) {
if (!t)
return NULL;
t->left = clean(t->left);
t->right = clean(t->right);
free(t);
return NULL;
}
int save(struct tree *t, void *data) {
int i, rc = 0;
FILE *fp = (FILE *) data;
for (i = 0; i < t->cnt; ++i)
rc += (fprintf(fp, "%d\n", t->num) < 0);
return rc;
}
int saveb(struct tree *t, void *data) {
int i, rc = 0;
FILE *fp = (FILE *) data;
for (i = 0; i < t->cnt; ++i)
rc += (fwrite((void *) &t->num, sizeof t->num, 1, fp) != 1);
return rc;
}
int main(int argc, char **argv) {
int rc = 0;
struct tree *t = NULL;
char buff[0x200];
FILE *fin, *fout, *foutb;
if (argc < 4) {
fprintf(stderr, "Usage: %s SRCFILE OUTFILE.TXT OUTFILE.BIN\n", argv[0]);
exit(0);
}
if (!((fin = fopen(argv[1], "r")) && (fout = fopen(argv[2], "w"))
&& (foutb = fopen(argv[3], "wb")))) {
perror("fopen");
exit(-1);
}
while (fgets(buff, sizeof buff, fin))
t = add(t, atoi(buff));
rc += walk(t, save, (void *) fout);
rc += walk(t, saveb, (void *) foutb);
t = clean(t);
fclose(fin);
fclose(fout);
fclose(foutb);
return rc;
}
Just noticed the "number of integers in first string of a file" spec; I think your teacher ment you'd put them into array and sort it; but anyway do it yourself :)
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
return *(int*)a > *(int*)b ? 1 : (*(int*)a < *(int*)b ? -1 : 0);
}
int main(int argc, char **argv) {
char buff[0x200];
FILE *fin, *fout, *foutb;
int i, *arr, sz = 0, rc = 0;
if (argc < 4) {
fprintf(stderr, "Usage: %s SRCFILE OUTFILE.TXT OUTFILE.BIN\n", argv[0]);
exit(0);
}
if (!((fin = fopen(argv[1], "r")) && (fout = fopen(argv[2], "w"))
&& (foutb = fopen(argv[3], "wb")))) {
perror("fopen");
exit(-1);
}
if (fgets(buff, sizeof buff, fin)) {
sz = atoi(buff);
if (!(arr = malloc(sizeof(int) * sz)))
perror("Not enough memory"), exit(-1);
for (i = 0; i < sz && fgets(buff, sizeof buff, fin); ++i)
arr[i] = atoi(buff);
}
qsort(arr, sz, sizeof(int), cmp);
for (i = 0; i < sz; ++i)
rc += (fprintf(fout, "%d\n", arr[i]) < 0);
for (i = 0; i < sz; ++i)
rc += (fwrite((void *) &arr[i], sizeof(int), 1, foutb) != 1);
fclose(fin);
fclose(fout);
fclose(foutb);
return rc;
}
Here are some sample codes. If you google for these function names, and if you stayed awake in class, I'm sure you'll do fine. You'll probably need to:
open a file:
FILE* inFile = fopen("input.txt", "r");
read a single value from the input
int numConverted = fscanf(inFile, "%d", &value);
allocate some memory:
int *pInts = malloc(n * sizeof(int));
sort the array
// The parameters are tricky! Check your class notes or text book
qsort(...)
write a single value out as text
fprintf(outFile, "%d\n", i);
write a single value out as binary:
fwrite( &i, sizeof i, 1, outBinFile);