Read wrong values from binary file - c

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

Related

Reading a file in C on Linux

How do I read a file into a string on Linux in C?
I came up with some code, but it's not working, and idk why. fgetc() always returns -1.
The file structure is something like this
.:
Files/
main.c
makefile
./Files:
test
Contents of main.c:
#include <stdio.h>
int fileLength(const char filePath[]);
void readFile(const char filePath[], char* outString);
int main()
{
char fileContents[fileLength("Files/test")];
readFile("Files/test", &fileContents);
printf("DEBUG: Address of fileContents is 0x%x\n", &fileContents);
printf("File contents:\n%s\n", fileContents);
return 0;
}
int fileLength(const char filePath[])
{
//Open the file
FILE* file;
if ((file = fopen(filePath, "r")) == NULL)
{
printf("ERROR: File (%s) cannot be opened.\n", filePath);
return -1;
}
//Find the length
fseek(file, 0, SEEK_END);
return ftell(file);
}
void readFile(const char filePath[], char* outString)
{
FILE* file;
//File reading
printf("DEBUG: File path is %s\n", filePath);
if ((file = fopen(filePath, "r")) == NULL)
{
printf("ERROR: File (%s) cannot be opened.\n", filePath);
exit(1);
}
//Get length of file and allocate the according amount of memory
fseek(file, 0, SEEK_END);
int fileLength = ftell(file);
printf("DEBUG: File length is %i\n", fileLength);
//Allocate string
char fileContent[fileLength];
//Read file to string
printf("DEBUG: File contents as digits:\n");
for (int i = 0; i < fileLength; i++)
{
fileContent[i] = fgetc(file);
printf("%d ", fileContent[i]);
}
printf("\n");
printf("DEBUG: Contents of file are:\n%s\n", fileContent);
fclose(file);
printf("DEBUG: outString is pointing to 0x%x\n", outString);
*outString = fileContent;
}
The output is usually just a bunch of question mark diamond things (running in terminal) that match the length of the file with a few other random chars thrown in at the end. The chars at the end change every time the program is run.
kaylum was right, the solution was to:
rewind() after finding the file length in readFile()
remember to fclose() when done
write directly to outString instead of using fileContent
The final code of main.c comes out to be:
#include <stdio.h>
int fileLength(const char filePath[]);
void readFile(const char filePath[], char* outString);
int main()
{
char fileContents[fileLength("Files/test")];
readFile("Files/test", &fileContents);
printf("File contents:\n%s\n", fileContents);
return 0;
}
int fileLength(const char filePath[])
{
//Open the file
FILE* file;
if ((file = fopen(filePath, "r")) == NULL)
{
printf("ERROR: File (%s) cannot be opened.\n", filePath);
return -1;
}
//Find the length
fseek(file, 0, SEEK_END);
int length = ftell(file);
fclose(file);
return length;
}
void readFile(const char filePath[], char* outString)
{
FILE* file;
//File reading
if ((file = fopen(filePath, "r")) == NULL)
{
printf("ERROR: File (%s) cannot be opened.\n", filePath);
exit(1);
}
//Get length of file and allocate the according amount of memory
fseek(file, 0, SEEK_END);
int fileLength = ftell(file);
rewind(file);
//Read file to string
for (int i = 0; i < fileLength; i++)
outString[i] = fgetc(file);
fclose(file);
}

Dynamic storage of a binary file in C

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

segment fault error in encrypt files smaller than 1Kbyte

i write this program for encrypt any file with any size but if file will smaller than 1Kbyte my program give me segment fault error whats wrong?
#include <stdio.h>
#include <stdlib.h>
long int findsize(char file_name[])
{
FILE* fp = fopen(file_name, "r");
if (fp == NULL) {
printf("File Not Found!\n");
return -1;
}
fseek(fp, 0L, SEEK_END);
long int res = ftell(fp);
fclose(fp);
return res;
}
int main ()
{
FILE *fptr;
char path[256];
char* data;
int passcode;
printf("Enter the path of file : ");
scanf("%s",path);
long int file_size = findsize(path);
data = malloc(file_size);
fptr = fopen(path,"rb");
int i = 0;
while (!feof(fptr))
data[i++] = fgetc(fptr);
fclose(fptr);
fptr = fopen(path, "wb");
for (int j=0; j<i-1; j++)
fputc((data[j] ^ 0x60), fptr);
fclose(fptr);
free(data);
return 0;
}
my program can encrypt files bigger than 1GByte but. what should i do?

sort array of structure C

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;

