Функция fwrite дописывает в начале строк буквы - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Не понимаю почему, но функция fwrite дописывает в начале строк буквы. К 1-ой строке прибавляется "яю", к последующим "НН".Хотя по отладчику видно что строка записываемая с помощью fwrite не содержит этих букв в начале. Они вылазят при считывании с помощью fread. Все файлы открываются как бинарные. 1-ый файл заносит "карточки с 3-мя полями" , 2-ой файл считывает эти карточки. Если нажать 2- вывод в файл, то эти начальные лишние буквы видно в shipsoutput.txt
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>//dl9 exit
//#include "iostream.h"
#include <windows.h>
#define M 50//количество пустых строк в очистке экрана
 
struct Record{
    char str1[M];
    char str2[M];
    char str3[M];
} *p;
 
void input1();
void input2();
void clrscrn();
FILE *openFile(char *filename, char *mode);
int IsAlpha(char c);//Аналог isaplha но с учётом русских букв. 1 если буква, 0-иначе
void SkipInput();//Пропуск небукв при вводе.
void SkipInputIsAlnum();
char OemSymbol(char c);

int _tmain(int argc, _TCHAR* argv[])
{
 
    /*SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    setlocale(LC_ALL, "Rus");*/
    p = (struct Record *)malloc(sizeof(struct Record));
    char c = '0';
    while (c != '3'){
        clrscrn();
        printf("This program let you add cards of ports and ships\n");
        printf("To add ship card press 1\nIf you want to add port card press 2\n");
        printf("To close program press 3\n");
 
        fflush(stdin);
        c = getchar();
 
        if (c == '1'){//Kod 1
            input1();
        }
        if (c == '2'){//Kod 2
            input2();
        }
    }
    delete[] p;
    return 0;
}
 
void clrscrn(){
    for (int i = 0; i<50; ++i){//o4istka ekrana
        printf("\n");
    }
}
 
FILE *openFile(char *filename, char *mode){//в fopen сделано через указатели.filename-имя создаваемого файла,mode - тип открытия файла- wb и т.д.
    FILE *f;
    f = fopen(filename, "r");//Возвращает 0 в случае успеха
 
    int c;
    if (f == NULL && mode == "r"){
        printf("Error opening %s file", filename);
        getchar();
        exit(-1);
    }
    if (f != NULL && *mode == 'w'){
        fclose(f);
        printf("The file %s already exists\nPress 1 to rewrite it\nPress 2 to cancel\n", filename);
        do{
            scanf("%d", &c);
            if (c == 1){
                f = fopen(filename, mode);
                return f;
            }
            else if (c == 2){
                f = NULL;
            }
        } while (c != 2);
    }
    else if (f == NULL && *mode == 'w'){
        f = fopen(filename, mode);
        return f;
    }
    else if (f != NULL && mode == "ab"){
        f = fopen(filename, mode);
        return f;
    }
 
    return f;
}
 
void input1(){
    FILE *f;
    //f = fopen("ships.dat", "ab");
    f = openFile("ships.dat", "ab");
    char c = '0';
    while (c != '3'){
        clrscrn();
        printf("All info will be put to \"ships.dat\"\n\n\n");
        printf("You are filling information about ship\n\n\n");
        printf("Fill-in ship name\n");// Vstavit proverki
        fflush(stdin);
        SkipInputIsAlnum();
        gets(p->str1);
        OemToAnsi(p->str1, p->str1);
        if (strlen(p->str1) == 0){
            strcpy(p->str1, "No info");
        }
        printf("Fill-in port of departure\n");
        SkipInputIsAlnum();
        gets(p->str2);
        OemToAnsi(p->str2, p->str2);
        if (strlen(p->str2) == 0){
            strcpy(p->str2, "No info");
        }
        printf("Fill-in arrival port\n");
        SkipInputIsAlnum();
        gets(p->str3);
        OemToAnsi(p->str3, p->str3);
        if (strlen(p->str3) == 0){
            strcpy(p->str3, "No info");
        }
        while (strcmp(p->str2, p->str3) == 0){//Через do while не сделал ибо с printf мучаться (счётчик для первого прохода чтобы не выводить в 1-ый раз)
            printf("Inputed ports must be different. Please input 2nd port again.\n\n");
            SkipInputIsAlnum();
            gets(p->str3);
            OemToAnsi(p->str3, p->str3);
        }
        fwrite(p, sizeof(struct Record), 1, f);
        clrscrn();
        printf("Return to main menu press 3.\n\nTo input one more ship card press any key\n\n");
        c = getchar();//potom peredelat na s4itivanie stroki. I esli strlen > 1 to incorrect input. bez fflush
    }
    fclose(f);
}
 
