C iteration with two structs - c

The program should print the username of the user who has uploaded at least three videos.
I think that the problem is with the last nested for, the first row that is printed is correct, but the others aren't.
These are the files:
Archivio.txt
Ciro Esposito cir0esp ciro.esposito#gmail.com
Gennaro Sorrentino gennSor gennaro.sorrentino#gmail.com
Pasquale Zemma pasZem pasquale.zemma#gmail.com
Video.txt
cir0esp ciro.esposito#gmail.com Io_al_mare 15 34
pasZem pasquale.zemma#gmail.com Festa_di_laurea 358 623
gennSor gennaro.sorrentino#gmail.com Io_allo_stadio 45 97
cir0esp ciro.esposito#gmail.com Io_in_montagna 446 814
gennSor gennaro.sorrentino#gmail.com Io_al_parco 66 124
cir0esp ciro.esposito#gmail.com Io_in_auto 10 23
The code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
struct DATI{ // STRUTTURA NON DINAMICA
char nome [N];
char cognome [N];
char username[N];
char email [N];
};
struct DATI dati [N];
struct PROFILO{ // STRUTTURA NON DINAMICA
char username [N];
char email [N];
char titolo_video [N];
int durata_video;
int dimensione_video;
};
struct PROFILO profilo [N];
struct UTENTI{ // LINKED LIST
char* account;
struct UTENTI *next;
};
typedef struct UTENTI utenti;
// PROTOTIPO FUNZIONI
void Lista_utenti(FILE *ptr_archivio);
void Info_video(FILE *ptr_dati, FILE *ptr_video);
// MAIN
int main (){
FILE *ptr_archivio; //LINKED LIST
FILE *ptr_video;
FILE *ptr_dati;
// PER LA LINKED LIST
ptr_archivio = fopen("Archivio.txt" , "r");
// CONFRONTO ARCHIVIO E VIDEO
ptr_video = fopen("Video.txt" , "r");
ptr_dati = fopen("Archivio.txt" , "r");
Lista_utenti(ptr_archivio);
Info_video(ptr_dati, ptr_video);
return 0;
}
// DEFINIZIONE FUNZIONI
void Lista_utenti(FILE *ptr_archivio){ // FUNZIONE PER LA LINKED LIST
char lista [N];
utenti *current, *head;
head = current = NULL;
if (ptr_archivio == NULL){
printf("Errore, file non trovato!");
}
else{
while(fgets(lista,sizeof(lista), ptr_archivio)){
utenti *node = malloc(sizeof(utenti));
node->account = strdup(lista);
node->next = NULL;
if(head == NULL){
current = head = node;
}
else {
current = current->next = node;
}
}
fclose(ptr_archivio);
}
printf("LINKED LIST UTENTI\n");
for(current = head; current ; current=current->next){
printf("%s->", current->account);
}
printf("NULL\n");
}
void Info_video(FILE *ptr_dati, FILE *ptr_video){ // FUNZIONE PER CONFRONTO FILE ARCHIVIO E VIDEO
int counter = 0;
int j = 0;
int i = 0;
int totale = 0;
char video [N];
char archivio[N];
if (ptr_dati == NULL){
printf("Errore, file non trovato!");
}
else {
while(fgets(archivio, N, ptr_dati)!= NULL){
sscanf(archivio, "%s %s %s %s", dati[i].nome, dati[i].cognome, dati[i].username, dati[i].email);
printf("\n\n");
printf("Nome: %s\n" , dati[i].nome);
printf("Cognome: %s\n" , dati[i].cognome);
printf("Username: %s\n" , dati[i].username);
printf("Email: %s\n" , dati[i].email);
printf("\n\n");
i++;
}
}
fclose(ptr_dati);
if (ptr_video == NULL){
printf("Errore, file non trovato!");
}
else {
while(fgets(video, N, ptr_video)!= NULL){
sscanf(video, "%s %s %s %d %d", profilo[i].username, profilo[i].email, profilo[i].titolo_video, &profilo[i].durata_video, &profilo[i].dimensione_video);
printf("\n\n");
printf("Username: %s\n" , profilo[i].username);
printf("Email: %s\n" , profilo[i].email);
printf("Titolo video: %s\n" , profilo[i].titolo_video);
printf("Durata video: %d secondi\n" , profilo[i].durata_video);
printf("Dimensione video: %d mb\n" , profilo[i].dimensione_video);
totale = totale + profilo[i].durata_video;
i++;
printf("\n\n");
}
fclose(ptr_video);
}
printf("La durata totale di tutti i video caricati e' di %d secondi\n" , totale);
for(i=0; i<N; i++){
for (j=0; j<N; j++){
if (strcmp(dati[i].username,profilo[j].username)== 0){
counter = counter+1;
if (counter == 3){
printf("\nIl seguente utente %s ha caricato almeno 3 video" , dati[i].username);
counter = 0;
}
}
}
}
}

