Problem with duplicate data in fgets with structs [duplicate] - c

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 5 months ago.
I have a program that seems to have a problem displaying the data received from a .txt file with fgets
Basically the program is something similar to a CRUD or ABM (in Spanish).
The problem is that when I show the structs from the file, it shows me a duplicate of the last struct.
The code is the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
// ==== Estructura Empleado ====
typedef struct
{
int legajo; // Numero de 6 digitos
char nombreApellido[30];
float sueldo; // Aleatorio entre 80k-200k
} Empleado;
// Carga un empleado por teclado; Devuelve un struct Empleado
Empleado cargarEmpleadoPorTeclado();
// Carga un vector de Empleado
void cargarEmpleadosPorTeclado(Empleado empleados[], int cantidadEmpleados);
// Recibe un vector de chars y devuelve un struct Empleado
Empleado parsearEmpleado(char datosSinParsear[50], int largoDatos);
// Carga los empleados desde el archivo al vector empleados[]
void cargarEmpleadosEnVector(Empleado empleados[], int cantidadEmpleados);
// Guarda los empleados en el archivo 'empleados.txt'
void guardarEmpleados(Empleado empleados[], int cantidadEmpleados);
// Muestra los empleados cargados en el vector empleados[]
void mostrarEmpleadosDesdeArchivo(int cantidadEmpleados, int eliminados);
// Busca un empleado por legajo en el archivo 'empleados.txt' y lo 'elimina'
void eliminarEmpleadoPorLegajo(Empleado empleados[], int legajo, int cantidadEmpleados, int * eliminados);
void eliminarEmpleadoVectorPorLegajo(Empleado empleados[], int legajo, int cantidadEmpleados, int *eliminados);
void menu(Empleado empleados[], int cantidadEmpleados);
/* ==== Funcion main ==== */
int main()
{
int cantidadEmpleados = 100;
Empleado empleados[cantidadEmpleados];
menu(empleados, cantidadEmpleados);
return 0;
}
/* ==== Implementaciones ==== */
Empleado cargarEmpleadoPorTeclado()
{
Empleado empleado;
printf("\nIngrese el Nombre y Apellido del empleado: ");
fflush(stdin);
gets(empleado.nombreApellido);
printf("\nIngrese el numero de Legajo del empleado: ");
fflush(stdin);
scanf("%d", &empleado.legajo);
empleado.sueldo = 80000 + rand() % (200000-80000);
return empleado;
}
void cargarEmpleadosPorTeclado(Empleado empleados[], int cantidadEmpleados)
{
for (int i = 0; i < cantidadEmpleados; i++)
{
empleados[i] = cargarEmpleadoPorTeclado();
}
guardarEmpleados(empleados, cantidadEmpleados);
}
Empleado parsearEmpleado(char datosSinParsear[], int largoDatos)
{
Empleado empleado;
int delimitador1 = -1;
int delimitador2 = -1;
char auxiliarLegajo[10] = " ";
char auxiliarNombreApellido[30] = " ";
char auxiliarSueldo[10] = " ";
for(int i = 0; i < largoDatos; i++)
{
// Recorro el string hasta encontrar la primera ocurrencia
// Notese que i = largoDatos es para forzar la salida del for y no sobreescribir el valor de delimitador1
// con la segunda ocurrencia
if(datosSinParsear[i] == ';')
{
delimitador1 = i;
i = largoDatos;
}
}
// Recorro el string a partir de la posicion siguiente de la primera ocurrencia
for (int i = delimitador1 + 1; i < largoDatos; i++)
{
if (datosSinParsear[i] == ';')
{
delimitador2 = i;
}
}
if ((delimitador1 != -1) && (delimitador2 != -1))
{
// Desde 0 hasta delimitador1 tenemos el legajo
for (int i = 0; i < delimitador1; i++)
{
auxiliarLegajo[i] = datosSinParsear[i];
}
// Desde delimitador1+1 hasta delimitador2 tenemos el nombre y apellido
for (int i = delimitador1 + 1; i < delimitador2; i++)
{
auxiliarNombreApellido[i - delimitador1 - 1] = datosSinParsear[i];
}
// Desde delimitador2+1 hasta largoDatos tenemos el sueldo en float
for (int i = delimitador2 + 1; i < strlen(datosSinParsear); i++)
{
auxiliarSueldo[i - delimitador2 - 1] = datosSinParsear[i];
}
empleado.legajo = atoi(auxiliarLegajo);
strcpy(empleado.nombreApellido, auxiliarNombreApellido);
empleado.sueldo = atof(auxiliarSueldo);
return empleado;
}
}
void cargarEmpleadosEnVector(Empleado empleados[], int cantidadEmpleados)
{
// Intentamos abrir el archivo y verificamos si no es un puntero nulo
FILE * archivoEmpleados = fopen("empleados.txt", "r");
if(archivoEmpleados != NULL)
{
int i = 0;
while (!feof(archivoEmpleados) && (i < cantidadEmpleados))
{
char datosSinParsear[50] = "";
Empleado empleadoActual;
// Leemos los datos y lo parseamos
fgets(datosSinParsear, 50, archivoEmpleados);
empleadoActual = parsearEmpleado(datosSinParsear, 50);
// Lo asignamos a la posicion actual del vector 'empleados[]'
empleados[i] = empleadoActual;
i++;
}
fclose(archivoEmpleados);
}
// Si el archivo no existe o no lo encuentra
else
{
printf("\nImposible leer los empleados\nEl archivo \"empleados.txt\" no existe o no se encuentra en la ruta actual");
exit(-1);
}
}
void guardarEmpleados(Empleado empleados[], int cantidadEmpleados)
{
// Intentamos abrir el archivo y verificamos si no es un puntero nulo
FILE * archivoEmpleados = fopen("empleados.txt", "w");
if(archivoEmpleados != NULL)
{
for (int i = 0; i < cantidadEmpleados; i++)
{
// Grabamos los datos linea por linea con el formato 'legajo;nombreapellido;sueldo'
fprintf(archivoEmpleados, "%d;%s;%.2f\n", empleados[i].legajo, empleados[i].nombreApellido, empleados[i].sueldo);
}
printf("\nEmpleados guardados exitosamente en \"empleados.txt\"");
fclose(archivoEmpleados);
}
// Si el archivo no existe o no lo encuentra
else
{
printf("\nImposible guardar los empleados\nEl archivo \"empleados.txt\" no existe o no se encuentra en la ruta actual");
exit(-1);
}
}
void mostrarEmpleadosDesdeArchivo(int cantidadEmpleados, int eliminados)
{
FILE * archivoEmpleados = fopen("empleados.txt", "r");
int i = 0;
while(!feof(archivoEmpleados) && i < (cantidadEmpleados-eliminados))
{
char datosSinParsear[50] = "";
fgets(datosSinParsear, 50, archivoEmpleados);
Empleado empleadoActual;
empleadoActual = parsearEmpleado(datosSinParsear, 50);
printf("\nEmpleado");
printf("\n\t* Numero de legajo: %d", empleadoActual.legajo);
printf("\n\t* Nombre y Apellido: %s", empleadoActual.nombreApellido);
printf("\n\t* Sueldo (en pesos): %.2f", empleadoActual.sueldo);
i++;
}
fclose(archivoEmpleados);
}
/*
Esta funcion no elimina en si la linea que pertenezca al empleado
Sino mas bien, la omitiria cuando la lea, escribiendo un archivo nuevo con el mismo nombre
De esa forma, estariamos haciendo lo mismo
*/
void eliminarEmpleadoPorLegajo(Empleado empleados[], int legajo, int cantidadEmpleados, int *eliminados)
{
// Intentamos abrir el archivo y verificamos si no es un puntero nulo
FILE * archivoEmpleados = fopen("empleados.txt", "r");
// Creamos un nuevo archivo para escribir los datos
FILE * nuevoArchivoEmpleados = fopen("empleados2.txt", "w");
if(archivoEmpleados != NULL)
{
int i = 0;
while (!feof(archivoEmpleados) && i < cantidadEmpleados)
{
char datosSinParsear[50] = "";
Empleado empleadoActual;
// Recibimos los datos y los parseamos
fgets(datosSinParsear, 50, archivoEmpleados);
empleadoActual = parsearEmpleado(datosSinParsear, 50);
/*
Cuando no coincida el legajo, escribe
Si es que llega a coincidir (justamente ese debemos eliminar), no lo escribimos,
simplemente, hacemos una iteración y continuamos el bucle
*/
if (empleadoActual.legajo != legajo)
{
fprintf(nuevoArchivoEmpleados, "%d;%s;%.2f\n", empleadoActual.legajo, empleadoActual.nombreApellido, empleadoActual.sueldo);
i++;
}
else
{
i++;
continue;
};
}
fclose(archivoEmpleados);
fclose(nuevoArchivoEmpleados);
remove("empleados.txt");
rename("empleados2.txt", "empleados.txt");
eliminarEmpleadoVectorPorLegajo(empleados, legajo, cantidadEmpleados, &eliminados);
*eliminados = *eliminados + 1;
printf("\nEmpleado con legajo numero %d eliminado exitosamente", legajo);
}
// Si el archivo no existe o no lo encuentra
else
{
printf("\nImposible eliminar al empleado\nEl archivo \"empleados.txt\" no existe o no se encuentra en la ruta actual");
exit(-1);
}
}
void eliminarEmpleadoVectorPorLegajo(Empleado empleados[], int legajo, int cantidadEmpleados, int *eliminados)
{
int posicionDelElemento = -1;
for (int i = 0; i < cantidadEmpleados; i++)
{
if(empleados[i].legajo == legajo)
{
posicionDelElemento = i;
i = cantidadEmpleados;
}
}
for(int i = posicionDelElemento - 1; i<cantidadEmpleados-1; i++)
{
empleados[i] = empleados[i + 1];
}
cantidadEmpleados--;
}
void menu(Empleado empleados[], int cantidadEmpleados)
{
int sigue = 1;
int eliminados = 0;
int cantidadEmpleadosVar = 0;
printf("\nMenu Empleados\n");
printf("\nOpciones:\n");
printf("\n\t1. Listar los empleados");
printf("\n\t2. Agregar un empleado");
printf("\n\t3. Eliminar un empleado");
printf("\n\t4. Salir");
do
{
int opcion;
int legajo;
printf("\nIngrese opcion > ");
scanf("%d", &opcion);
switch (opcion)
{
case 1:
printf("\nMostrando empleados cargados");
mostrarEmpleadosDesdeArchivo(cantidadEmpleados, eliminados);
break;
case 2:
printf("\nAgregar un empleado:");
printf("\nCuantos empleados desea cargar? > ");
scanf("%d", &cantidadEmpleadosVar);
cargarEmpleadosPorTeclado(empleados, cantidadEmpleadosVar);
break;
case 3:
printf("\nEliminando un empleado:");
printf("\nIngrese el numero de legajo del empleado a eliminar > ");
scanf("%d", &legajo);
eliminarEmpleadoPorLegajo(empleados, legajo, cantidadEmpleados, &eliminados);
break;
case 4:
sigue = 0;
break;
default:
printf("\nLa opcion \"%d\" no es valida, ingrese otra vez\n\n", opcion);
continue;
break;
}
} while (sigue);
}
And the empleados.txt file is the following:
555666;Leandro;80041.00
232433;Juan;80945.00
234443;Antonio;90485.00
119304;Manuel;102943.00
The output is:
Code output linked on imgur
Does anyone know what this error could be?

