Функция 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. - Если программа завершается нормально, выводится сообщение об успешном завершении.