C - Writing to binary failed (rewrites a file)

I'm not sure what I'm doing wrong, trying to write a simple program that encrypts after being ran once renames. When the method is ran twice it is supposed to do the same thing but instead it decrypts the file. The first version worked but it left the old version and made a new version and I wanted a program that I could run once to encrypt and again to decrypt allowing me to change the file extension in the process, for convenience.
When I run the program it crashes on fwrite().
#include <stdio.h>
#include <stdlib.h>
#define KEY '&'
int main(void)
{
FILE *fp; // file pointer
size_t size, test; // file size
char src_file[FILENAME_MAX], dst_file[FILENAME_MAX];
int orig_char, new_char;
int i = 0;
printf("Enter the name of the source file \"file.ext\": ");
scanf("%s", src_file);
if ((fp = fopen(src_file, "rb")) == NULL) { // open file
fprintf(stderr, "Can't open \"%s\"\n", src_file);
exit(EXIT_FAILURE);
}
fseek(fp, 0, SEEK_END); // find the end of file
size = ftell(fp); // file size
fseek(fp, 0, SEEK_SET); // set file position to start
unsigned char buffer[size], *temp = buffer; //buffer
test = fread(buffer, sizeof(buffer[0]), size, fp);
printf("size written: %d, size of file: %d\n", test, size);
if (test != size) {
fprintf(stderr, "Error: operation fwrite failed!\n");
exit(EXIT_FAILURE);
}
fclose(fp);
printf("Enter the name of the destination file \"file.ext\": ");
scanf("%s", dst_file);
if ((fp = fopen(src_file, "wb")) == NULL) {
fprintf(stderr, "Can't open \"%s\"\n", dst_file);
exit(EXIT_FAILURE);
}
puts("Test1");
for (i = 0; (size_t)i < size && orig_char != EOF; i++, temp++) {
orig_char = (int) *temp;
new_char = orig_char ^ KEY;
*temp = new_char;
}
puts("Test3");
test = fwrite(buffer, sizeof(buffer[0]), size, fp);
fclose(fp);
free(buffer);
if ((rename(src_file, dst_file)) != 0)
fprintf(stderr, "Failed to rename file, make sure file doesn't" \
"already exist!\n");
return 0;
}
Here is my final code in case anyone else comes across this problem, I cleaned it up a tad and added a loop feature for offsetting multiple files. I also added some error recovery.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define KEY '&'
int main(void)
{
FILE *fp; // file pointer
size_t size, test; // file size
char src_file[FILENAME_MAX], dst_file[FILENAME_MAX];
char ch = 'Y';
int orig_char, new_char;
int i = 0;
while (toupper(ch) != 'N') {
printf("Enter the name of the source file \"file.ext\": ");
scanf("%s", src_file);
while ((fp = fopen(src_file, "rb")) == NULL) { // open file
fprintf(stderr, "Can't open \"%s\"\n", src_file);
printf("Enter the name of the source file \"file.ext\": ");
scanf("%s", src_file);
}
fseek(fp, 0, SEEK_END); // find the end of file
size = ftell(fp); // file size
fseek(fp, 0, SEEK_SET); // set file position to start
unsigned char buffer[size], *temp = buffer; // buffer
// send file to buffer
test = fread(buffer, sizeof(buffer[0]), size, fp);
printf("size written: %d, size of file: %d\n", test, size);
if (test != size) {
fprintf(stderr, "Error: operation fwrite failed!\n");
system("Press any key to continue");
exit(EXIT_FAILURE);
}
fclose(fp);
while ((fp = fopen(src_file, "wb")) == NULL) {
fprintf(stderr, "Can't open \"%s\"\n", src_file);
printf("Enter the name of the source file \"file.ext\": ");
scanf("%s", src_file);
}
// offset buffer data
for (i = 0; (size_t)i < size && orig_char != EOF; i++, temp++) {
orig_char = (int) *temp;
new_char = orig_char ^ KEY;
*temp = new_char;
}
// write buffer to file
test = fwrite(buffer, sizeof(buffer[0]), size, fp);
fclose(fp);
printf("Enter the file's new name \"file.ext\": ");
scanf("%s", dst_file);
while ((rename(src_file, dst_file)) != 0) {
fprintf(stderr, "Failed to rename file, make sure file doesn't already exist!\n");
}
printf("size written: %d, size of file: %d\n", test, size);
printf("File Successfully offset\n\n");
printf("Would you like to continue: ");
scanf(" %c", &ch);
}
return 0;
}

Resources