void input2(){
    //printf("All info will be put to \"ports.dat\"\n\n\n");
    FILE *f;
    //f = fopen("ports.dat", "ab");
    f = openFile("ports.dat", "ab");
    char c='0';
    while (c != '3'){
        clrscrn();
        printf("All info will be put to \"ports.dat\"\n\n\n");
        printf("You are filling information about port\n\n\n");
 
        printf("Fill-in port name\n");// Vstavit proverki
        fflush(stdin);
        SkipInputIsAlnum();
        gets(p->str1);
        OemToAnsi(p->str1, p->str1);
        printf("Fill-in its country\n");
        int flag1 = 0;
        while (!flag1){
            SkipInput();
            gets(p->str2);
            OemToAnsi(p->str2, p->str2);
            char *g = p->str2;//Ибо str2[M] нельзя двигать ++ как указатель
            while (*g != '\0'){
                if (IsAlpha(*g) || strchr("- ",*g)){
                    ++g;
                }
                else{
                    printf("Incorrect input. Try again\n");
                    break;
                }
            }
            if (*g == '\0'){
                flag1 = 1;
            }
        }
        flag1 = 0;
        printf("Fill-in its sea\n");
        while (!flag1){
            SkipInput();
            gets(p->str3);
            OemToAnsi(p->str3, p->str3);
            char *g = p->str3;//Ибо str2[M] нельзя двигать ++ как указатель
            while (*g != '\0'){
                if (IsAlpha(*g) || *g==' '){
                    ++g;
                }
                else{
                    printf("Incorrect input. Try again\n");
                    break;
                }
            }
            if (*g == '\0'){
                flag1 = 1;
            }
        }
 
        fwrite(p, sizeof(struct Record), 1, f);
        clrscrn();
        printf("Return to main menu press 3.\nTo input one more port card press any key\n");
        scanf("%c", &c);//pravit na stroky
    }
    fclose(f);
    clrscrn();
}
 
char OemSymbol(char c){
    char k[] = " ";
    k[0] = c;
    OemToAnsi(k, k);
    return k[0];
}
int IsAlpha(char c){//Аналог isaplha но с учётом русских букв. 1 если буква, 0-иначе
    //c = OemSymbol(c);
    if ((c >= 'а' && c <= 'я') || (c >= 'А' && c <= 'Я') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){
        return 1;
    }
    else return 0;
}
void SkipInput(){
    char c;
    while (!IsAlpha(OemSymbol(c=getc(stdin))));     
    ungetc(c, stdin);
}
void SkipInputIsAlnum(){
    int c;
    while (!(IsAlpha(OemSymbol(c=getc(stdin))) || isdigit(OemSymbol(c))));      
    ungetc(c, stdin);
}
Прога 2
#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"//dl9 exit
#include <windows.h>
//#include "iostream.h"
#define M 50//Dlina strok v structure
 
struct Record{//shipname,port1,port2
    char str1[M];
    char str2[M];
    char str3[M];
} *tmp, *search;//search dl9 sravneni9 s tmp. Vna4ale zapoln9ets9 tolko 1-oe pole

struct Result{
    char Shipname[M];
    struct Record port1;
    struct Record port2;
} *Res;
 
void ShipNameSearch();
void OutputToFile();
void clrscrn();
FILE *openFile(char *filename, char *mode);

int _tmain(int argc, _TCHAR* argv[])
{
    tmp = new struct Record;
    search = new struct Record;
    Res = new struct Result;
 
    char c = 0;//vprincipe mojno i int
    int flag = 0;
    while (c != '3'){
        clrscrn();
        printf("This program looks for information about ships\n");
        printf("Press 1 if you want to find specific ship info\n");
        printf("Press 2 to output all data to file\"Shipsoutput.dat\"\n");
        printf("To close program press 3\n");
 
        fflush(stdin);
        scanf("%c", &c);
        if (c == '1'){//Kod 1
            ShipNameSearch();
        }
        if (c == '2'){//Kod 2
            OutputToFile();
        }
    }
    delete[] tmp;
    delete[] search;
    delete[] Res;
    return 0;
}
 
void clrscrn(){
    for (int i = 0; i<50; ++i){//o4istka ekrana
        printf("\n");
    }
}
 
FILE *openFile(char *filename, char *mode){//в fopen сделано через указатели.filename-имя создаваемого файла,mode - тип открытия файла- wb и т.д.
    FILE *f = fopen(filename, mode);
    if (f == NULL){
        perror("Error opening file");
        getchar();
        exit(-1);
    }
    return f;
}
 