There are many issues in your code, here are some important ones:
you must not use gets(): read Why is the gets function so dangerous that it should not be used?
you should test the return value of fgets() to determine if a line was read or if end of file has been reached.
using feof() for this purpose as you do is incorrect. You should read Why is “while( !feof(file) )” always wrong?
you should always test for fopen() success before calling any stream function with the FILE pointer.
Also use more spaces for indentation, 4 is recommended for readability.

Related

Error "a label can only be part of a statement" when compiling file line 17 in the main() function [duplicate]

This question already has answers here:
Why can we not declare a variable after a switch case colon without using curly braces?
(3 answers)
Closed last month.
I have a problem compiling the code in the main file at line 17.
The error is
"a label can only be part of a statement and a declaration is not a statement".
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
#define TAILLE_MAX_NOM 50
// Définition du type Compte
typedef struct {
int RIB;
float solde;
char etat[TAILLE_MAX_NOM];
float plafond_credit;
int nb_operations;
float operations[100];
} Compte;
Compte T_Compte[100];
int menu();
void CreerCompte(Compte *C);
int ChercherCompte(Compte T_Compte[],int NC,int RIB );
void AjouterCompte (Compte T_Compte[], int *NC, Compte C);
float Ajouter_Retirer (Compte T_Compte[], int NC, float M,int RIB);
void ListeComptes(Compte T_Compte[], int NC);
void StatCompte (Compte T_Compte[], int NC, int *PNBA,int *PNBR ,int RIB);
void Prime (Compte T_Compte[], int NC);
#endif // HEADER_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"
int menu() {
int choix;
printf("\n\n -> Menu <- \n\n");
printf(" 1 - Ajouter un Nouveau Compte \n");
printf(" 2 - Afficher les comptes de la banque \n");
printf(" 3 - Ajouter une operation a un compte\n");
printf(" 4 - Attribuer une prime aux meilleurs comptes bancaires \n");
printf(" 0 - Quitte\n");
printf("\n --------------------------------------\n");
do {
printf(" -> Tapez votre choix : ");
scanf("%d",&choix);
printf("\n\n");
} while (choix>4 || choix<0);
return choix;
}
void CreerCompte(Compte *C) {
printf("RIB du compte : ");
scanf("%d", &C->RIB);
printf("Solde initial du compte (supérieur ou égal à 50) : ");
scanf("%f", &C->solde);
while (C->solde < 50) {
printf("Le solde initial doit être supérieur ou égal à 50 !\n");
printf("Solde initial du compte (supérieur ou égal à 50) : ");
scanf("%f", &C->solde);
}
strcpy(C->etat, "debiteur");
printf("Plafond de crédit du compte (strictement négatif supérieur à -500) : ");
scanf("%f", &C->plafond_credit);
while (C->plafond_credit >= 0 || C->plafond_credit <= -500) {
printf("Le plafond de crédit doit être un montant strictement négatif supérieur à -500 !\n");
printf("Plafond de crédit du compte (strictement négatif supérieur à -500) : ");
scanf("%f", &C->plafond_credit);
}
C->nb_operations = 0;
}
int ChercherCompte(Compte T_Compte[], int NC, int RIB) {
for (int i = 0; i < NC; i++) {
if (T_Compte[i].RIB == RIB) {
return i;
}
}
return -1;
}
void AjouterCompte(Compte T_Compte[], int *NC, Compte C) {
if (ChercherCompte(T_Compte, *NC, C.RIB) != -1) {
printf("Un compte avec ce RIB existe déjà !\n");
return;
}
T_Compte[*NC] = C;
(*NC)++;
}
float Ajouter_Retirer(Compte T_Compte[], int NC, float M, int RIB) {
// Vérifie que la somme à ajouter ou retirer est non nulle
if (M == 0) {
printf("La somme à ajouter ou retirer ne peut pas être nulle !\n");
return -1;
}
// Cherche le compte dans le tableau
int pos = ChercherCompte(T_Compte, NC, RIB);
// Vérifie que le compte existe
if (pos == -1) {
printf("Le compte avec le RIB spécifié n'existe pas !\n");
return -1;
}
Compte C = T_Compte[pos];
// Vérifie que l'opération de retrait peut être effectuée
if (M < 0 && (C.solde + M < -C.plafond_credit)) {
printf("Opération de retrait impossible !\n");
return -1;
}
// Effectue l'opération
C.solde += M;
C.nb_operations++;
T_Compte[pos] = C;
return C.solde;
}
void ListeComptes(Compte T_Compte[], int NC) {
printf("Liste des comptes de la banque :\n");
for (int i = 0; i < NC; i++) {
Compte C = T_Compte[i];
printf("RIB : %d, Solde : %.2f, Etat : %s, Plafond de crédit : %.2f, Nombre d'opérations : %d\n",
C.RIB, C.solde, C.etat, C.plafond_credit, C.nb_operations);
}
}void StatCompte(Compte T_Compte[], int NC, int *PNBA, int *PNBR, int RIB) {
// Initialise les compteurs à 0
*PNBA = 0;
*PNBR = 0;
// Cherche le compte dans le tableau
int pos = ChercherCompte(T_Compte, NC, RIB);
if (pos == -1) {
printf("Le compte avec ce RIB n'existe pas !\n");
return;
}
// Parcours les opérations du compte
Compte C = T_Compte[pos];
for (int i = 0; i < C.nb_operations; i++) {
if (C.operations[i] > 0) {
(*PNBA)++;
} else if (C.operations[i] < 0) {
(*PNBR)++;
}
}
}
void Prime(Compte T_Compte[], int NC) {
printf("Attribution de la prime aux meilleurs comptes de la banque :\n");
for (int i = 0; i < NC; i++) {
Compte C = T_Compte[i];
// Vérifie que le compte est débiteur
if (strcmp(C.etat, "debiteur") == 0) {
int nb_ajout = 0;
int nb_retrait = 0;
// Parcours les opérations du compte pour compter le nombre d'opérations d'ajout et de retrait
for (int j = 0; j < C.nb_operations; j++) {
if (C.operations[j] > 0) {
nb_ajout++;
} else if (C.operations[j] < 0) {
nb_retrait++;
}
}
// Vérifie que le nombre d'opérations d'ajout est supérieur aux nombres d'opérations de retrait
if (nb_ajout > nb_retrait) {
float prime = (C.solde / C.nb_operations) * 0.5;
printf("RIB : %d - Prime : %.2f\n", C.RIB, prime);
}
}
}
}
//source file/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"
int main() {
// Initialize the array of accounts
int NC = 0;
// Display the menu and get the user's choice
int choix = menu();
while (choix != 0) {
switch (choix) {
case 1:
Compte C;
getchar();
CreerCompte(&C);
AjouterCompte(T_Compte, &NC, C);
break;
case 2:
// Display the accounts
ListeComptes(T_Compte, NC);
break;
case 3:
// Add or remove money from an account
printf("RIB du compte : ");
int RIB;
scanf("%d", &RIB);
printf("Somme à ajouter ou retirer : ");
float M;
scanf("%f", &M);
float solde = Ajouter_Retirer(T_Compte, NC, M, RIB);
if (solde != -1) {
printf("Nouveau solde : %.2f\n", solde);
}
break;
case 4:
// Attribute a prize to the best accounts
Prime(T_Compte, NC);
break;
}
// Display the menu and get the user's choice again
choix = menu();
}
printf("Au revoir !\n");
return 0;
}
Here is the main function that uses 4 switches to perform the following functions:
Add a new account
Display the accounts of the bank
Add an operation to an account
Attribute a prize to the best accounts
Is this line 17?
Compte C;
If so, you need to scope the variable C. Change the case 1: handler to this:
case 1:
{
Compte C;
getchar();
CreerCompte(&C);
AjouterCompte(T_Compte, &NC, C);
break;
}

