Функция fwrite дописывает в начале строк буквы - C (СИ)
Формулировка задачи:
Не понимаю почему, но функция fwrite дописывает в начале строк буквы.
К 1-ой строке прибавляется "яю", к последующим "НН".Хотя по отладчику видно что строка записываемая с помощью fwrite не содержит этих букв в начале. Они вылазят при считывании с помощью fread. Все файлы открываются как бинарные. 1-ый файл заносит "карточки с 3-мя полями" , 2-ой файл считывает эти карточки. Если нажать 2- вывод в файл, то эти начальные лишние буквы видно в shipsoutput.txt
Прога 2
#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); }
#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; }
Объяснение кода листинга программы
- В начале кода определен макрос MM, который равен 50.
- Затем определена структура By, которая содержит три строки по 50 символов каждая.
- В функции main() открывается файл
ships.dat
для записи в двоичном формате. - Если файл не может быть открыт, программа выводит сообщение об ошибке и завершается.
- Создается экземпляр структуры By с помощью оператора new.
- Затем с помощью функции memset() все поля экземпляра структуры By очищаются.
- Пользователю предлагается ввести три строки текста.
- Введенные строки записываются в поля экземпляра структуры By с помощью функций gets().
- Затем записывается пустая строка с помощью функции printf().
- Всю структуру By записывают в файл с помощью функции fwrite().
- Файл закрывается с помощью функции fclose().
- Снова открывается файл
ships.dat
, на этот раз для чтения. - Если файл не может быть открыт, программа выводит сообщение об ошибке, закрывает файл, освобождает память и завершается.
- Если файл успешно открыт, программа читает из него одну структуру By с помощью функции fread().
- Файл закрывается с помощью функции fclose().
- Выводится содержимое полей структуры By с помощью функции printf().
- Память освобождается с помощью функции delete[] и указатель на структуру By устанавливается в NULL.
- Программа завершается с помощью функции return().
- В начале и в конце программы устанавливается идентификатор atexit() для вызова функции fclose() для файла
ships.dat
. - Если программа завершается нормально, выводится сообщение об успешном завершении.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д