Segmentation fault on fopen C [duplicate] - c

This question already has answers here:
When using gets to get a file name in C, the file opens but when using fgets it does not
(3 answers)
Closed 7 years ago.
guy's well I have this code
#include <stdio.h>
typedef struct
{
int numero, notaF, notaE;
char nome[100];
} ALUNO;
void lerFicheiro(char path[], ALUNO alunos[], int *i);
void escreverFicheiro(char path[], ALUNO alunos[], int tamanho);
int main()
{
//Declarações
int i=0,t=0;
char path[999], wpath[999];
ALUNO alunos[999];
FILE *f;
//Introdução do nome do ficheiro para leitura e para escrita
printf("Introduza a localização do ficheiro para leitura: ");
fgets(path,999,stdin); //segmentation fault e o fopen dá null (apenas no read)
printf("Introduza a localização do ficheiro para escrita: ");
fgets(wpath,999,stdin);
//Leitura do ficheiro
lerFicheiro(path,alunos,&t);
//Escrita do ficheiro
escreverFicheiro(wpath, alunos, t);
return 0;
}
void lerFicheiro(char path[], ALUNO alunos[],int *i)
{
FILE *f = fopen("dados1.txt","r");
if(f!=NULL)
{
while(fscanf(f,"%d\n",&alunos[*i].numero)==1)
{
fgets(alunos[*i].nome,100,f);
fscanf(f,"%d\n",&alunos[*i].notaF);
fscanf(f,"%d\n",&alunos[*i].notaE);
*i=*i+1;
}
}
else
{
printf("Erro ao abrir o ficheiro\n");
}
fclose(f);
}
void escreverFicheiro(char path[], ALUNO alunos[], int tamanho)
{
FILE *f = fopen(path,"w+");
int i = 0, notaFinal = 0;
for(i=0;i<tamanho;i++)
{
if(alunos[i].notaF>alunos[i].notaE)
notaFinal = alunos[i].notaF;
else
notaFinal = alunos[i].notaE;
if(notaFinal>=10)
{
fprintf(f,"%d\n",alunos[i].numero);
fputs(alunos[i].nome,f);
fprintf(f,"%d\n",notaFinal);
}
}
fclose(f);
}
But on the lerFicheiro function, on the fopen if I replace the "dados1.txt" by path I will get the error "Erro ao abrir o ficheiro" in english "Unable to open file" and right after segmentation fault
I can't find the error anywere

You should strip the trailing newline from the file name
char *sptr = strchr(path, '\n');
if (sptr) *sptr = '\0';
Also move the fclose(f);, you are trying to close a file you did not open.
void lerFicheiro(char path[], ALUNO alunos[],int *i)
{
FILE *f = fopen("dados1.txt","r");
if(f!=NULL)
{
while(fscanf(f,"%d\n",&alunos[*i].numero)==1)
{
fgets(alunos[*i].nome,100,f);
fscanf(f,"%d\n",&alunos[*i].notaF);
fscanf(f,"%d\n",&alunos[*i].notaE);
*i=*i+1;
}
fclose(f);
}
else
{
printf("Erro ao abrir o ficheiro\n");
}
}

Related

Reading from binary file LANG C