Process miscomunication with mmap

I cant get this program to work.
It should convert capital letters to normal and vice versa, and numberso into three asterisks (***), and rewrite the file that i give as an argument with said changes, mapped into memory.
The parent process must do the letter conversion, and the child process must do the numbers. They must procceed in halves: the first half of the file, and then the second half of it. The first half seems to be doing fine, but the second one is all corrupted.
I tried making buffer a char *buffer, and using the various methos commented in the code, but nothing seems to work properly.
Here is the code and output:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv)
{
// Comprobamos que se haya proporcionado un nombre de archivo como argumento
if (argc < 2) {
printf("Error: se debe proporcionar el nombre del archivo como argumento.\n");
exit(EXIT_FAILURE);
}
// Abrimos el archivo en modo lectura/escritura
int file = open(argv[1], O_RDWR);
if (file < 0) {
printf("Error: no se puede abrir el archivo %s.\n", argv[1]);
exit(EXIT_FAILURE);
}
// Obtenemos el estado del archivo
struct stat estado;
if (fstat(file, &estado) < 0) {
printf("Error: no se puede obtener el estado del archivo %s.\n", argv[1]);
exit(EXIT_FAILURE);// Función que se ejecuta cuando se recibe una señal
}
// Comprobamos que el archivo sea un archivo regular
if (!S_ISREG(estado.st_mode)) {
printf("Error: %s no es un archivo regular.\n", argv[1]);
exit(EXIT_FAILURE);
}
// Mapeamos el archivo en memoria
char *map = (char*) mmap(NULL, estado.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, file, 0);
if (map == MAP_FAILED) {
printf("Error: no se puede mapear el archivo %s en memoria.\n", argv[1]);
exit(EXIT_FAILURE);
}
printf("\n---------------PROCESO DE LECTURA EN CURSO---------------\n");
char texto ='\0';
int lr = 0;
for (int i = 0; i < estado.st_size; i++) {
// Comenzamos a leer el archivo
if ((lr = read(file, &texto, 1)) < 0) {
printf("\nError intentando leer el archivo\n");
exit(EXIT_FAILURE);
}
// Comprobamos que se está leyendo correctamente el contenido del archivo (y cuál es)
printf("%c", texto);
}
// Creamos un proceso hijo
pid_t pid = fork();
if (pid < 0) {
printf("Error: no se puede crear el proceso hijo.\n");
exit(EXIT_FAILURE);
}
if (pid == 0) {
// Proceso hijo
// Esperamos a que el padre procese la mitad del archivo
raise(SIGSTOP); // Paramos el proceso para esperar la señal del padre
int mitadArchivo = estado.st_size / 2;
// Obtenemos el tamaño final del archivo (con la sustitución de números por asteriscos)
int tamanioFinal = estado.st_size;
for (int i = 0; i < estado.st_size; i++) {
if (isdigit(map[i])) {
tamanioFinal += 2;
}
}
// Redimensionamos el archivo para ajustarlo al tamaño final
if (ftruncate(file, tamanioFinal) < 0) {
printf("Error: no se puede redimensionar el archivo %s.\n", argv[1]);
exit(EXIT_FAILURE);
}
// Procesamos la segunda mitad del archivo
char buffer[/*mitadArchivo*/estado.st_size];
int j = 0, k = 0;
printf("\n---------IMPRIMIR DESDE EL HIJO---------\n");
for (int i = 0; i < estado.st_size; i++) {
if (isdigit(map[i])) {
// Si el caracter es un número, lo sustituimos por tres asteriscos
buffer[j++] = '*';
buffer[j++] = '*';
buffer[j++] = '*';
} else {
// Si el caracter no es un número, lo copiamos tal cual al buffer
buffer[j++] = map[i];
}
printf("%c", buffer[i]);
if (i == mitadArchivo) { // Hemos llegado a la mitad
memcpy(map, buffer, /*2*(estado.st_size + j)*/ mitadArchivo + j); // Escribimos la primera mitad ya modificada
raise(SIGSTOP); // Paramos el proceso para esperar la señal del padre
printf("\nSegunda mitad del archivo: \n");
if (isdigit(map[i])) {
// Si el caracter es un número, lo sustituimos por tres asteriscos
buffer[k++] = '*';
buffer[k++] = '*';
buffer[k++] = '*';
} else {
// Si el caracter no es un número, lo copiamos tal cual al buffer
buffer[k++] = map[i];
}
memcpy(buffer, map + (mitadArchivo + j), /*2*(estado.st_size + j)*/ tamanioFinal - (mitadArchivo + j)); // Leemos la segunda mitad que queda por transformar
}
}
printf("\n");
// Copiamos el contenido del buffer al archivo
//memcpy(map /*+ mitadArchivo*/, buffer, j);
// Modificamos el tamaño del archivo para que tenga en cuenta los cambios
//ftruncate(file, 2*(estado.st_size + j) /*- mitadArchivo*/);
// Finalizamos el proceso hijo
exit(EXIT_SUCCESS);
} else {
// Proceso padre
// Procesamos la primera mitad del archivo
char buffer[estado.st_size];
int mitadArchivo = estado.st_size / 2;
int j = 0;
for (int i = 0; i < estado.st_size /*/ 2*/; i++) {
if (islower(map[i])) {
// Si el caracter es una letra minúscula, la convertimos en mayúscula
buffer[j++] = toupper(map[i]);
} else if (isupper(map[i])) {
// Si el caracter es una letra mayúscula, la convertimos en minúscula
buffer[j++] = tolower(map[i]);
} else {
// Si el caracter no es una letra, lo copiamos tal cual al buffer
buffer[j++] = map[i];
}
if (i == estado.st_size / 2){
sleep(1);
// Copiamos el contenido del buffer al archivo
memcpy(map, buffer, j);
// Indicamos al proceso hijo que puede continuar
kill(pid, SIGCONT);
}
}
// Copiamos el contenido del buffer al archivo
memcpy(buffer, map, j);
sleep(1);
// Indicamos al proceso hijo que puede continuar
kill(pid, SIGCONT);
// Esperamos a que el proceso hijo termine
waitpid(pid, NULL, 0);
printf("\n---------IMPRIMIR DESDE LA SALIDA DESDE MEMORIA---------\n");
for (int i = 0; i < estado.st_size; i++)
printf("%c", map[i]);
printf("\n");
// Finalizamos el proceso padre
exit(EXIT_SUCCESS);
}
return 0;
}
Output:
---------------PROCESO DE LECTURA EN CURSO---------------
esta 5 es 6 la
prueba 89 para 531 ver si
35 el programa 7 funciona
---------IMPRIMIR DESDE EL HIJO---------
ESTA *** ES *** LA
PRUEBA ****** P
Segunda mitad del archivo:
ARA ********* ARA ********* ���c�
---------IMPRIMIR DESDE LA SALIDA DESDE MEMORIA---------
ESTA *** ES *** LA
PRUEBA ****** PARA ********* ���c���of�/����

