0

I'm fairly new to C and I'm trying to make a program where I take names and other information from a text file and then store it on a .dat file. Here is my code:

#include <stdio.h>
#define MAX 30

typedef struct 
{
    char nombre[MAX];
    char apellido[MAX];
    char pais[MAX];
    unsigned int puntaje;
} Treg;


void ArmaBinario (FILE *archb);
void BuscaArchivo(FILE *archb);

void main (){
    FILE *archb; 

    ArmaBinario(archb); 
    BuscaArchivo(archb); 
}

void ArmaBinario (FILE *archb){
    FILE *archt;
    Treg ranking;
    char car; 
    int i; 

    archt = fopen("datos_ej26.txt","rt");

    if (archt == NULL) {
        printf("Error al abrir el archivo: el archivo no existe.");
    }
    else{
        archb = fopen("ranking.dat","wb");
        car = fgetc(archt);
        while (!feof(archt)){
            i = 0;
            while (car != ' ') {
                ranking.nombre[i] = car;
                i++;
                car = fgetc(archt);
            }
            car = fgetc(archt); car = fgetc(archt);
            i = 0;
            while (car != ' ') {
                ranking.apellido[i] = car;
                i++;
                car = getc(archt);
            }

            car = fgetc(archt); car = fgetc(archt);
            i = 0; 
            while (car != ' ') {
                ranking.pais[i] = car;
                i++;
                car = fgetc(archt);
            }

            fscanf(archt,"%u \n",&ranking.puntaje);
            fwrite(&ranking,sizeof(Treg),1,archb); 
            car = fgetc(archt);
            
        }

    } 

    fclose(archt);
    fclose(archb); 
 }


The structure of the text file is like this

Name Surname Country Points

When I run the program and then look into the .dat file I get no name and last name, usually the last characters of the country and then just an integer. For example for

John Smith Inglaterra 290

I get

Name: 
Country: terra
Points: 1685027142 

I'm sure the problem is in the handling of the characters, but I'm not sure what the exact issue is.

Thanks!

Morganuz
  • 55
  • 7
  • You are using `feof` incorrectly: https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – William Pursell Apr 03 '21 at 23:36
  • 1
    If your input is the string "John", and you only put 4 characters into `ranking.nombre`, but you write all 30 characters, bad things will happen. In particular, since the data was never initialized and never written to, reading from it is undefined behavior. Anything can happen. – William Pursell Apr 03 '21 at 23:42
  • Please note that `fgetc` returns an `int`, not a `char`. This is not by accident. You need to know the reason of this, and change your program accordingly. You should also understand that when you read the characters `'John'` into an array of 30 characters, you are left with 4 characters containing `'John'` and 26 characters containing garbage, unless you specifically do something about it. – n. m. could be an AI Apr 03 '21 at 23:43
  • @WilliamPursell `read_it(); while(!feof()) { ....; read_it(); }` works just fine (until you start getting real IO errors not caught by `feof`, that is). We used to write this way back when all the time. – n. m. could be an AI Apr 03 '21 at 23:48
  • @WilliamPursell I have read the link and superficially I have to agree. But this is the way I'm asked to do it on college. Would you say it's adequate for situations where there's a low chance of error? Or is it a never use it situation? Thanks for answering! – Morganuz Apr 04 '21 at 00:33
  • Also, what do you mean about the data not being initialized and written to? You mean on the new file? – Morganuz Apr 04 '21 at 00:37
  • Your code is self-contained: `BuscaArchivo()` is not defined. In `ArmaBinario()` the variable `archb` is not initialized if archt is NULL. I don't think it's valid to declare main() returning void opposed to int. Could be wrong though. – Allan Wind Apr 04 '21 at 00:43
  • @Morganuz Your program as written has the very real chance of entering an infinite loop. You need to check every call to `getchar` to detect an EOF. If the input stream is exhausted during `while (car != ' ') {`, the loop will never terminate. If you are being instructed to use `while(!feof())`, you should be very wary of the quality of the instruction. – William Pursell Apr 04 '21 at 02:37
  • I would suggest you do a function that you call for each token, e.g. `int getToken(FILE* archt, char* buffer, const size_t maxLen)` instead of having it as you have it now. – AndersK Apr 04 '21 at 10:34

1 Answers1

1

You have different issues :

  • you skip one character between each word
  • you do not initialize the Treg variable before using it at each beginning of new line
  • it is not very useful to pass FILE* variables to functions if not initialized before in main and also as file archb is closed in function, it can not be used as is after exiting function.
Ptit Xav
  • 3,006
  • 2
  • 6
  • 15