Help how to pass everything to Text in C [closed]

0

The code creates nodes and saves them in a file .bin and at the end saves them and when I return it opens it recovers what the binary file already has. All this is done with the "int" or a number.

What I want is that instead of doing it with a number, I want everything to be with text and that is what I can not do. OK if someone can help me with the same variable of valor I want that instead of int is char , do not modify anything just write text instead of numbers. Please help. I am sorry if I do not express myself well but if someone helps me I would appreciate it very much

    #include<stdlib.h>
#include<stdio.h>
#include<windows.h>

typedef struct NODE{ // En C hay que hacer typedef...
    int longitud;
    char *caracteres;
    node *ptrSiguiente; //me tira error "[Error] 'node' does not name a type"
} node;

node *ptrInicio = NULL;
node *ptrActual = NULL;
node *ptrNuevo = NULL;
node *ptrTemp = NULL;

void CrearNodo(char,int); // me dice "[Note] declared here"
void ImprimirNodos();
void GuardarLista();
void LeeNodoDesdeArchivo();
void Buscar(int bval);

int main(){

    LeeNodoDesdeArchivo();

    //Menu
    int opt = 1,bval=0;

    while(opt != 4){
        system("cls");
        printf("Menu de aplicacion\n\n");
        printf("1. Agregar Nodo\n");
        printf("2. Imprimir Lista\n");
        printf("3. Buscar\n");
        printf("4. Salir\n\n");
        printf("Seleccione una opcion: "); scanf("%d",&opt);

        if(opt == 1){
            char texto[10];
            system("cls");
            printf("Agregar Nuevo Nodo\n\n");
            printf("Ingrese Valor del Nodo: "); scanf("%s",&texto);
            CrearNodo(texto); //aqui me dice "[Error] invalid conversion from 'char*' to 'char' [-fpermissive]" y tambien "[Error] too few arguments to function 'void CrearNodo(char, int)'"
            printf("\n\nNodo Creado!"); 
            system("pause");
        }

        if(opt == 2){
            system("cls");
            printf("Lista Actual:\n\n");
            ImprimirNodos();
            system("pause");
        }

        if(opt == 3){
            system("cls");
            printf("Buscar en la lista\n\n");
            printf("Ingrese valor de busqueda: "); scanf("%d",&bval);
            Buscar(bval);
            system("pause");
        }

    }

    GuardarLista(); 
}

void ImprimirNodos(){
    //Volvemos al inicio de la lista
    ptrTemp = ptrInicio;

    //Recorremos la lista   
    while(ptrTemp != NULL){
        printf("%d \n",ptrTemp->texto); // tambien aqui "[Error] 'node' has no member named 'texto'" lo que no se si la de lee nodo era aqui o lee nodo la cambiaba por cargar lista
        ptrTemp = ptrTemp->ptrSiguiente;
    }   

}

void Buscar(int bval){
    ptrTemp = ptrInicio;
    bool encontrado = false;
    int i=0;

    while(ptrTemp != NULL){
        if(ptrTemp->valor == bval){
            printf("Valor Encontrado!");
            printf("Valor en la Posicion: %d\n\n",i);

            encontrado = true;
        }

        i++;
        ptrTemp = ptrTemp->ptrSiguiente;

    }
    if(!encontrado){
        printf("El valor no existe en la lista.\n\n");
    }
}

void LeeNodoDesdeArchivo(FILE *archivo, node *nodo)
{
    fread(&nodo->longitud, sizeof(int),1,file);
    nodo->caracteres = (char*) malloc(nodo->longitud + 1);
    fread(&nodo->caracteres, sizeof(char),nodo->longitud,file);
    nodo->caracteres[nodo->longitud] = 0;
}


void GuardarLista(){
    ptrActual = ptrInicio;
    FILE *file = fopen("lista.bin","wb");

    while(ptrActual != NULL){
        // Guardamos la cantidad de caracteres que ocupa este nodo
        // pues lo necesitaremos para recuperar (leer) desde archivo.
        fwrite(ptrActual->longitud,sizeof(int),1,file);
        // Guardamos los caracteres, la longitud no incluye el
        // caracter final de cadena.
        fwrite(ptrActual->caracteres,sizeof(char),longitud,file);
        ptrActual = ptrActual->ptrSiguiente;
    }

    fclose(file);
}