Reading integer from file through function in c returns wrong value

I'm trying to read a bunch of information about a player from a binary file in c through the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// structure joueur
typedef struct Joueur {
char nom[20];
int num_lieu;
int liste_objet[10];
}Joueur;
// question a
void sauvegarder_jeu(char* nom_partie, Joueur* joueur) {
// ouverture du fichier
FILE *flot;
flot = fopen(nom_partie, "wb");
if (flot == NULL) {
printf("Erreur dans l'ouverture du fichier!\n");
return;
}
// écriture du nom du joueur
fwrite(joueur->nom, sizeof(joueur->nom), 1, flot);
// écriture du numero du lieu
fwrite(&(joueur->num_lieu), sizeof(joueur->num_lieu), 1, flot);
// écriture de la liste des objets
fwrite(joueur->liste_objet, sizeof(joueur->liste_objet), 1, flot);
// fermeture du fichier
fclose(flot);
}
// question b
void charger_jeu(char* nom_partie, char* nom, int* num_lieu, int* liste_objet) {
// ouverture du fichier
FILE *flot;
flot = fopen(nom_partie, "rb");
if (flot == NULL) {
printf("Erreur dans l'ouverture du fichier!\n");
return;
}
// joueur temp pour sizeof
Joueur *temp = (Joueur*)malloc(sizeof(Joueur));
// lecture du nom du joueur
fread(nom, sizeof(temp->nom), 1, flot);
// écriture du numero du lieu
fread(&num_lieu, sizeof(temp->num_lieu), 1, flot);
// écriture de la liste des objets
fread(liste_objet, sizeof(temp->liste_objet), 1, flot);
// suppression du joueur temporaire
free(temp);
// fermeture du fichier
fclose(flot);
}
int main() {
// variables
char *nom_partie = "save.sve";
int i;
int* num_lieu_lecture;
int* liste_objet_lecture;
char* nom_lecture;
// creation d'un joueur qui possede tous les objets
Joueur *j1 = (Joueur*)malloc(sizeof(Joueur));
strcpy(j1->nom, "Omar");
j1->num_lieu = 12;
for (i = 0; i < 10; i++) {
j1->liste_objet[i] = 1;
}
// sauvegarde de la partie
sauvegarder_jeu(nom_partie, j1);
printf("Sauvegarde terminee!\n");
// lecture de la partie
charger_jeu(nom_partie, nom_lecture, num_lieu_lecture, liste_objet_lecture);
printf("Chargement terminee!\n");
// affichage des donnees de la partie
printf("%s\n", nom_lecture);
printf("%d\n", *num_lieu_lecture);
for (i = 0; i < 10; i++) {
printf("liste_objet[%d] = %d\n", i, liste_objet_lecture[i]);
}
// liberation de la memoire
free(j1);
return 0;
}
The function "sauvegarder_jeu()" writes the player's data into a binary file, and the "charger_jeu()" is supposed to read that data and store into variables that I would print out.
The output, where all the values are correct expect for the "num_lieu_lecture" value:
Omar
32759
liste_objet[0] = 1
liste_objet[1] = 1
liste_objet[2] = 1
liste_objet[3] = 1
liste_objet[4] = 1
liste_objet[5] = 1
liste_objet[6] = 1
liste_objet[7] = 1
liste_objet[8] = 1
liste_objet[9] = 1
I don't know where the problem stems from.
The variables you're passing to charger_jeu() do not need to be pointers. num_liste_objet should be int, and liste_objet_lecture and nom_lecture should be arrays.
Then you should pass the address of num_liste_objet to charger_jeu(), so it will update the variable. In charger_jeu() you don't need to use & before num_lieu because it's already a pointer.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// structure joueur
typedef struct Joueur {
char nom[20];
int num_lieu;
int liste_objet[10];
}Joueur;
// question a
void sauvegarder_jeu(char* nom_partie, Joueur* joueur) {
// ouverture du fichier
FILE *flot;
flot = fopen(nom_partie, "wb");
if (flot == NULL) {
printf("Erreur dans l'ouverture du fichier!\n");
return;
}
// écriture du nom du joueur
fwrite(joueur->nom, sizeof(joueur->nom), 1, flot);
// écriture du numero du lieu
fwrite(&(joueur->num_lieu), sizeof(joueur->num_lieu), 1, flot);
// écriture de la liste des objets
fwrite(joueur->liste_objet, sizeof(joueur->liste_objet), 1, flot);
// fermeture du fichier
fclose(flot);
}
// question b
void charger_jeu(char* nom_partie, char* nom, int* num_lieu, int* liste_objet) {
// ouverture du fichier
FILE *flot;
flot = fopen(nom_partie, "rb");
if (flot == NULL) {
printf("Erreur dans l'ouverture du fichier!\n");
return;
}
// joueur temp pour sizeof
Joueur *temp = (Joueur*)malloc(sizeof(Joueur));
// lecture du nom du joueur
fread(nom, sizeof(temp->nom), 1, flot);
// écriture du numero du lieu
fread(num_lieu, sizeof(temp->num_lieu), 1, flot);
// écriture de la liste des objets
fread(liste_objet, sizeof(temp->liste_objet), 1, flot);
// suppression du joueur temporaire
free(temp);
// fermeture du fichier
fclose(flot);
}
int main() {
// variables
char *nom_partie = "save.sve";
int i;
int num_lieu_lecture;
int liste_objet_lecture[10];
char nom_lecture[20];
// creation d'un joueur qui possede tous les objets
Joueur *j1 = (Joueur*)malloc(sizeof(Joueur));
strcpy(j1->nom, "Omar");
j1->num_lieu = 12;
for (i = 0; i < 10; i++) {
j1->liste_objet[i] = 1;
}
// sauvegarde de la partie
sauvegarder_jeu(nom_partie, j1);
printf("Sauvegarde terminee!\n");
// lecture de la partie
charger_jeu(nom_partie, nom_lecture, &num_lieu_lecture, liste_objet_lecture);
printf("Chargement terminee!\n");
// affichage des donnees de la partie
printf("%s\n", nom_lecture);
printf("%d\n", *num_lieu_lecture);
for (i = 0; i < 10; i++) {
printf("liste_objet[%d] = %d\n", i, liste_objet_lecture[i]);
}
// liberation de la memoire
free(j1);
return 0;
}