This is wrong:
for(i=0; i<N; i++){
for (j=0; j<N; j++){
You don't have N valid elements in dati and profilo, that's just the maximum. You should save the value of the counter after you read the user and video information. I've added variables dati_count and profilo_count.
You also need to set i back to 0 before the loop that reads from ptr_video, so that you fill in the profilo array from the beginning.
And you should check whether sscanf() succeeds.
#Include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100
struct DATI{ // STRUTTURA NON DINAMICA
char nome [N];
char cognome [N];
char username[N];
char email [N];
};
struct DATI dati [N];
int dati_count;
struct PROFILO{ // STRUTTURA NON DINAMICA
char username [N];
char email [N];
char titolo_video [N];
int durata_video;
int dimensione_video;
};
struct PROFILO profilo [N];
int profilo_count;
struct UTENTI{ // LINKED LIST
char* account;
struct UTENTI *next;
};
typedef struct UTENTI utenti;
// PROTOTIPO FUNZIONI
void Lista_utenti(FILE *ptr_archivio);
void Info_video(FILE *ptr_dati, FILE *ptr_video);
// MAIN
int main (){
FILE *ptr_archivio; //LINKED LIST
FILE *ptr_video;
FILE *ptr_dati;
// PER LA LINKED LIST
ptr_archivio = fopen("Archivio.txt" , "r");
// CONFRONTO ARCHIVIO E VIDEO
ptr_video = fopen("Video.txt" , "r");
ptr_dati = fopen("Archivio.txt" , "r");
Lista_utenti(ptr_archivio);
Info_video(ptr_dati, ptr_video);
return 0;
}
// DEFINIZIONE FUNZIONI
void Lista_utenti(FILE *ptr_archivio){ // FUNZIONE PER LA LINKED LIST
char lista [N];
utenti *current, *head;
head = current = NULL;
if (ptr_archivio == NULL){
printf("Errore, file non trovato!");
}
else{
while(fgets(lista,sizeof(lista), ptr_archivio)){
utenti *node = malloc(sizeof(utenti));
node->account = strdup(lista);
node->next = NULL;
if(head == NULL){
current = head = node;
}
else {
current = current->next = node;
}
}
fclose(ptr_archivio);
}
printf("LINKED LIST UTENTI\n");
for(current = head; current ; current=current->next){
printf("%s->", current->account);
}
printf("NULL\n");
}
void Info_video(FILE *ptr_dati, FILE *ptr_video){ // FUNZIONE PER CONFRONTO FILE ARCHIVIO E VIDEO
int counter = 0;
int j = 0;
int i = 0;
int totale = 0;
char video [N];
char archivio[N];
if (ptr_dati == NULL){
printf("Errore, file non trovato!");
}
else {
while(fgets(archivio, N, ptr_dati)!= NULL){
if (sscanf(archivio, "%s %s %s %s", dati[i].nome, dati[i].cognome, dati[i].username, dati[i].email) != 4) {
continue;
}
printf("\n\n");
printf("Nome: %s\n" , dati[i].nome);
printf("Cognome: %s\n" , dati[i].cognome);
printf("Username: %s\n" , dati[i].username);
printf("Email: %s\n" , dati[i].email);
printf("\n\n");
i++;
}
}
fclose(ptr_dati);
dati_count = i;
if (ptr_video == NULL){
printf("Errore, file non trovato!");
}
else {
i = 0;
while(fgets(video, N, ptr_video)!= NULL){
if (sscanf(video, "%s %s %s %d %d", profilo[i].username, profilo[i].email, profilo[i].titolo_video, &profilo[i].durata_video, &profilo[i].dimensione_video) != 5) {
continue;
}
printf("\n\n");
printf("Username: %s\n" , profilo[i].username);
printf("Email: %s\n" , profilo[i].email);
printf("Titolo video: %s\n" , profilo[i].titolo_video);
printf("Durata video: %d secondi\n" , profilo[i].durata_video);
printf("Dimensione video: %d mb\n" , profilo[i].dimensione_video);
totale = totale + profilo[i].durata_video;
i++;
printf("\n\n");
}
fclose(ptr_video);
profilo_count = i;
}
printf("La durata totale di tutti i video caricati e' di %d secondi\n" , totale);
for(i=0; i<dati_count; i++){
for (j=0; j<profilo_count; j++){
if (strcmp(dati[i].username,profilo[j].username)== 0){
counter = counter+1;
if (counter == 3){
printf("\nIl seguente utente %s ha caricato almeno 3 video" , dati[i].username);
counter = 0;
}
}
}
}
}

Related

Multiple fscanf statements in a loop. How do I get when EOF is reached?

I'm having problems while reading a file -again.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct camion {
int data[3];
int numeropacchi;
char *hubprovenienza[100];
_Bool iseccezionale;
};
int main(void) {
struct camion **listacamion = malloc(sizeof(struct camion * ));
listacamion[0] = calloc(1, sizeof(struct camion));
int numerocamion = 0;
//importazione
FILE *input = fopen("info.txt", "r");
if (input != NULL) {
char *temp = calloc(100, sizeof(char));
for (int i = 0; true; i++) {
//1, 2, 3
fscanf(input, "%d - %d - %d",
&listacamion[i]->data[0],
&listacamion[i]->data[1],
&listacamion[i]->data[2]);
printf("ORA %d-%d-%d\n",
listacamion[i]->data[0],
listacamion[i]->data[1],
listacamion[i]->data[2]);
fscanf(input, "%d", &listacamion[i]->numeropacchi);
printf("NUMERO PACCHI %d\n", listacamion[i]->numeropacchi);
if (fscanf(input, "%s", listacamion[i]->hubprovenienza) == EOF) {
listacamion[i]->iseccezionale = false;
break;
}
printf("HUB PROVENIENZA %s\n", listacamion[i]->hubprovenienza);
//4
char eccezionale;
long i_senoneccezionale = ftell(input);
if (fscanf(input, "%s", temp) == EOF)
break;
else { //if not EOF alloc mem for the next truck
listacamion = realloc(listacamion, sizeof(struct camion *) * (i + 1));
listacamion[i + 1] = calloc(1, sizeof(struct camion))
numerocamion++;
printf("RIALLOCATA!\n");
}
if (temp[0] == 'E') //if 'E' is there, bool is true
listacamion[i]->iseccezionale = true;
else {
//otherwise go back to the saved pointer
listacamion[i]->iseccezionale = false;
fseek(input, i_senoneccezionale, SEEK_SET);
}
//set temp to zero;
free(temp);
temp = calloc(100, sizeof(char));
//---
printf("YES OR NO %d\n\n", listacamion[i]->iseccezionale);
}
}
//---
return 0;
}
Here's the input file I use:
22 - 03 - 2020
39
Bergamo
E
30 - 05 - 2021
90
Napoli
19 - 02 - 2022
132
Bari
21 - 03 - 2022
1721
Modena
E
I've got 3 or 4 lines per camion (truck) in my file, depending on whether the load is oversized or not (if it is, then an 'E' is put, otherwise the line in the file doesn't exist). So the end of the file could be detected either at the third fscanf or the fourth, but I'm not sure fscanf works this way... The issue is that the loop is correctly executed 3 times out of 4 (I've got the info of 4 trucks), then I get a segmentation fault, so I assumed that the problem might be an inadequate detection of the end of the file. I've tried other options - feof for example - but they weren't useful, and I can only find examples of a fscanf used as a condition, while my condition is just a true because I have different fscanfs...
Here's my output:
ORA 22-3-2020
NUMERO PACCHI 39
HUB PROVENIENZA Bergamo
RIALLOCATA!
YES OR NO 1
ORA 30-5-2021
NUMERO PACCHI 90
HUB PROVENIENZA Napoli
RIALLOCATA!
YES OR NO 0
ORA 19-2-2022
NUMERO PACCHI 132
HUB PROVENIENZA Bari
RIALLOCATA!
--------------------------------
Process exited after 0.4117 seconds with return value 3221226356
You should test the return value of every call to fscanf(): fscanf returns the number of successful conversions. A return value different from the number of conversions requested is an indication of invalid or missing input. Both must be handled to avoid undefined behavior.
fscanf(input, "%s", temp) is risky: a word longer than 99 bytes will cause a buffer overflow. You should write fscanf(input, "%99s", temp)
Here is a modified version using an array of structures instead of an array of pointers:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct camion {
int data[3];
int numeropacchi;
char *hubprovenienza[100];
_Bool iseccezionale;
};
int main() {
struct camion *listacamion = NULL;
struct camion cam;
char ebuf[2];
int numerocamion = 0;
//importazione
FILE *input = fopen("info.txt", "r");
if (input != NULL) {
while (fscanf(input, "%d - %d - %d\n%d\n%99s",
&cam.data[0], &cam.data[1], &cam.data[2],
&cam.numeropacchi,
cam.hubprovenienza) == 5) {
cam.iseccezionale = false;
if (fscanf(input, " %1[E]", ebuf) == 1)
cam.iseccezionale = true;
printf("ORA %d-%d-%d\n"
"NUMERO PACCHI %d\n"
"HUB PROVENIENZA %s\n"
"YES OR NO %d\n\n",
cam.data[0], cam.data[1], cam.data[2]);
cam.numeropacchi,
cam.hubprovenienza,
cam.iseccezionale);
// if new truck, append to array
listacamion = realloc(listacamion, sizeof(*listacamion) * (numerocamion + 1));
listacamion[numerocamion] = cam;
numerocamion++;
printf("RIALLOCATA!\n");
}
}
return 0;
}
Check the return value of every call to scanf. You can refactor your code to make it simpler. Try something like:
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
struct camion {
int data[3];
int numeropacchi;
char hubprovenienza[100];
_Bool iseccezionale;
};
int
get_record(FILE *fp, struct camion *c)
{
/* Read up to one record from the file. Return 1 on success. */
if( 3 != fscanf(fp, "%d -%d -%d", c->data, c->data + 1, c->data + 2) ){
return 0;
}
if( 1 != fscanf(fp, "%d", &c->numeropacchi) ){
return 0;
}
if( 1 != fscanf(fp, "%99s", c->hubprovenienza) ){
return 0;
}
int k;
while( ( k = fgetc(fp)) != EOF && isspace(k) ){
;
}
if( k == 'E' ){
c->iseccezionale = 1;
} else {
c->iseccezionale = 0;
ungetc(k, fp);
}
return 1;
}
int
main(int argc, char **argv)
{
struct camion c;
while( get_record(stdin, &c) ){
printf(
"%s is %soversized\n",
c.hubprovenienza,
c.iseccezionale ? "" : "not "
);
}
return 0;
}
Okay, this morning I've tried again and now it's working. Thanks to your comments I've paid more attention to the fscanf return value; I've also realized that I could get an EOF from either the 1st line per truck or the 4th one, not 3rd and 4th.
I didn't know whether to delete this question or what... so I've decided to post the code that worked for me just in case it might turn useful to some C beginners like me in the future because it contains a couple of things I wish I knew before. I'm also quite sure there's a faster way to do so, but who knows...
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct camion {
int data[3];
int numeropacchi;
char* hubprovenienza[100];
_Bool iseccezionale;
};
int main(void) {
struct camion** listacamion=malloc(sizeof(struct camion*));
listacamion[0]=calloc(1, sizeof(struct camion));
int numerocamion=0;
//importazione
FILE* input=fopen("info.txt", "r");
if(input!=NULL) {
char* temp=calloc(100, sizeof(char));
_Bool primavolta=true;
for(int i=0; true; i++) {
int fs1, fs4;
int temp1, temp2, temp3;
//1
if((fs1=fscanf(input, "%d - %d - %d", &temp1, &temp2, &temp3) == EOF))
break;
else {
numerocamion++;
if(primavolta) {
primavolta=false;
listacamion[i]->data[0]=temp1;
listacamion[i]->data[1]=temp2;
listacamion[i]->data[2]=temp3;
}
else {
//EVENTUALE RIALLOCAZIONE
listacamion=realloc(listacamion, sizeof(struct camion*)*(i+1));
listacamion[i]=calloc(1, sizeof(struct camion));
//---
listacamion[i]->data[0]=temp1;
listacamion[i]->data[1]=temp2;
listacamion[i]->data[2]=temp3;
}
}
//2
fscanf(input, "%d", &listacamion[i]->numeropacchi);
//3
fscanf(input, "%s", listacamion[i]->hubprovenienza);
//4
char eccezionale;
long i_senoneccezionale=ftell(input);
if((fs4=fscanf(input, "%s", temp)) == EOF) {//se è la fine del file...
listacamion[i]->iseccezionale=false;
free(temp);
break;
}
else {
if(temp[0]=='E') //se esiste il carattere 'E' - e quindi la quarta riga ESISTE - assegna il valore positivo alla booleana
listacamion[i]->iseccezionale=true;
else { /*se invece NON esiste il carattere 'E', ripristina il puntatore al file alla stessa riga che avrebbe dovuto contenere la 'E',
così che questo non vada perso per la prossima chiamata a scanf per la prima riga di ciascun camion, quella contenente la data*/
listacamion[i]->iseccezionale=false;
fseek(input, i_senoneccezionale, SEEK_SET);
}
}
//ripristina memoria per temp;
free(temp);
temp=calloc(100, sizeof(char));
//---
}
}
//---
//output
for(int i=0; i<numerocamion; i++) {
printf("%d-%d-%d %d %s %d\n", listacamion[i]->data[0], listacamion[i]->data[1], listacamion[i]->data[2], listacamion[i]->numeropacchi, listacamion[i]->hubprovenienza, listacamion[i]->iseccezionale);
}
return 0;
}

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.