void CrearNodo(char *texto, int longitud){

    // No es necesario duplicar la logica de creacion del nodo
    // hazlo tan solo una vez.
    ptrNuevo = (node*) malloc(sizeof(node));
    ptrActual->ptrSiguiente = NULL;

    // Solicitamos tantos caracteres como larga sea la cadena
    // anyadiendo uno mas para el carácter nulo
    ptrNuevo->caracteres = (char*) malloc(longitud + 1);
    memcpy(ptrNuevo->caracteres, texto, longitud);
    ptrNuevo->caracteres[longitud] = 0;

    if(ptrInicio == NULL){
        //Primer Nodo
        ptrInicio = ptrNuevo;
        ptrActual = ptrInicio;
    }else{
        ptrActual->ptrSiguiente = ptrNuevo;
        ptrActual = ptrNuevo;
    }   
}
    
asked by Fernando Banegas 13.04.2017 в 03:29
source

1 answer

4

Unlike a whole number, a string of characters ( string ) does not have a fixed size. In other words, both the number 1 and the number 7654321 occupy 32bits 1 , but the chains "Ataulfo Perez de la Chinchilla" and "Paco Pocero" occupy 30 and 11 bits respectively 2 .

So, to store text data you can not use the node as you have it and you can not use the same file writing logic either; in this case you should separate the text data into two components:

  • Length.
  • Characters.

To do this, your node should be like this:

typedef struct NODE{ // En C hay que hacer typedef...
    int longitud;
    char *caracteres;
    node *ptrSiguiente;
} node;

This means that your nodes will no longer occupy a homogeneous size in memory, but depending on how long the chain they store will occupy more or less; this affects the logic of reading, saving and creation.

The logic to create it should change as follows:

void CrearNodo(char *texto, int longitud){

    // No es necesario duplicar la logica de creacion del nodo
    // hazlo tan solo una vez.
    ptrNuevo = (node*) malloc(sizeof(node));
    ptrActual->ptrSiguiente = NULL;

    // Solicitamos tantos caracteres como larga sea la cadena
    // anyadiendo uno mas para el carácter nulo
    ptrNuevo->caracteres = (char*) malloc(longitud + 1);
    memcpy(ptrNuevo->caracteres, texto, longitud);
    ptrNuevo->caracteres[longitud] = 0;

    if(ptrInicio == NULL){
        //Primer Nodo
        ptrInicio = ptrNuevo;
        ptrActual = ptrInicio;
    }else{
        ptrActual->ptrSiguiente = ptrNuevo;
        ptrActual = ptrNuevo;
    }   
}

The saving logic must take into account the variable size of the nodes, instead of saving the nodes as monolithic blocks they must be saved component by component:

void GuardarLista(){
    ptrActual = ptrInicio;
    FILE *file = fopen("lista.bin","wb");

    while(ptrActual != NULL){
        // Guardamos la cantidad de caracteres que ocupa este nodo
        // pues lo necesitaremos para recuperar (leer) desde archivo.
        fwrite(ptrActual->longitud,sizeof(int),1,file);
        // Guardamos los caracteres, la longitud no incluye el
        // caracter final de cadena.
        fwrite(ptrActual->caracteres,sizeof(char),longitud,file);
        ptrActual = ptrActual->ptrSiguiente;
    }

    fclose(file);
}

Notice that only saves longitud and caracteres , it does not make sense to save the pointer to the next node since its value will change for each execution of the program. As for the reading from file, it will be done in the same way: reading the length first and then the characters, let's see:

void LeeNodoDesdeArchivo(FILE *archivo, node *nodo)
{
    fread(&nodo->longitud, sizeof(int),1,file);
    nodo->caracteres = (char*) malloc(nodo->longitud + 1);
    fread(&nodo->caracteres, sizeof(char),nodo->longitud,file);
    nodo->caracteres[nodo->longitud] = 0;
}

To be taken into account.

There are things in your code that, despite not being incorrect, need to be pointed out.

  • Avoid the use of global variables: global variables make it more difficult to follow the logic of the code, transform ptrInicio , ptrActual , ptrNuevo and ptrTemp in local variables.
  • You should check the return of fopen instead of using its return directly: in case the file opening fails fopen will return NULL and use a pointer to FILE null causes errors at run time .
  • Instead of a string of if , change the action check to be performed for switch .

1 On 32-bit platforms, they could occupy 64 on 64-bit platforms or 16 on 16-bit platforms.

2 It can also vary according to the platform.

    
answered by 13.04.2017 в 09:06