i want to Print the minimum road data

I want to print the mininum road but I don't know which variable I have to select, can somebody help me?
The code is in Spanish.
int algoritmo(const int begin, const int end, const Graph graph)
{
priority_queue<State> pq; // La cola de prioridad.
vector<int> Dist(graph.V, oo); // La distancia hacia todos los vertices. Inicialmente para cada vertice su valor es infinito.
vector<bool> mark(graph.V, false); // Este arreglo nos permitira determinar los nodos procesados.
Dist[begin] = 0; // Valor inicial del vertice de partida.
pq.push(State(begin, 0)); // Agregamos el primer elemento, que no es mas que el vertice de partida.
while(!pq.empty()) // Mientras existan vertices por procesar.
{
State st = pq.top(); pq.pop(); // Se desencola el elemento minimo.
mark[st.node] = true;// Se marca el nodo como visitado.
if (st.node == end)
return st.cost; // Retornamos el valor del camino, hemos llegado al vertice destino.
int T = (int)graph.G[st.node].size();
for(int i = 0; i < T; ++i) // Se recorren las adyacencias de "a".
{
// Si no ha sido procesado el vertice "vi" y la distancia hacia "vi" es menor a la distancia
// en Dist entonces hemos encontrado un camino mas corto a "vi".
if (!mark[graph.G[st.node][i].node] && ((Dist[st.node] + graph.G[st.node][i].cost) < Dist[graph.G[st.node][i].node]))
{
Dist[graph.G[st.node][i].node] = st.cost + graph.G[st.node][i].cost;
pq.push(State(graph.G[st.node][i].node, st.cost + graph.G[st.node][i].cost));
}
}
//cout<<st.node<<endl;
}
return -1; // Si no se puede llegar al destino, retornar -1.
}