I am having trouble reading from a bin file.
I am recording some text in binary (correctly i think), but my code isn't able to read the text I wrote and print it in the console. When i open the file the information is there (this document is use to storage the information from the client and the login access) and i can login, but when i try to read and print in console it doesn't show me.
I am using a struct to get the values from the document, and then i open the document "fopen()" but when i try to read with the "fread()" in a "while" I don't get in, the print don't give me the right information
I try to reduce as much i could of the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <dir.h>
#include <unistd.h>
#include <time.h>
#include <conio.h>
#define SIZE 1000
typedef struct
{
char id[10];
char nome[100];
char passe[100];
}Pacient;
Pacient p1;
FILE* filepaciente;
//variables
char tmpnome[100], tmppassword[100];
//variable for path
char nomedoc[15];
char pasta[250];
char sessionName[15];
char tmp_name[15];
char fullpath[200];
char tmp_nome[15];
void vedocumento(int* i, char* line, char pacienteData[])
{
// DEFINE A VARIÁVEL USERDATA COMO UMA STRING VAZIA
strcpy(pacienteData, "");
// IF FINDS "|", GO TO THE NEXT CHARACTER
if (line[*i] == '|')
{
(*i)++;
}
//WHEN THE CHARACTER IS DIFERENT THEN |, ADD THAT CHARACTER TO THE ARRAY USERDATA
while (line[*i] != '|') // *i = 0
{
strncat(pacienteData, &line[*i], 1); // userData = "" ; userData = userData + carater
(*i)++;
}
}
findpath()
{
//PROCURA O CAMINHO ONDE SE ENCONTRA O PROJETO
if (getcwd(pasta, sizeof(pasta)) == NULL)
{
printf("ERROR!\n");
}
else
{
strcat(pasta, "\\file\\");
//CRIA O FICHEIRO COM O NUMERO DE INTERNO
strcpy(nomedoc, strcat(tmp_nome, ".bin"));
//JUNTA O CAMINHO COMPLETO AO NOME DO FICHEIRO
strcat(pasta, nomedoc);
strcpy(fullpath, pasta);
}
}
int main() //where i write in the bin file
{
//GETTING REGISTRY DATA
fflush(stdin); //para ir so buscar os dados
printf("\nName pacient: ");
scanf("%[^\n]", p1.nome);
printf("\nPassword do pacient %s: ", p1.nome);
scanf("%s", p1.passe);
printf("\nID pacient %s: ", p1.nome);
scanf(" %s", p1.id);
strcpy(tmp_nome, p1.nome);
strcpy(tmp_nome, strlwr(tmp_nome));
findpath();
if (access(fullpath, F_OK) == 0)
{
//IF EXISTS
printf("Este nome de utilizador já foi registado! Por favor, tente novamente!\n");
}
else
{
// IF DOESN'T EXIST
filepaciente = fopen(fullpath, "wb");
if (filepaciente == NULL)
{
printf("\nerror\n");
}
//size_t elements_written = fwrite(&p1, sizeof(Paciente), 1, filepaciente);
//PRINTING ON FILE
fprintf(filepaciente, "%s|%s|%s\n", p1.nome, p1.passe, p1.id);
fclose(filepaciente);
}
//WHERE I WANT TO PRINT ON THE CONSOLE
{
printf("Name do pacient: ");
scanf(" %[^\n]", tmpnome);
strcpy(tmp_nome, tmpnome);
strcpy(tmp_nome, strlwr(tmp_nome));//this is to get the name of the document
findpath(); //Find the path to the document
if (access(fullpath, F_OK) == 0)
{
filepaciente = fopen(fullpath, "rb"); //Open the document
Pacient pacient[100];
char line[SIZE];
int nline = 0;
fgets(line, SIZE, filepaciente);
int i = 0;
vedocumento(&i, line, pacient[nline].nome);
vedocumento(&i, line, pacient[nline].passe);
nline++;
//LOOP TO CHECK
for (i = 0; i < 1; i++)
{
if (strcmp(tmpnome, pacient[i].nome) == 0)
{ //WRITE INFO
char buf[SIZE];
if (filepaciente == NULL)
{
printf("\nERRO OPENING\n");
}else printf("\nOPEN THE FILE\n");
//IF I PUT "==1" DON'T GET IN THE WHILE
while( fread(&p1, sizeof(p1), 1, filepaciente) == 1)
{
printf("%c", p1); //NOT SURE IF THIS IS CORRECT
}
}
}
}
}
}

Double chained list problems passing char[] with function

