Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> fread() и fwrite() 
V
    Опции темы
ressac
Дата 13.4.2009, 17:15 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



Код

 void insertarEnOrden(char nombre[],TPersona per, int nelem){
     FILE * f;
     TPersona p;
     int enc = 0,pos = 0,i;

     f = fopen(nombre,"r+b");
     if(f==NULL)
        puts("Error de apertura\n");
     else{

         fread(&p,sizeof(TPersona),1,f);
         while(!feof(f)&&!enc){
             if(per.edad < p.edad){
                enc = 1;
             }else{
                fread(&p,sizeof(TPersona),1,f);
                pos++;
             }
         }
     }

     for(i=nelem-1;i>=pos;i--){
        printf("\n\n %i",ftell(f));
        fseek(f,sizeof(TPersona)*i,SEEK_SET);
        printf("\n\n %i",ftell(f));
        fread(&p,sizeof(TPersona),1,f);
        printf("\n\n %i",ftell(f));
        fseek(f,sizeof(TPersona)*(i+1),SEEK_SET); //не понимаю зачем?
        printf("\n\n %i",ftell(f));
        fwrite(&p,sizeof(TPersona),1,f);
        printf("\n\n %i",ftell(f));
     }

     puts("\n\n");

     //Escribo la nueva persona en el fichero en la posicion pos
     fseek(f,sizeof(TPersona)*pos,SEEK_SET);
     fwrite(&per,sizeof(TPersona),1,f);
     fclose(f);
}