I have some problems with linked lists

I have some problems with my code. I want to load a file (i can do it in "cargar" function), i have my menu, my "show list" function (mostrar_lista) and my "add function" (anadir_elemento) but i have problems with guardar (my save function).
When I use my save function (guardar) i can't save anything, my file "records.txt" just collapses and i have a file with 700.000 Kbytes.
The code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct unDisco{
char titulo[100];
char artista[100];
short fecha;
char formato[50];
float precio;
struct unDisco *siguiente;
};
struct unDisco *primero, *ultimo;
void cargar(){
FILE *discoteca;
discoteca = fopen("records.txt","r");
if (discoteca==NULL){
return ;
}else{
char ayuda, titulo[100], artista[100], formato[50];
int cont=0, k, fecha, n;
float precio;
while((ayuda=fgetc(discoteca))!=EOF){
if (ayuda=='\n'){
cont++;
}
}
rewind(discoteca);
char linea[cont][1024];
for (k=0;k<cont;k++){
fgets(linea[k],1023,discoteca);
struct unDisco *disco=(struct unDisco *)malloc(sizeof(struct unDisco));
sscanf(linea[k]," %s %s %i %s %f", titulo,artista,&fecha,formato,&precio);
strcpy(disco->titulo, titulo);
strcpy(disco->artista, artista);
strcpy(disco->formato, formato);
disco->fecha=fecha;
disco->precio=precio;
if (primero==NULL) {
primero = disco;
ultimo = disco;
}
else {
ultimo->siguiente = disco;
ultimo = disco;
}
}
}
fclose(discoteca);
return ;
}
void mostrar_menu() {
printf("\n\nMenú:\n=====\n\n");
printf("1.- Añadir elementos\n");
printf("2.- Borrar elementos\n");
printf("3.- Mostrar lista\n");
printf("4.- Salir\n\n");
printf("Escoge una opción: ");fflush(stdout);
}
void anadir_elemento() {
struct unDisco *disco;
int data;
float prezo;
char titulo[100],artista[100],formato[50];
//reservamos memoria para el nuevo elemento
disco = (struct unDisco *) malloc (sizeof(struct unDisco));
printf("\nTitulo: "); fflush(stdout);
fscanf(stdin," %s",titulo);
printf("Artista: "); fflush(stdout);
fscanf(stdin," %s",artista);
printf("Fecha: "); fflush(stdout);
fscanf(stdin," %i",&data);
printf("Formato: "); fflush(stdout);
fscanf(stdin," %s",formato);
printf("Precio: "); fflush(stdout);
fscanf(stdin," %f",&prezo);
strcpy(disco->titulo, titulo);
strcpy(disco->artista, artista);
strcpy(disco->formato, formato);
disco->fecha=data;
disco->precio=prezo;
// el campo siguiente va a ser NULL por ser el último elemento de la lista
disco->siguiente = NULL;
// ahora metemos el nuevo elemento en la lista. lo situamos al final de la lista
//comprobamos si la lista está vacía. si primero==NULL es que no hay ningún elemento en la lista. también vale ultimo==NULL
if (primero==NULL) {
printf( "Primer elemento\n");
primero = disco;
ultimo = disco;
}
else {
// el que hasta ahora era el último tiene que apuntar al nuevo
ultimo->siguiente = disco;
// hacemos que el nuevo sea ahora el último
ultimo = disco;
}
}
void mostrar_lista() {
struct unDisco *auxiliar; // lo usamos para recorrer la lista
int i;
i=0;
auxiliar = primero;
printf("\nMostrando la lista completa:\n");
while (auxiliar!=NULL) {
printf( "Titulo: %s, Artista: %s, Fecha: %i, Formato: %s, Precio: %.2f",
auxiliar->titulo,auxiliar->artista,auxiliar->fecha,auxiliar->formato,auxiliar->precio);
auxiliar = auxiliar->siguiente;
i++;
}
if (i==0) printf( "\nLa lista está vacía!!\n" );
}
void guardar(){
FILE *discoteca;
struct unDisco *disco;
discoteca=fopen("records.txt","w");
while(disco->siguiente!=NULL){
fprintf(discoteca,"%s %s %i %s %.2f\n",
disco->titulo, disco->artista, disco->fecha, disco->formato, disco->precio);
}
fclose(discoteca);
}
int main(){
char opcion;
cargar();
primero = (struct unDisco *) NULL;
ultimo = (struct unDisco *) NULL;
do {
mostrar_menu();
fscanf(stdin," %c",&opcion);
switch ( opcion ) {
case '1': anadir_elemento();
break;
case '2': printf("No disponible todavía!\n");
break;
case '3': mostrar_lista(primero);
break;
case '4':
guardar();
exit( 1 );
break;
default: printf( "Opción no válida\n" );
break;
}
} while (opcion!='4');
return 0;
}
it seems logical that guardar receives the unDisco in parameter, something like
void guardar(struct unDisco *disco){
FILE *discoteca = fopen("records.txt","w");
while(disco != NULL) { /* <<< test changed */
fprintf(discoteca,"%s %s %i %s %.2f\n",
disco->titulo, disco->artista,
disco->fecha, disco->formato,
disco->precio);
disco = disco->siguiente; /* <<< added */
}
fclose(discoteca);
}

Resources