I have been working on a school project that requires working with double-chained list with struct. I have managed to create the functions that add an integer and a char to the struct. But when I attempt to add the char it wont works, but with the integer, works fine.I'm working with 3 files, the header.h, function.c, and main.c
main.c file:
No* primeiro = NULL;
No* atual = NULL;
int i, val;
char tecla;
char nome[50];
for(i = 0; i < 3; i++)
{
printf("Digite o valor: ");
scanf("%d", &val);
getchar();
printf("\nType something: ");
fgets(nome, 50, stdin);
inserir_final(&primeiro, val, nome);
}
The function file:
struct no{
int elemento;
char nome[50];
struct no *anterior;
struct no *proximo;
};
void inserir_final (No **primeiro, int valor, char nome[]){
No* novo = novo_no(valor, nome);
No* aux;
if(*primeiro == NULL){
*primeiro = novo;
}
else
{
novo->proximo = *primeiro;
(*primeiro)->anterior->proximo = novo;
novo->anterior=(*primeiro)->anterior;
(*primeiro)->anterior = novo;
}
}
No* novo_no(int dado, char nome[]){
No* aux = (No*)malloc(sizeof(No));
aux->elemento = dado;
strcpy(aux->nome, nome);
aux->proximo = aux;
aux->anterior = aux;
return aux;
}
This is how I print it:
void listar_nos(No* primeiro){
No* aux = primeiro;
printf("Listagem do primeiro ao ultimo: \n");
if (primeiro == NULL)
return;
do
{
printf("Elemento: %d\n", aux->elemento);
printf("Nome: %s\n", aux->nome);
aux = aux->proximo;
} while (aux != primeiro);
printf("\n\nListagem do ultimo ao primeiro: \n");
aux = aux->anterior;
do
{
printf("Elemento: %d\n", aux->elemento);
aux=aux->anterior;
} while (aux->proximo!=primeiro);
}
The output:
Digite o valor: 10
Type something: ola
Digite o valor: 20
Type something: ok
Digite o valor: 30
Type something: po
Digite p para proximo e A para anteriro:s
Todos os nos: Listagem do primeiro ao ultimo:
Elemento: 10
Nome: ñ
Elemento: 20
Nome: ▄
Elemento: 30
Nome: $
An array is passed to a function as a pointer. You are printing the numerical value of the pointer. To print the string, you want to use %s, not %d.

Why is a Printf in a Function Preventing a Variable in a Struct Array from going Corrupt in Another Function?

