Открытие и чтение файлов в С++
#include <fstream.h>
#include <conio.h>
void main()
{
char ch;
ifstream in("C:\read.txt", ios::in);
if (!in)
{
cout << "Can't open file!\n";
}
while (in)
{
in.get(ch);
if(in) cout << ch;
}
in.close();
getch();
}
Как вы догадались, на консоли появилось - "Can't open file!" =)
В чем ошибка? Смотрел в учебнике, так и не понял, что я делаю неправильно ...
А вообще, если у кого-то есть время и желание, вот все задание (можно взять любой вариант):
"Входной файл содержит произвольную синтаксически верную программу на С++. Необходимо выполнить один из следующих вариантов задания:
Вариант 1. В выходной файл записать все комментарии содержащиеся во входном файле на С++. Комментарии могут объявляться как знаками /*…..*/ так и //……. .
Вариант 2. В выходной файл записать все объявленные в программе переменные типа int в следующем формате:
Переменные типа int : a,b,c.
Указание: в этом варианте выходной файл должен содержать только одну строку.
Вариант 3. В выходной файл записать все циклы for вместе с их содержимым (в соответствие с синтаксисом цикла for). Циклы разделять пустой строкой."
Жду ответов )
нужно писать два слеша... например c:\\my.txt
Спасибо, киска ) я даже не подозревал, что нужно 2 слеша.
Может кто-нибудь поможет дальше дописать программу? =)
Не внимательно смотрел - открываеш файл для записи и пытаешся из него читать.
Я все правильно открывал. Читай внимательней - проблема была в двойном слеше.
+ я уже немного продвинулся, могу находить нужные символы =)
#include <fstream>
using namespace std;
int main(int argc, char *argv[])
{
if(argc!=3)
{
cout<<"input file name"<<endl;
return 1;
}
ifstream f_in(argv[1]);
if(!f_in)
{
cout<<"File is not open"<<endl;
return 1;
}
ofstream f_out(argv[2]);
if(!f_out)
{
cout<<"File destination is not open"<<endl;
return 1;
}
char ch;
int size=0;
f_in.unsetf(ios::skipws);
while(!f_in.eof())
{
f_in>>ch;
if(!f_out.eof())f_out<<ch;
size++;
}
f_in.close();
f_out<<endl<<"Quantity of symbols in file is: "<<size;
f_out.close();
return 0;
}
Спасибо, конечно, но мне это не пригодится. Посимвольное чтение и запись я уже сам могу организовать ))
Кстати на счет количества символов - по моему лучше использовать функцию gcount(), хотя хз - я не шарю :D
to KiskaZ
Представь себе, во время того, когда я писал тебе ответ - у меня очень продвинулась работа ). Теперь прога успешно находит символы "//" и отображает комментарии! Вот она:
#include <fstream.h>
#include <conio.h>
#define n 100
void main()
{
char b[2], str[n];
ifstream in("C:\\read.txt", ios::in, ios::binary);
if (!in)
cout << "Can't open file!\n";
while (in)
{
in.read((char *) b, sizeof b);
if(b[0] == '/' && b[1] == '/')
{
in.getline(str,n);
cout << b[0] << b[1] << str <<"\n";
for (int i=0; i<n;i++)
str = 0;
}
}
in.close();
getch();
}
Но как всегда есть одно НО - если комментариев очень много, приходится очищать массив под каждую строку. Это правильно? И все равно почему-то некоторые строки не отображаются.
Вобщем потестите кому не лень на исходниках, и скажите чего можно исправить\дописать...
Но как всегда есть одно НО - если комментариев очень много, приходится очищать массив под каждую строку. Это правильно? И все равно почему-то некоторые строки не отображаются.
Вобщем потестите кому не лень на исходниках, и скажите чего можно исправить\дописать...
ты можешь не чистить каждый раз массив, если будешь использовать указатели
т.е. вместо
char b[2], str[n];
написать
char *b,*str;
а далее выделять под массив необходимую память
например b=(char *)malloc(2); --здесь под переменную в выделяется 2 байта.
в общем смысл в том, что в такой указатель записывается строка как есть, а остальное не используется.
и как я поняла тебе надо искать в строке коментарии (и они начинаются с символа //), тогда лучше ситать не по символьно, а построчно и искать в строке символ при помощи функции strstr. например ptr=strstr(ptr,"////");
в общем я делала вот так
str=(char*)malloc(255);
do{
fgets(s,LINESZ,inf);
strcpy(str,s);
char *ptr=strstr (s,"имя_АРМ");
if (ptr != NULL )
{
int sk=strlen(s);
int pk=strlen(ptr);
int n;
n=sk-pk;
strcpy(str,"");
strncat(str,s,n);
//добавляем имя компьютера
strcat(str,nameARM);
ptr=strstr(ptr,"\\");
strcat(str,ptr);
}
//имя_сервера
ptr=strstr (s,"имя_сервера");
if (ptr != NULL )
{
int sk=strlen(s);
int pk=strlen(ptr);
int n;
n=sk-pk;
strcpy(str,"");
strncat(str,s,n);
char *pt=strtok(nameServer,"\\");
if (pt != NULL)
{
strcat(str,pt);
}
ptr=strstr(ptr,"\\");
strcat(str,ptr);
}
fputs(str,outf);
}while(!feof(inf));
т.е. вместо
char b[2], str[n];
написать
char *b,*str;
а далее выделять под массив необходимую память
например b=(char *)malloc(2); --здесь под переменную в выделяется 2 байта.
в общем смысл в том, что в такой указатель записывается строка как есть, а остальное не используется.
ака динамическое выделение памяти, я это уже встречал. Попробовал использовать указатель на b - не работает (да и зачем, чето не понял...). С str вроде все нормально.
А на счет того, что "читать не по символьно, а построчно и искать в строке символ при помощи функции strstr" - не прокатит, ибо мне нужно искать также и МНОГОСТРОЧНЫЕ комментарии (см.первый пост). (хотя это можно применить ко второму варианту - поиск значений типа "int")
Кстати я понял почему у меня прога не все комментарии находит - просто я считываю в буфер размером 2 байта, поэтому 2 рядом стоящих слеша могут оказаться в разных буферах, и поэтому не смогут интерпретироваться как "//". То бишь нужно что-то с этим сделать =) Как думаешь?
это же не проблема, для многострочных коментариев используется '/*' сделай условие если находишь этот символ то следуящая строка проверяется на '*/' и помещается целиком если не нашел его, а нашел, только до этого символа...
в общем динамическое выделение памяти как раз и спасает тебя от 2-х рядом стоящих слеша оказываются в разных буферах...
Динамическое выделение памяти позволяет более рационально использовать память и ты можешь использовать не все выделенное пространство памяти... и главное очень подходит для строковых массивов не определенной длины
вот поэтому и говорю что нужно использовать построчное чтение и искать сразу '//' а не один....
что конкретно не работает?
в том то и дело, что проблема - я не знаю как сделать переход на др. строку, и как взять все символы ДО */
На счет указателей. Я сделал, но комментарии почему-то выводятся в строчку. Вот мой код:
#include <fstream.h>
#include <conio.h>
#define n 100
void main()
{
char *str, *b;
str = (char *)malloc(50);
b = (char *)malloc(2);
ifstream in("C:\\read.txt", ios::in, ios::binary);
if (!in)
cout << "Can't open file!\n";
while (in)
{
in.read((char *) b, sizeof b);
if(*b == '/' && *(b++) == '/')
{
in.getline(str,*str);
cout << *b << *(b++)<< str <<"\n";
}
}
in.close();
getch();
}
Так чтоли надо было делать? Выводит что-то типо этого "/ wqerty /// uiop[]'/.;l,mkjnbhgvc //fdxzsa" (в одну строку)
Можешь выложить код еще раз, но с комментариями?
#include <fstream.h>
#include <conio.h>
#define n 100
void main()
{
char *str, *b;
str = (char *)[color=red]malloc[/color](50); // malloc странно выглядит в программе на C++
b = (char *)[color=red]malloc[/color](2);
ifstream in("C:\\read.txt", [color=red]ios::in, ios::binary[/color]); // ios::in - не надо, ios::bin - почему?
if (!in)
cout << "Can't open file!\n";
while ([color=red]in[/color]) // надо while ( !in.eof() )
{
in.read((char *) b, [color=red]sizeof b[/color]); // sizeof b = 4, читаешь 4 байта? В буфер размером 2 байта?
if(*b == '/' && *([color=red]b++[/color]) == '/') // Инкрементируешь указатель? Ты понимаешь куда он после этого указывает?
{
in.getline(str,[color=red]*str[/color]); // А это что значит?
cout << *b << [color=red]*(b++)[/color]<< str <<"\n"; // Читаешь данные за пределами массива?
}
}
in.close();
getch();
}
Резюме:
1. Тебе необходимо разобраться, что такое инкремент (++).
2. Тебе необходимо разобраться с указателями.
3. Тебе необходимо разобраться с тем, что такое sizeof.
4. Тебе необходимо разобраться с методом ifstream::getline, и какие аргументы в него передаются. Кстати, есть более удобная функция std::getline.
5. Не пользуйся в программах на C++ функцией malloc, используй new, а ещё лучше научись использовать подходящие классы, например std::string.
А теперь маленький примерчик,- информация к размышлению:
#include <fstream>
#include <string>
using namespace std;
/*
comments
*/
int main()
{
ifstream is("1.cpp");
if(!is) return -1;
string str;
getline(is, str, '/');
getline(is, str, '/');
cout << str;
return 0;
}
is.close();
...
Во-вторых: То, что malloc из си - это не важно.
В-третьих: "ios::in - не надо, ios::bin - почему?" - это я тренировался :)
В-четвертых: "надо while ( !in.eof() )" почему это while(in) не катит??? Имхо тоже самое, Г. Шилдт, например, во всех примерах так пишет.
В-пятых: "sizeof b = 4, читаешь 4 байта? В буфер размером 2 байта?" Я тебя не понимаю, где ты 4 байта взял? Вроде читаю 2, в буфер из 2-х байт.
В-шестых: "Инкрементируешь указатель? Ты понимаешь куда он после этого указывает?" Здесь я конечно ступил - надо: (*b)++
В-седьмых: "in.getline(str,*str); // А это что значит?" Как я понял, это значит, что мы помещаем строку в str а *str как я понял - показывает сколько байт из строки мы возьмем. Хз, но я другого не придумал.
В-восьмых: Про std::getline я ничего не знаю.
В-девятых: std::string - тоже не знаю.
В-десятых: Я вообще мало чего знаю в С/С++ (+ это моя третья программа на С :)
В-одиннадцатых: Не понял я твой пример. Расскажи подробней про getline(is, str, '/');
is.close();
...
Нет необходимости. Это работа деструктора.
А придется, если будешь использовать C/C++.
Во-вторых: То, что malloc из си - это не важно.
Если хочешь научиться грамотно использовать C++, то важно
В-четвертых: "надо while ( !in.eof() )" почему это while(in) не катит??? Имхо тоже самое, Г. Шилдт, например, во всех примерах так пишет.
К сожалению, не помню, что пишет Г.Шилдт, но это некрасиво по двум причинам:
1) запись while ( !in.eof() ) более информативна - "читаем до конца";
2) while ( !in.eof() ) - работает до тех пор, пока не достигли конца, а while(in) - работает до достижения конца, потом производится попытка чтения уже из завершившегося файла, получаем ошибку и только после этого выходим.
В-пятых: "sizeof b = 4, читаешь 4 байта? В буфер размером 2 байта?" Я тебя не понимаю, где ты 4 байта взял? Вроде читаю 2, в буфер из 2-х байт.
Поэтому я и советовал изучить указатели и sizeof.
sizeof указателя - это 4 байта в 32 разрядных системах
В-шестых: "Инкрементируешь указатель? Ты понимаешь куда он после этого указывает?" Здесь я конечно ступил - надо: (*b)++
Нет. Ещё раз советую изучать указатели и инкремент.
В-седьмых: "in.getline(str,*str); // А это что значит?" Как я понял, это значит, что мы помещаем строку в str а *str как я понял - показывает сколько байт из строки мы возьмем. Хз, но я другого не придумал.
Ну так сколько возьмем? :)
В-восьмых: Про std::getline я ничего не знаю.
В-девятых: std::string - тоже не знаю.
В-десятых: Я вообще мало чего знаю в С/С++ (+ это моя третья программа на С :)
В-одиннадцатых: Не понял я твой пример. Расскажи подробней про getline(is, str, '/');
Учись, направление задано.
Ты меня совсем запутал... Дык указатель-то на тип char где же там 4 байта?
[COLOR="Red"](*b)++ ПРАВИЛЬНО[/COLOR]
ибо...Цитирую Шилдта:
(*p)++;
могу скан дать :D
Ты меня совсем запутал... Дык указатель-то на тип char где же там 4 байта?
Читай про указатели и sizeof.
[COLOR="Red"](*b)++ ПРАВИЛЬНО[/COLOR]
ибо...Цитирую Шилдта:
могу скан дать :D
А зачем тебе инкрементировать содержимое?
Допустим, по этому адресу лежит символ 'A', в результате ты сделаешь так, что там будет лежать 'B'. Ты этого добивался?
cout << (*str)++ << endl; // вывод "A"
cout << str << endl; // вывод "BBC"
В результате (*str)++ измениться содержимое массива, вместо 'A' будет лежать 'B'.
Поэтому вместо "ABC", в массиве будет "BBC".
Я хотел перейти на следующий байт в буфере. Вот и все.
Ладно, пошел я спать - время-то у меня не московское :)
Утро вечера мудренее. :)