Write and Read struct to Binary File in C (netbeans) doesnt work

## MY STRUCT ##
typedef struct clientes{
int cod_cliente;
char name[100];
char country[100];
char city[100];
char email[100];
int nif;
char n_passporte[50];
char n_carta_conducao[50];
char telefone[50];
}CLIENTE;
typedef struct Elem{
VEICULO info_veiculo;
CLIENTE info_cliente;
ALUGADO info_alugado;
struct Elem *seguinte;
}ELEMENTO;
## FUNCTIONS ##
int saveBinaryCliente(ELEMENTO *iniLista){
ELEMENTO *aux = NULL;
FILE *fp = NULL;
int res=0;
fp = fopen("clientes.dat", "wb");
if(fp == NULL){
printf("Erro ao abrir o ficheiro clientes!\n");
return -1;
}
for(aux=iniLista; aux!=NULL; aux=aux->seguinte){
/*
printf("%i %s %s %s %i %s %s %s %s\n", aux->info_cliente.cod_cliente, aux->info_cliente.nome, aux->info_cliente.pais, aux->info_cliente.cidade, aux->info_cliente.nif, aux->info_cliente.n_passporte, aux->info_cliente.n_carta_conducao, aux->info_cliente.email, aux->info_cliente.telefone);
*/
Receives every parameter until this printf above
res = fwrite(aux, sizeof(CLIENTE), 1, fp);
}
fclose(fp);
printf("Saved %i register clientes!\n", res);
return 0;
}
int readDataCliente(ELEMENTO **iniLista){
CLIENTE aux;
int res=0;
FILE *fp = NULL;
fp = fopen("clientes.dat", "rb");
if(fp == NULL){
printf("Error reading file clientes!\n");
return -1;
}
while (!feof(fp)){
res = fread(&aux, sizeof(CLIENTE), 1, fp);
if (res){
inserirCliente(&(*iniLista), aux);
}
}
fclose(fp);
return 0;
}
## OUTPUT ##
LISTING BEFORE CLOSING WITH 1 CLIENT INSERTED
1 nuno portugal porto 23421342 ASDFA0942 ASDF-434 ssss#hotmail.com +351093856273
**AFTER CLOSING PROGRAM AND SAVE TO BINARY FILE**
*****************************************************
* MENU CLIENTES *
*****************************************************
* *
* 1 - INSERT NEW CLIENTE *
* 2 - CHANGE INFO CLIENTE *
* 3 - LIST CLIENTES *
*****************************************************
Choose your CHOICE: 3
0 0
0 0
strange fact...all seemed to work before. Dunno why doesnt work now and it also saves when I dont insert a client and reads it. I have been poking my head for a while so i decided to ask you guys for your help, thank you.