I have got a function to read a file and attribute to a struct array multiple ints and strings, my fscanf format string looks like this: "%d.%d.%d.%d %d %60c%60c%d %8c".
And everything is OK if while I scan it and if I use a printf, but if I don't then the 2 last strings become corrupted at the end.
Since the file is gigantic and that is not the purpose of the function, I would like to take that printf out.
typedef struct
{
int nacional;
int regional;
int distrital;
int municipal;
}id_geo;
typedef struct
{
id_geo id_geo;
long int cartao_cid;
char nome_dono[61];
char morada[61];
int num_porta;
char codigo_postal[9];
}prop_id_dono;
prop_id_dono *ler_ficheiro(char *file_name, int num_linha) {
prop_id_dono *info_geral;
long int cartao_cid;
char nome_ficheiro;
char nome_dono[60];
char morada[60];
int num_porta;
char codigo_postal[8];
int nacional;
int regional;
int distrital;
int municipal;
int i = 0;
FILE *fp;
fp = fopen(file_name, "r");
if (fp == NULL)
printf("Peço desculpa, mas não foi possível abrir o ficheiro.");
info_geral = (prop_id_dono *)malloc(sizeof(prop_id_dono) * num_linhas);
while (fscanf(fp, "%d.%d.%d.%d %ld %60c%60c%d %8c\n",
&nacional, &regional, &distrital, &municipal,
&cartao_cid, nome_dono, morada, &num_porta, codigo_postal) != EOF) {
// Faz o scan ao ficheiro através de variáveis temporais, sendo que só
// depois é que atribui valores ao vetor que contém a informação geral
info_geral[i].id_geo.nacional = nacional;
info_geral[i].id_geo.regional = regional;
info_geral[i].id_geo.distrital = distrital;
info_geral[i].id_geo.municipal = municipal;
info_geral[i].cartao_cid = cartao_cid;
strcpy(info_geral[i].nome_dono, nome_dono + '\0');
strcpy(info_geral[i].morada, morada + '\0');
info_geral[i].num_porta = num_porta;
strcpy(info_geral[i].codigo_postal, codigo_postal + '\0');
//This is the magical printf
printf("%d.%d.%d.%d %ld %s%s%d %s \n",
info_geral[i].id_geo.nacional, info_geral[i].id_geo.regional,
info_geral[i].id_geo.distrital, info_geral[i].id_geo.municipal,
info_geral[i].cartao_cid, info_geral[i].nome_dono,
info_geral[i].morada, info_geral[i].num_porta,
info_geral[i].codigo_postal);
i++;
}
fclose(fp);
return info_geral;
}
The input is something like this, but it repeats 20,000 something times in the file
1.1.1.1 1234568 Name, 60 caracters in total(including the spaces)Adress(same thing with the spaces here)House Number Postal Code
You parse input fragments with %60c into character arrays of size 60.
Assuming the conversion succeeds, these arrays will not contain proper C strings, and your attempt at concatenating a '\0' does not work in C.
Here are ways to improve your program:
you should read lines into a local array for easier error reporting in case of conversion failures, and use sscanf() fo parsing.
you should make the destination arrays one byte longer and set a null terminator at the end. The arrays in the prop_id_dono structure should be made large enough too.
you should check the return value of sscanf and report conversion failures
you should stop scanning after num_linhas lines.
you should check for memory allocation failure.
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int nacional;
int regional;
int distrital;
int municipal;
} id_geo;
typedef struct {
id_geo id_geo;
long int cartao_cid;
char nome_dono[61];
char morada[61];
int num_porta;
char codigo_postal[9];
} prop_id_dono;
prop_id_dono *ler_ficheiro(const char *file_name, int num_linha) {
char buf[256];
prop_id_dono *info_geral;
long int cartao_cid;
char nome_ficheiro;
char nome_dono[61];
char morada[61];
int num_porta;
char codigo_postal[9];
int nacional;
int regional;
int distrital;
int municipal;
int i = 0;
FILE *fp;
fp = fopen(file_name, "r");
if (fp == NULL) {
printf("Peço desculpa, mas não foi possível abrir o ficheiro.");
return NULL;
}
// use calloc to allocate an array initialized to all bits zero
info_geral = (prop_id_dono *)calloc(num_linhas, sizeof(prop_id_dono));
if (info_geral == NULL) {
fclose(fp);
return NULL;
}
while (i < num_linhas && fgets(buf, sizeof buf, fp) != NULL) {
// Faz o scan ao ficheiro através de variáveis temporais, sendo que só
// depois é que atribui valores ao vetor que contém a informação geral
if (sscanf(buf, "%d.%d.%d.%d %ld %60c%60c%d %8c",
&nacional, &regional, &distrital, &municipal,
&cartao_cid, nome_dono, morada, &num_porta, codigo_postal) != 9) {
printf("parsing error: %s", buf);
continue;
}
info_geral[i].id_geo.nacional = nacional;
info_geral[i].id_geo.regional = regional;
info_geral[i].id_geo.distrital = distrital;
info_geral[i].id_geo.municipal = municipal;
info_geral[i].cartao_cid = cartao_cid;
nome_dono[60] = '\0';
strcpy(info_geral[i].nome_dono, nome_dono);
morada[60] = '\0';
strcpy(info_geral[i].morada, morada);
info_geral[i].num_porta = num_porta;
codigo_postal[8] = '\0';
strcpy(info_geral[i].codigo_postal, codigo_postal);
i++;
}
fclose(fp);
// note that the caller does not receive the number of lines parsed.
// passing the address of a int for this purpose if a good solution.
return info_geral;
}

input of data in a FILE