void ShipNameSearch(){
    FILE *f1, *f2;
    char c = 'y';
    f1 = openFile("ships.dat", "rb");
    f2 = openFile("ports.dat", "rb");
    clrscrn();
    while (c == 'Y' || c == 'y'){
        fseek(f1, 0, SEEK_SET);//4tobi posle kajdogo poiska v sly4ae eshe 1-ogo vozvrashalis na na4alo failov
        fseek(f2, 0, SEEK_SET);
        do{
            printf("Enter name of ship to find\n");
            scanf("%s", search->str1);
            OemToAnsi(search->str1, search->str1);
        } while (!strlen(search->str1));
        strcpy(Res->Shipname, search->str1);
        printf("Search for ship %s info\n", search->str1);//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Тут ошибка наверно. Надо де OemToAnsi
 
        int flag = 0, flag1 = 0, flag2 = 0;//mojno flag=flag1=flag2=0?
 
        while (fread(tmp, sizeof(*tmp), 1, f1) == 1 && !flag){//mojno sdelat while (fread(...)==1 && strcmp(...)!=0) no nyjno (fread(...))
            if (strcmp(search->str1, tmp->str1) == 0){//sravnenie iskomogo i pro4itannogo pol9
                flag = 1;//nashli boatname kotorii ishem
                *search = *tmp;
                while (fread(tmp, sizeof(*tmp), 1, f2) == 1 && !(flag1 && flag2)){
 
                    if (!flag1 && strcmp(search->str2, tmp->str1) == 0){//Proverka po 2-omy polu.
                        Res->port1 = *tmp;
                        flag1 = 1;//nashli port1
                    }
 
                    if (!flag2 && strcmp(search->str3, tmp->str1) == 0){//proverka po 3-emy polu (2-omy porty)
                        Res->port2 = *tmp;
                        flag2 = 1;//nashli port2
                    }
                }
 
            }
 
        }
        if (!flag1){
            strcpy(Res->port1.str2, "No info");
            strcpy(Res->port1.str3, "No info");
        }
        if (!flag2){
            strcpy(Res->port2.str2, "No info");
            strcpy(Res->port2.str3, "No info");
        }
        clrscrn();
        if (!flag){
            AnsiToOem(search->str1, search->str1);
            printf("No one record with name %s was found\n\n", search->str1);
        }
        else {
            AnsiToOem(Res->Shipname, Res->Shipname);
            AnsiToOem(Res->port1.str2, Res->port1.str2);
            AnsiToOem(Res->port1.str3, Res->port1.str3);
            AnsiToOem(Res->port2.str2, Res->port2.str2);
            AnsiToOem(Res->port2.str3, Res->port2.str3);
            printf("Ship: %s\ndepart from country:%s\nSea:%s\n\n to\n\nCountry:%s\nSea:%s\n", Res->Shipname /*Res->Shipname ne podxodit t.k. nelz9 Res->Shipname=search->str1*/, Res->port1.str2, Res->port1.str3, Res->port2.str2, Res->port2.str3);
            printf("\n\n\n");
        }
        printf("To search again press Y, otherwise any other key\n");
        fflush(stdin);
        scanf("%c", &c);
        fflush(stdin);//ina4e pri vvode stroki sledyushii cikl pervii simvol idet v c a ostalnie v shipname v na4ale cikla (search->str1)
    }
    fclose(f1);
    fclose(f2);
    clrscrn();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void OutputToFile(){//vivod nyjno delat f textovii fail
    FILE *f1, *f2, *fout;
    int c = 0;
    //int flag1=0, flag2=0;
    clrscrn();
    f1 = openFile("ships.dat", "rb");
    f2 = openFile("ports.dat", "rb");
    if (fout = fopen("Shipsoutput.txt", "r")){//Проверка существования файла вывода данных и выбор действия
        fclose(fout);
        do{
            printf("File Shipsouput.txt already exists. Do you want to rewrite or to supplement it?\nTo rewrite press 1\nTo supplement press 2\n");
            scanf("%d", &c);
            if (c == 1){
                fout = openFile("Shipsoutput.txt", "w");
            }
            if (c == 2){
                fout = openFile("Shipsoutput.txt", "a");
            }
        } while (c != 1 && c != 2);
    }
    else{
        fout = openFile("Shipsoutput.txt", "w");
    }
    /*fseek (f1, 0, SEEK_SET);//yto4nit nyjno li vozvrashat pointer na na4alo faila ili fopen delaet eto sama
    fseek (f2, 0, SEEK_SET);*/
    while (fread(search, sizeof(*tmp), 1, f1) == 1){
        int flag1 = 0, flag2 = 0;
        strcpy(Res->Shipname, search->str1);/*Res->Shipname=search->str1;*/
        while (fread(tmp, sizeof(*tmp), 1, f2) == 1 && !(flag1 && flag2)){
 
            if (!flag1 && strcmp(search->str2, tmp->str1) == 0){
                Res->port1 = *tmp;
                flag1 = 1;
            }
 
            if (!flag2 && strcmp(search->str3, tmp->str1) == 0){
                Res->port2 = *tmp;
                flag2 = 1;
            }
        }
        if (!flag1){
            strcpy(Res->port1.str2, "No info");
            strcpy(Res->port1.str3, "No info");
        }
        if (!flag2){
            strcpy(Res->port2.str2, "No info");
            strcpy(Res->port2.str3, "No info");
        }
        fseek(f2, 0, SEEK_SET);//posle kajdogo proxoda vozvrashaems9 v na4alo faila
 
        fprintf(fout, "Ship: %s\ndepart from\n\nCountry:%s\nSea:%s\n\n to\n\nCountry:%s\nSea:%s\n", Res->Shipname /*Res->Shipname ne podxodit t.k. nelz9 Res->Shipname=search->str1*/, Res->port1.str2, Res->port1.str3, Res->port2.str2, Res->port2.str3);
        fprintf(fout, "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
    }
    printf("All ship info was successfully copied to Shipsoutput.dat\n");
    printf("press any key to return to menu");
    fflush(stdin);
    char str[1];
    gets(str);
    fclose(f1);
    fclose(f2);
    fclose(fout);
}

Решение задачи: «Функция fwrite дописывает в начале строк буквы»

textual
Листинг программы
#define MM           (50)
 
struct By
{  
   char     str1[MM + 1];
   char     str2[MM + 1];
   char     str3[MM + 1];
};
 
int main(int argc,char** argv)
{
   FILE*    pShips = fopen("ships.dat","wb");
 
   if (!pShips)
   {
      // Error !
      return 0;
   }
 
   By*      pStrings = new By; 
 
   memset(pStrings,0,sizeof(By));
 
   printf("Enter 3 lines of text:\n");   
 
   gets(pStrings->str1);  
   gets(pStrings->str2);
   gets(pStrings->str3);
 
   printf("\n\n");   
 
   fwrite(pStrings,sizeof(By),1,pShips);
 
   fclose(pShips);
   pShips = NULL;
 
   ///
 
   pShips = fopen("ships.dat","rb");   
 
   if (!pShips)
   {
      // Error !
      delete[] pStrings;
      pStrings = NULL; 
      return 0;
   }
   
   if (fread(pStrings,sizeof(By),1,pShips) != 1)
   {                
      // Error !
      delete[] pStrings;
      pStrings = NULL; 
      return 0;
   }   
 
   fclose(pShips);  
   pShips = NULL;
 
   printf("%s\n%s\n%s\n~~~~~~\n",pStrings->str1,pStrings->str2,pStrings->str3);
 
   delete[]  pStrings;
   pStrings = NULL; 
 
   return 0;
}

Объяснение кода листинга программы

  1. В начале кода определен макрос MM, который равен 50.
  2. Затем определена структура By, которая содержит три строки по 50 символов каждая.
  3. В функции main() открывается файл ships.dat для записи в двоичном формате.
  4. Если файл не может быть открыт, программа выводит сообщение об ошибке и завершается.
  5. Создается экземпляр структуры By с помощью оператора new.
  6. Затем с помощью функции memset() все поля экземпляра структуры By очищаются.
  7. Пользователю предлагается ввести три строки текста.
  8. Введенные строки записываются в поля экземпляра структуры By с помощью функций gets().
  9. Затем записывается пустая строка с помощью функции printf().
  10. Всю структуру By записывают в файл с помощью функции fwrite().
  11. Файл закрывается с помощью функции fclose().
  12. Снова открывается файл ships.dat, на этот раз для чтения.
  13. Если файл не может быть открыт, программа выводит сообщение об ошибке, закрывает файл, освобождает память и завершается.
  14. Если файл успешно открыт, программа читает из него одну структуру By с помощью функции fread().
  15. Файл закрывается с помощью функции fclose().
  16. Выводится содержимое полей структуры By с помощью функции printf().
  17. Память освобождается с помощью функции delete[] и указатель на структуру By устанавливается в NULL.
  18. Программа завершается с помощью функции return().
  19. В начале и в конце программы устанавливается идентификатор atexit() для вызова функции fclose() для файла ships.dat.
  20. Если программа завершается нормально, выводится сообщение об успешном завершении.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

15   голосов , оценка 4 из 5
Похожие ответы