C Passing char array to function using structs

We have a small program where the input comes from a text file (see text sample below) and is used to scan and write certain student information to different struct variables. However, when the add_student() function is called it gives this bizzare output (see screenshot below).
struct student_list sl;
struct teacher_list tl;
struct data {
char *name;
int number;
char index;};
struct student {
struct data *d;
struct student *next;};
struct student_list{
int size;
struct student *front;
struct student *tail;};
struct teacher{
struct data *d;
struct teacher *next;};
struct teacher_list{
int size;
struct teacher *front;
struct teacher *tail;};
void main()
{
readAndLoad();
print_students();
}
void readAndLoad()
{
int c;
int i=0;
char line[200];
int number, semNum;
char name[100];
char index;
while ((c=getchar())!=EOF)
{
if(c != '\n')
{
line[i++] = c;
line[i] = '\0';
/*printf("%c ", c);
printf("%s \n", line);*/
}else
{
//printf("\n");
int j, b;
b = 0;
for (j = 0; j < sizeof(line); j++)
{
if (line[j] == ' ')
++b;
}
//printf("%s \n", line);
if (b == 2)
{
if (line[0] == 'S')
{
sscanf(line, "S %d %s", &number, name);
struct student *studentnode;
studentnode = malloc(sizeof(struct student));
add_student(&studentnode, number, &name);
} else if (line[0] == 'T')
{
sscanf(line, "T %d %s", &number, name);
struct teacher *teachernode;
teachernode = malloc(sizeof(struct teacher));
add_teacher(&teachernode, number, &name);
}
}
memset(&line[0], 0, sizeof(line));
i=0;
}
}
//printf(line);
}
void add_student(struct student *n, int student_number, char *student_name)
{
//---------------------------------------------------
printf("%s\n", student_name);
n->d->name = student_name;
n->d->number = student_number;
n->d->index = 'S';
n->next = 0;
printf("%s\n", n->d->name);
//---------------------------------------------------
if (sl.size == 0)
{
sl.front = n;
sl.tail = n;
printf("%s %d \n", n->d->name, n->d->number);
} else
{
sl.tail->next = n;
sl.tail = n;
printf("%s %d \n", n->d->name, n->d->number);
}
sl.size++;
printf("Student added\n");
}
void add_teacher(struct teacher *n, int number, char *name)
{
n->d->name = name;
n->d->number = number;
n->d->index = 'T';
n->next = 0;
if (tl.size == 0)
{
tl.front = n;
tl.tail = n;
} else
{
tl.tail->next = n;
tl.tail = n;
}
tl.size++;
printf("Teacher added\n");
}
void print_students()
{
int i;
struct student *s = sl.front;
for (i = 0; i < sl.size; i++)
//while (s->next != 0)
{
if (i == (sl.size - 2))
{
printf("%c %s %d", s->d->index, s->d->name, s->d->number);
} else
{
printf("%c %s %d \n", s->d->index, s->d->name, s->d->number);
s = s->next;
}
}
}
Input text file sample
here is the output
Between the highlighted part //-------------------
in the code we can see a correct output of the name from the first printf() but when we go to the second printf() it only prints the blank space... Do you know what could be the problem?
Input text file:
S 123456 Ivan
S 654321 Georgi
T 123456 Jesper
T 123457 Ole
T 123458 Lars
T 123459 Erland
C 31 CALI1 3
C 11 WDDI1 1
C 21 SDJI2 2
E 123456 31
E 123456 11
E 654321 21
A 123456 31
A 123457 11
Console output:
Ivan
123456
Student added
Georgi
,▒( 654321
Student added
Teacher added
Teacher added
Teacher added
Teacher added
E 0▒( 2673448E 0▒( 2673448
studentnode = malloc(sizeof(struct student));
only allocates memory for an instance of student. The memory for studentnode->d has not been allocated. Therefore any n->d->something in add_student() is invalid, thus invokes undefined behavior.

can't copy/read in right mode from a file to a list

i've a problem with read/write from file and view correctly the input:
// LOAD THE LIST FROM THE FILE
struct elemento *caricalista(struct elemento *p) {
struct elemento *punt;
FILE * utenti = fopen ("miarubrica.txt", "r");
char nome[MAX];
char cognome[MAX];
char telefono[MAX];
char mail[MAX];
if (utenti == NULL) {
printf("non ho caricato gli utenti");
} else {
while (!feof(utenti)) {
if (p != NULL) {
punt = (struct elemento *)malloc(sizeof(struct elemento));
fscanf(utenti, "%s", nome);
puts(nome);
fscanf(utenti, "%s", cognome);
puts(cognome);
fscanf(utenti, "%s", telefono);
puts(telefono);
fscanf(utenti, "%s", mail);
puts(mail);
strcpy(punt->nome, nome);
strcpy(punt->cognome, cognome);
strcpy(punt->telefono, telefono);
strcpy(punt->mail, mail);
punt->pun = p;
} else if (p == NULL) {
p = (struct elemento *)malloc(sizeof(struct elemento));
fscanf(utenti, "%s", nome);
fscanf(utenti, "%s", cognome);
fscanf(utenti, "%s", telefono);
fscanf(utenti, "%s", mail);
strcpy(p->nome, nome);
strcpy(p->cognome, cognome);
strcpy(p->telefono, telefono);
strcpy(p->mail, mail);
p->pun = NULL;
punt = p;
}
}
}
fflush(utenti);
fclose(utenti);
return(punt);
}
// SAVE THE LIST
int salva(struct elemento *p) {
FILE *stream = fopen("miarubrica.txt", "w");
while (p != NULL) {
// Scrive sul file
fprintf(stream, "%s ", p->nome);
fprintf(stream, "%s ", p->cognome);
fprintf(stream, "%s ", p->mail);
fprintf(stream, "%s \n", p->telefono);
p = p->pun;
}
fflush(stream);
fclose(stream);
return;
}
this write me (example)
pippo disney 02345432 pippodisney#pippodisney.com
in miarubrica.txt but when i read it with a method that read lists (it works), i see
pippo disney 02345432 pippodisney#pippodisney.com
pippo disney 02345432 pippodisney#pippodisney.com
two times in the shell. what's wrong?
Here's a quick fix. You've mixed the stuff with "->pun" pointer. I've removed the salva() method since you do not use it.
#include <stdio.h>
#include <malloc.h>
#define MAX (256)
struct elemento {
char nome[MAX], cognome[MAX], telefono[MAX], mail[MAX];
struct elemento* pun;
};
// LOAD THE LIST FROM THE FILE
struct elemento *caricalista(struct elemento *p) {
struct elemento *punt = p;
FILE * utenti = fopen ("miarubrica.txt","r");
if(!utenti) { printf("non ho caricato gli utenti"); return p; }
while(!feof(utenti)) {
punt= (struct elemento *)malloc(sizeof(struct elemento));
fscanf(utenti,"%s%s%s%s",
punt->nome, punt->cognome, punt->telefono, punt->mail);
printf("%s %s %s %s\n", /* print new element */
punt->nome, punt->cognome, punt->telefono, punt->mail);
punt->pun = p; /* old list at the end */
p = punt;
}
fclose(utenti);
return(punt);
}
int main() { caricalista(NULL); return 0; }
In caricalista there appears to be some confusion about whether you're prepending (putting the new entry before the one pointed to by p) or appending (put the new entry after the one pointed to by p).
For example, if p isn't NULL, it does punt->pun = p;, leaving p unchanged, but then on the next iteration it does the same.
Also, if the file is empty, it will return punt uninitialised.

Resources