i have to input the data into a FILE * (this is in C and using codeblocks), the data is a struct containing 3 char[ ] an 1 double, i dont know why when i print the file it repeats the last struct twice and in "dni" it puts 0.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char dni[9];
char nombre[100], apellido[100];
double monto_adeudado;
} t_datos;
void carga_del_archivo(char[]);
t_datos carga_struct(t_datos);
int main()
{
char nombrearchivo[30];
printf("ingrese el nombre del archivo: ");
gets(nombrearchivo);
carga_del_archivo(nombrearchivo);
return 0;
}
void carga_del_archivo(char nombre[30])
{
FILE* ptrarch;
t_datos aux;
ptrarch = fopen(nombre, "ab");
if (ptrarch != NULL) {
do {
aux = carga_struct(aux);
fwrite(&aux, sizeof(t_datos), 1, ptrarch);
} while (strcmp(aux.dni, "0") != 0);
} else {
printf("ERROR\n");
}
}
t_datos carga_struct(t_datos aux)
{
printf("\ningrese el dni: ");
fflush(stdin);
gets(aux.dni);
if (strcmp(aux.dni, "0") == 0)
return aux;
printf("\ningrese el nombre: ");
fflush(stdin);
gets(aux.nombre);
fflush(stdin);
printf("\ningrese el apellido: ");
gets(aux.apellido);
fflush(stdin);
printf("\ningrese el monto adeudado: ");
scanf("%lf", &aux.monto_adeudado);
return aux;
}
Problem is here:
{
aux=carga_struct(aux);
fwrite(&aux,sizeof(t_datos),1,ptrarch);
}while(strcmp(aux.dni,"0")!=0);
When you enter 0 here aux=carga_struct(aux) you write it to the disk by fwrite on next line before checking this statement: while(strcmp(aux.dni,"0")!=0).

Using a list to store data from a .txt file, only stores the last input (C)