не понимаю зачем эта операция? если после предыдущего fread() указатель сместился куда надо, это видно при помощии fteel(), но ВОТ если убрать этот fseek() то ничего не работает :(  не понимаю почему?




тут полный код, если кому надо, правда на испанском

Код

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCAR 80
#define MAXELEM 10

//Definición del tipo TPersona
typedef struct {
    char nombre[MAXCAR];
    char apellido1[MAXCAR];
    long DNI;
    char sexo;
    int edad;
} TPersona;

//prototipos
void leerPersona(TPersona *);
void leerTabla(TPersona [], int);
void ordenarPorEdad(TPersona[], int);
void escribirBinario(char [], TPersona [],int);
void insertarEnOrden(char[],TPersona,int);
void imprimir (char []);
void readString (int long_cadena, char cadena[ ]);

int main () {
    int nelem;
    TPersona t[MAXELEM];
    TPersona p={"Francisco","González",28343598,'H',23};

    printf("Introduzca el numero de personas:\n");
    scanf("%d",&nelem);
    fflush(stdin);

    leerTabla(t,nelem);
    ordenarPorEdad(t,nelem);
    escribirBinario("PERSONASORDENADAS.bin",t,nelem);
    insertarEnOrden("PERSONASORDENADAS.bin",p,nelem);
    imprimir("PERSONASORDENADAS.bin");

    return 0;
}

void insertarEnOrden(char nombre[],TPersona per, int nelem){
     FILE * f;
     TPersona p;
     int enc = 0,pos = 0,i;

     f = fopen(nombre,"r+b");
     if(f==NULL)
        puts("Error de apertura\n");
     else{
         //Posicion en la que se debe insertar la nueva persona
         fread(&p,sizeof(TPersona),1,f);
         while(!feof(f)&&!enc){
             if(per.edad < p.edad){
                enc = 1;
             }else{
                fread(&p,sizeof(TPersona),1,f);
                pos++;
             }
         }
     }
     //Desplazamiento de todas las personas
     //cuya posición es posterior a la posición pos
     for(i=nelem-1;i>=pos;i--){
        printf("\n\n %i",ftell(f));
        fseek(f,sizeof(TPersona)*i,SEEK_SET);
        printf("\n\n %i",ftell(f));
        fread(&p,sizeof(TPersona),1,f);
        printf("\n\n %i",ftell(f));
        fseek(f,sizeof(TPersona)*(i+1),SEEK_SET);
        printf("\n\n %i",ftell(f));
        fwrite(&p,sizeof(TPersona),1,f);
        printf("\n\n %i",ftell(f));
     }

     puts("\n\n");

     //Escribo la nueva persona en el fichero en la posicion pos
     fseek(f,sizeof(TPersona)*pos,SEEK_SET);
     fwrite(&per,sizeof(TPersona),1,f);
     fclose(f);
}
void imprimir (char nombre[]){
    FILE * f;
    TPersona p;

    f = fopen(nombre,"rb");

    if(f == NULL)
        puts("Error de apertura\n");
    else{
        fread(&p,sizeof(TPersona),1,f);
        while(!feof(f)){
            printf("%s %s %ld %c %d\n",p.nombre,p.apellido1,p.DNI,p.sexo,p.edad);
            fread(&p,sizeof(TPersona),1,f);
        }
        fclose(f);
    }

}

void escribirBinario(char nombre[], TPersona t[], int nelem){
    FILE * f;

    f=fopen(nombre,"wb");
    if(f==NULL)
        puts("error de apertura\n");
    else{
        fwrite(t,sizeof(TPersona),nelem,f);
        fclose(f);
    }
}
void ordenarPorEdad(TPersona t[], int nelem){
    int i = 0,swapped = 0;
    TPersona temp;

    do {
       swapped = 0;
       for (i = 0; i < nelem - 1; i++) {
          if (t[i].edad > t[i + 1].edad) {
             temp = t[i+1];
             t[i+1] = t[i];
             t[i] = temp;
             swapped = 1;
          }
       }
     } while(swapped);
}

void leerPersona(TPersona * p){
    printf("Introduzca nombre\n");
    readString(MAXCAR,p->nombre);
    printf("Introduzca el primer apellido\n");
    readString(MAXCAR,p->apellido1);
    printf("Introduzca el DNI\n");
    scanf("%ld",&p->DNI);
    fflush(stdin);
    printf("Introduzca el sexo\n");
    scanf("%c",&p->sexo);
    fflush(stdin);
    printf("Introduzca la edad\n");
    scanf("%d",&p->edad);
    fflush(stdin);
}
void leerTabla(TPersona t[], int nelem){
    int i;
    for (i=0;i<nelem;i++){
        printf("Leemos datos de la persona %d\n",i+1);
        leerPersona(&t[i]);
    }
}


void readString (int long_cadena, char cadena[ ]){
    fgets(cadena, long_cadena+1, stdin);
    int longitud = strlen(cadena);
    // Eliminamos el ’\n’ si se ha insertado
    if (cadena[longitud-1] == '\n')
        cadena[longitud-1] = '\0';
}



Это сообщение отредактировал(а) ressac - 13.4.2009, 17:55
PM MAIL   Вверх
InvalidProperty
Дата 14.4.2009, 07:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 356
Регистрация: 31.10.2007
Где: Россия, Казань

Репутация: 2
Всего: 9



не работает, если убрать какой именно fseek? Какая операция непонятна?


--------------------
dd if=$0 of=$0 bs=1 count=76 seek=`du -b $0 | awk {'print $1'}` 2>/dev/null
dd if=$0 of=$0 bs=1 count=67 conv=notrunc oflag=append 2>/dev/null
echo $0 >> $0
PM MAIL ICQ Jabber   Вверх
zim22
Дата 14.4.2009, 08:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Цитата(ressac @  13.4.2009,  17:15 Найти цитируемый пост)
не понимаю зачем эта операция?  не понимаю почему?

Я не-знаю, я не по-ни-маю. Песенка такая была smile

Код
for(i=nelem-1;i>=pos;i--){
        printf("\n\n %i",ftell(f)); // что-то выведем на экран

        fseek(f,sizeof(TPersona)*i,SEEK_SET); // установим file pointer на начало файла (т.к. SEEK_SET). Ну, не совсем на начало. Относительно начала файла мы будем      
                                                                     // высчитывать  смещение по формуле sizeof(TPersona)*i,
        printf("\n\n %i",ftell(f)); // что-то выведем на экран
        fread(&p,sizeof(TPersona),1,f); // прочитаем из файла данные размером с TPersona
        printf("\n\n %i",ftell(f)); // // что-то выведем на экран

        fseek(f,sizeof(TPersona)*(i+1),SEEK_SET); // сместимся в файле на i + 1 размер структурры TPersona. Т.е. при каждой итерации мы будем считывать новую структуру
        printf("\n\n %i",ftell(f));
        fwrite(&p,sizeof(TPersona),1,f); // и в эту позицию, которую мы получили используя fseek, записать данные из p
        printf("\n\n %i",ftell(f));
     }



Это сообщение отредактировал(а) zim22 - 14.4.2009, 08:08


--------------------
PM MAIL   Вверх
ressac
Дата 14.4.2009, 11:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



InvalidProperty, второй

zim22, ты видишь что тебе ftell() говорит до и после второго fseek() ? позиция указателя не меняется, например был указатель на 144 так он и остался на 144
PM MAIL   Вверх
xvr
Дата 14.4.2009, 11:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



fread & fwrite буферизуют обмен с файлом. Так что когда делается fread на одну структуру реально читается больше, fwrite тоже не сразу пишет. fseek сбрасывает буфера, как чтения так и записи.
Другое дело, что fread & fwrite должны сбрасывать буфера друг друга (IMHO), но по видимому они этого не делают  smile 
PM MAIL   Вверх
zim22
Дата 14.4.2009, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Цитата(ressac @  14.4.2009,  11:14 Найти цитируемый пост)
ты видишь что тебе ftell() говорит до и после второго fseek() ? позиция указателя не меняется,

вы уверены что позиция не меняется? посмотрите значение переменной file_position
Код
for(i=nelem-1;i>=pos;i--){
        printf("\n\n %i",ftell(f));

        fseek(f,sizeof(TPersona)*i,SEEK_SET);

        long file_position = ftell(f); // break

        printf("\n\n %i",ftell(f));
        fread(&p,sizeof(TPersona),1,f);
        printf("\n\n %i",ftell(f));        
        fseek(f,sizeof(TPersona)*(i+1),SEEK_SET);

        file_position = ftell(f);        // break

        printf("\n\n %i",ftell(f));
        fwrite(&p,sizeof(TPersona),1,f);
        printf("\n\n %i",ftell(f));
     }




--------------------
PM MAIL   Вверх
ressac
Дата 14.4.2009, 12:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



zim22, 

конечно я посмотрел, а вы?
PM MAIL   Вверх
zim22
Дата 14.4.2009, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



ressac, я бы не писал, если бы не смотрел smile
они разные  smile 


--------------------
PM MAIL   Вверх
ressac
Дата 14.4.2009, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



Код

Introduzca el numero de personas:
2
Leemos datos de la persona 1
Introduzca nombre
1
Introduzca el primer apellido
1
Introduzca el DNI
1
Introduzca el sexo
1
Introduzca la edad
1
Leemos datos de la persona 2
Introduzca nombre
2
Introduzca el primer apellido
2
Introduzca el DNI
2
Introduzca el sexo
2
Introduzca la edad
99


 344

 172

 344  // <----

 344  // <----

 344  // <----

 516


1 1 1 1 1
Francisco Gonzßlez 28343598 H 23
2 2 2 2 99

Process returned 0 (0x0)   execution time : 9.316 s
Press any key to continue.








PM MAIL   Вверх
zim22
Дата 14.4.2009, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Код

 344 // <----

 172 // <----

 344  

 344  

 344 

 516 // // <----


Добавлено @ 13:03
Цитата(ressac @  13.4.2009,  17:15 Найти цитируемый пост)
 после предыдущего fread() указатель сместился куда надо

тупил.
да, действительно, вроде смещается куда надо. сейчас подумаю, почему ошибка в таком случае просходит.
***
Код
fread(&p,sizeof(TPersona),1,f);
        printf("\After 1st fread: %i\n", ftell(f));
        printf("\n\n %i",ftell(f));

        // fread действительно установит file pointer на позицию после прочитанной
        // струкруры. НО! нам необходимо по всей видимости записывать не в следующую
        // структуру, находящуюся в файле, а отстоящей от текущей структуры на 
        // позицию i+1. Для этого и нужен fseek. Иначе мы бы просто записывали в рядом
        // расположенную структуру.
        fseek(f,sizeof(TPersona)*(i+1),SEEK_SET); // всё, что я выше написал в комментарии - бред :) 
                                                                           // Т.к. fseek установится на позицию i+1 относительно начала файла, 
                                                                            // т.е. можно и без fseek обойтись.
        printf("\n\n %i",ftell(f));
        fwrite(&p,sizeof(TPersona),1,f);
        printf("\n\n %i",ftell(f));



Это сообщение отредактировал(а) zim22 - 14.4.2009, 14:26


--------------------
PM MAIL   Вверх
xvr
Дата 14.4.2009, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Ошибка происходит изх за буферизации потока. Можно позвать fflush(f) вместо fseek, должно работать

PM MAIL   Вверх
ressac
Дата 15.4.2009, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



это как в песне, нет ну всё понятно что конкретно....


c fflush() не пашет

а если fseek() не нужен, то почему без него не работает? smile
PM MAIL   Вверх
zim22
Дата 15.4.2009, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



 smile 
Цитата(zim22 @  14.4.2009,  08:01 Найти цитируемый пост)
Я не-знаю, я не по-ни-маю. Песенка такая была

Цитата(ressac @  15.4.2009,  16:01 Найти цитируемый пост)
это как в песне, нет ну всё понятно что конкретно

давайте споём! smile



--------------------
PM MAIL   Вверх
ressac
Дата 16.4.2009, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



ну что? smile кто - то поможет понять? smile
PM MAIL   Вверх
Anikmar
Дата 16.4.2009, 11:17 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Возможно не будет работать без fseek в том случае, если fread закончилась ничем - т.е. стояла на конце файла. Проверьте результат fread - прошло чтение или нет.

PM MAIL ICQ   Вверх
ressac
Дата 16.4.2009, 12:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



да, последний fread читает...
PM MAIL   Вверх
zim22
Дата 16.4.2009, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Цитата(ressac @  16.4.2009,  12:28 Найти цитируемый пост)
да, последний fread читает...

Anikmar прав. попробуйте закомментировать злосчастный fseek. и вы увидите, что не fread не читает, а fwrite не пишет
Код
size_t res = 0;
        fseek(f,sizeof(TPersona)*i,SEEK_SET);
        printf("\n\n %i",ftell(f));
        res = fread(&p,sizeof(TPersona),1,f);
        printf("\n\n %i",ftell(f));

       // fseek(f,sizeof(TPersona)*(i+1),SEEK_SET);
        printf("\n\n %i",ftell(f));
        res = fwrite(&p,sizeof(TPersona),1,f);
        printf("\n\n %i",ftell(f));



Это сообщение отредактировал(а) zim22 - 16.4.2009, 12:33


--------------------
PM MAIL   Вверх
Anikmar
Дата 16.4.2009, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 5
Всего: 59



Этот fseek, я так понимаю, нужен, чтобы увеличить размер файла - выйти за его границу для добавления информации. В середине файла он ничего не делает, а вот в конце файла - нужен.

Добавлено @ 12:43
Цитата(ressac @  16.4.2009,  12:28 Найти цитируемый пост)
да, последний fread читает... 

Последний понятно - цикл идет с конца к наячалу. Первый смотрите.

Это сообщение отредактировал(а) Anikmar - 16.4.2009, 12:43
PM MAIL ICQ   Вверх
ressac
Дата 30.4.2009, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



я так и не понял, можно ещё раз?
PM MAIL   Вверх
zim22
Дата 30.4.2009, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Цитата(ressac @  30.4.2009,  11:30 Найти цитируемый пост)
я так и не понял, можно ещё раз?

функции fread и fwrite возвращают количество байт, которые они записали/прочитали.
измените свой код так, чтобы он отображал эти значения и вы увидите, что в одном случае всё нормально, а вдругом - не очень.


--------------------
PM MAIL   Вверх
ressac
Дата 30.4.2009, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



ну в одном возрващает "1" а в другом "0"

только что это значит smile ?
PM MAIL   Вверх
zim22
Дата 30.4.2009, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


depict1
****


Профиль
Группа: Завсегдатай
Сообщений: 2682
Регистрация: 15.1.2009
Где: Украина

Репутация: 29
Всего: 69



Цитата(ressac @  30.4.2009,  12:36 Найти цитируемый пост)
только что это значит


Цитата(zim22 @  30.4.2009,  12:06 Найти цитируемый пост)
функции fread и fwrite возвращают количество байт, которые они записали/прочитали.

это и значит.


--------------------
PM MAIL   Вверх
math64
Дата 30.4.2009, 12:55 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



fread и fwrite возвращают число записей, т. е. 1 - записана 1 запись, 0 - запись не записана или записана не целиком.
Чтобы знать число байт установите параметр size в 1
PM   Вверх
ressac
Дата 30.4.2009, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



Ну да , всё сходится вообщем и fread и fwrite  возвращают "1".
ну а вопрос серовно открыт
PM MAIL   Вверх
ressac
Дата 8.5.2009, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 345
Регистрация: 25.11.2006

Репутация: нет
Всего: 1



http://www.opengroup.org/onlinepubs/799098.../xsh/fopen.html

"When a file is opened with update mode (+ as the second or third character in the mode argument), both input and output may be performed on the associated stream. However, output must not be directly followed by input without an intervening call to fflush() or to a file positioning function (.Fn fseek , fsetpos() or rewind()), and input must not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file. "


вот теперь, я могу спать спокойно
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0985 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.