I need a way to store data from a file as well as save it on a file, it all needs to be done through a list using pointers, as the menu specifies it has to be able to delete and search for an specific person`s data within the list, my problem is, it reads the data from the file and stores it, but the show (on screen) function gets stuck on a loop showing me the data it read from the file for the last person's information(what would go on the last node before pointing to NULL), the same happens with the save (to file) function and the search (on list) and delete (from list) functions, which leads me to think it's somehow not pointing to NULL at the end of the list, I checked several times every function and their calls and couldn't find anything wrong but I'm barely a student and I really need help with this, thanks in advance (I'm sorry if I didn't format the code properly).
This is the library I made with the functions I needed:
#define EOL '\n'
struct fecha{
int dia,mes,año;
};
struct lista{
long cedula;
int genero;
char nombre[20];
char apellido[20];
char direccion[50];
fecha f;
lista *prox;
};
void asignar (int i,char lectura[50],lista **t){
switch (i)
{
case 1:
(*t)->cedula=atol(lectura);//atol convierte string a long
break;
case 2:
(*t)->genero=atoi(lectura);//atoi convierte string a int
break;
case 3:
strcpy((*t)->nombre,lectura);
break;
case 4:
strcpy((*t)->apellido,lectura);
break;
case 5:
strcpy((*t)->direccion,lectura);
break;
case 6:
(*t)->f.dia=atoi(lectura);
break;
case 7:
(*t)->f.mes=atoi(lectura);
break;
case 8:
(*t)->f.año=atoi(lectura);
break;
};
}
void insertaCab(lista **p, char path[100]){
lista *t = new lista;//crea el nodo
FILE *archivo;//apuntador para el archivo
int i=1;
char lectura[50];
archivo = fopen(path, "r");
if (archivo != NULL){//Si el archivo existe
while (!feof(archivo)){//Mientras no es final de archivo
while (i<=8){//lee 8 lineas y pasa al siguiente nodo de la lista
memset(lectura, 0, 50);
fgets(lectura,50,archivo);//Lee una linea
asignar(i,lectura,&t);>le pasa a asignar el contador,los datos y el apuntador de la lista
i++;
}i=1;
t->prox =(*p);//T->datos->||
(*p)=t;//P->datos->||
}fclose(archivo);
}
}
void muestra(lista *p){
lista *t = p;
while (t){
printf("Cedula: %i\n",t->cedula);
if (t->genero == 1) printf("Genero: Femenino\n");
else printf("Genero: Masculino\n");
printf("Nombre: %s\n",t->nombre);
printf("Apellido: %s\n",t->apellido);
printf("Direccion: %s\n",t->direccion);
printf("Fecha de nacimiento: %i/%i/%i\n\n",t->f.dia,t->f.mes,t->f.año);
t=t->prox;
}
printf("\n");
}
int buscarlista(lista *p,long x){
lista *t=p;
while (t!= NULL ){
if (t->cedula == x)
return 1;
t=t->prox;
}
return 0;
}
void eliminar(lista **p, long x){
lista *t=(*p),*aux;
if (t!= NULL)
if (t->cedula == x){
(*p)=t->prox;
delete t;
}
else{
while ((t->prox!= NULL) && (t->prox->cedula!=x))
t=t->prox;
if (t->prox!= NULL){
aux=t->prox;
t->prox=aux->prox;
delete aux;
}
}
}
void guardar(lista *p,char path[100]){
lista *t= new lista;
t=p;//apuntador auxiliar para recorrer la lista
FILE *archivo;//apuntador para el archivo
archivo = fopen(path,"a");//abre el archivo en modo append, si no existe lo crea
if(archivo !=NULL){//Si el archivo existe
while (t){
fprintf(archivo,"Cedula: %i\n",t->cedula);
if (t->genero == 1) fprintf(archivo,"Genero: Femenino\n");
else fprintf(archivo,"Genero: Masculino\n");
fprintf(archivo,"Nombre: %s\n",t->nombre);
fprintf(archivo,"Apellido: %s\n",t->apellido);
fprintf(archivo,"Direccion: %s\n",t->direccion);
fprintf(archivo,"Fecha de nacimiento: %i/%i/%i\n\n",t->f.dia,t->f.mes,t->f.año);
t=t->prox;
}
fclose(archivo);
}
}
And this is my main:
void main ( )
{
lista *p=NULL;
long x = 0;
int op;
char path[100];
op=-1;
while (op!=0){
printf ("1. Agregar\n");
printf ("2. Buscar\n");
printf ("3. Eliminar\n");
printf ("4. Mostrar\n");
printf ("5. Guardar\n");
printf ("0. Salir\n");
scanf ("%d", &op);
switch (op){
case 1: printf("Introduzca la direccion del archivo:");
memset(path,0,100);//Inicializa dir
scanf("%s",path);//Lee la direccion del archivo
insertaCab(&p,path);//Recibe el apuntador de la lista y la direccion del archivo
break;
case 2: printf("Indique el numero de cedula a buscar:");
scanf("%d",&x);
if (buscarlista(p,x) == 1)printf("El numero %i se encuentra en la lista\n",x);
else printf("No se encuentra en la lista\n");
break;
case 3: printf("Indique numero de cedula a eliminar:");
scanf("%d",&x);
eliminar(&p,x);
break;
case 4: muestra(p);
break;
case 5: printf("Introduzca la direccion en donde desea guardar la lista:");
memset(path,0,100);
scanf("%s",path);
guardar(p,path);
break;
};
}
}
You aren't detecting EOF properly. Try this:
void insertaCab(lista **p, char path[100]){
char lectura[50];
FILE *archivo; = fopen(path, "r");
if (archivo == NULL) return;
lista *t = new lista;
while (fgets(lectura, 50, archivo)) {
for (i = 1; i <= 8 && fgets(lectura, 50, archivo); i++)
asignar(i, lectura, &t);
if (i <= 8) break; // reached EOF before 8 lines were read.
t->prox = *p;
*p = t;
}
fclose(archivo);
}
Alright so I was able to solve it, I was missing the use of the malloc function, that's the reason as to why the list never got to NULL. The following is the fixed and working version of the function to input data into the list from the file:
void insertaCab(lista **p, char path[100]){
lista *t = new lista;
t = (struct lista *) malloc( sizeof(struct lista) );
char lectura[50];
int i=1;
FILE *archivo = fopen(path, "r");
if (archivo == NULL) return;
while (fgets(lectura,50,archivo)){
t = (struct lista *) malloc( sizeof(struct lista) );
for (i=1; (i<=8) && (fgets(lectura,50,archivo)); i++)
asignar(i,lectura,&t);
if(i<=8) break;
t->prox =(*p);
(*p)=t;
}
fclose(archivo);
}

Resources