Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

If(strstr(line,word)) printf(“Присутствует”)




else printf(“Отсутствует”);

Для успешного поиска последовательностей, состоящих из русских букв, файл надо создать в тестовом редакторе с кодировкой ASCII- например в FAR. Если же текстовый файл уже существует и создан в кодировке ANSI, используемой в Windows, для преобразования в туже кодировку строки вводимой с клавиатуры в переменную word, придется воспользоватся нестандартной функциеу OemToChar, описанной в заголовке <windows.h> Два параметра – исходная и результирующая строка.

CharToOem, выполняет обратную перекодировку.

Сравнение строк

Char *strcmp(char *s1, char *s2); Возвращает 0 если равны, <0 если s1<s2, >0 если s1>s2

Char *strncmp(char *s1, char *s2, size_t n); Первую строку с первыми n символами второй строки. Возвращает 0 если равны, <0 если s1<s2, >0 если s1>s2

Поиск символа в строке

Char *strchr(char *s, int ch); Функция возвращает указатель на первое вхождение символа ch в строку s, если его нет, то возвращается NULL

char *strrchr(char *s, int ch)
похожа на strchr(), но возвращает указатель на последний символ c в строке.

int main(void)

{

 

char string[20];

char *ptr, c = 'r';

strcpy(string, "This is a string");

ptr = strchr(string, c);

if (ptr)

printf("The character %c is at position: %d\n", c, ptr-string);

else

printf("The character was not found\n");

getch();

return 0;

}

Конкатенация (объединение) строк

Сначала простой вопрос – каков результат выполнения следующего кода:

char str1[10]="Hello";char str2[10]="World!";char* str3;str3=str1+str2;

Если ответ – ошибка на этапе компиляции, материал изложенный в статье вы усвоили (или знали это раньше). Если же вы полагаете, что в str3 будет хранится строка "Hello world!", то вероятно, мои предыдущих объяснений оказалось недостаточно. Нельзя складывать указатели (и имена массивов).

Для конкатенации следует использовать функции.

Есть две специальные функции:

char* strcat(char* dest, const char* source)char* strncat(char* dest, const char* source, size_t size)

Эти функции добавляют к строке, на которую указывает dest, символы из строки source. Первая версия добавляет все символы до нуль-символа, вторая – максимум size символов. Результирующая строка завершается нуль-символом.

 

Поиск одиного из символов одной строки в другой

Char *strcspn(char *s1, char *s2); Возвращает значение индекса любого из символов из s2 в строке s1.

Поиск символа одной строки, отсутствующий в другой

Char *strspn(char *s1, char *s2); Возвращает индекс первого символа в s1, отсутствующего в s2.

char *string1 = "14234567890";

char *string2 = "123DC8";

int length;

length = strspn(string1, string2);

printf("Character where strings differ is at position %d\n", length);//1

strpbrk - найти в строке s1 любой из множества символов, входящих в строку s2.

char *strpbrk(char *s1,char *s2);

 

char *string1 = "abcdefghijklmnopqrstuvwxyz";

char *string2 = "onm";

char *ptr;

ptr = strpbrk(string1, string2);

if (ptr)

printf("strpbrk found first character: %d\n", ptr-string1);

else

printf("strpbrk didn't find character in set\n");

 

strtok - выделить из строки s1 лексемы, разделенные любым из множества символов, входящих в строку s2.

char *strtok(char *s1,Char *s2);

char *s1, *s2;

char input[16] = "a;b c,d";

char *p;

p = strtok(input, ",;");

while(p){

printf("%s\n", p);

p = strtok(NULL, ",;");}

Первый вызов формирует адрес первой лексемы в строке input. Он сохраняется в переменной р. Функция strtok заменяет на NULL разделитель находящийся после найденного слова. Оператор strtok в цикле выполняет поиск следующей лексемы в тойже строке. Для этог следует задать в функции strtok в качестве первого параметра NULL.

Использование функций strupr и strlwr библиотеки этапа выполнения:

cout << "Верхний регистр: " << strupr(title) << endl;
cout << "Нижний регистр: " << strlwr(lesson) << endl;

 

ПРЕДУПРЕЖДЕНИЕ

Не путайте ‘\0’, ‘0’ и “0”. Первое – символьный литерал, соответствующий символу с кодом 0. Второе – такой же литерал, но обозначающий цифру 0, ее код в ASCII-кодировке 48. Третий — это строковый литерал, содержащий два символа, цифру 0 и нуль-терминатор.

 

Если в строке нет символа "+", то оставить строку без изменения, иначе каждую цифру, предществующую первому вхождению знака "+" заменить на "*"

#include "iostream"

#include <string.h>

#include <conio.h>

#include <ctype.h>

#include <stdio.h>

using namespace std;

Void main()

{ char s1[30],s2[20],s3[20],*ptr;

int i;

cout<<"\nVvedite s1 ";gets(s1);

ptr=strchr(s1,'+');

if (ptr) {cout<<"position="<<ptr-s1;

for(i=0;i<ptr-s1;i++)

{if (isdigit(s1[i]))s1[i]='*';}

}

else cout<<" null ";

cout<<s1;

return;

}

Вывести все слова строки в алфавином порядке

#include "iostream"

using namespace std;

Void main()

{ char str[100],*ptr;

char mat[10][100];

cout<<"vvedite stroky"<<endl;

gets(str);

cout<<"dlina stroki "<<strlen(str)<<endl;

int i=0;

ptr=strchr(str,' ');

While(ptr)

{ strncpy(mat[i],str,ptr-str);

mat[i][ptr-str]='\0';

cout<<i<<"-slovo="<<mat[i]<<endl;

i++;

strcpy(str,ptr+1);

cout<<"*****"<<str<<endl;

cout<<"dlina stroki "<<strlen(str)<<endl;

ptr=strchr(str,' ');

}

strcpy(mat[i],str);

mat[i][strlen(str)]='\0';

cout<<i<<"-slovo="<<mat[i]<<endl;

//сортировка

int n=i;

for(i=n-1;i>0;i--)

for(int j=0;j<=i;j++)

{if(strcmp(mat[j],mat[j+1])>0)

{strcpy(str,mat[j]);

strcpy(mat[j],mat[j+1]);

strcpy(mat[j+1],str);

}

}

for(i=0;i<n;i++)

{cout<<mat[i]<<endl;

}

return;

}

Функции ввода/вывода

Ввод/вывод в С++ реализуется либо с помощью функций, унаследованных от библиотек С, либо с помощью потоков С++. Смешивать эти два способа в одной программе не рекомендуется.

Для использования функций ввода/вывода в стиле С необходимо подключить к программе заголовочный файл <stdio.h> или <cstdio>. При вводе/выводе данные рассматриваются как поток байтов. Физически поток представляет собой файл или устройство, например, клавиатуру или дисплей, рассматривающиеся как частный случай файла.

Открытие потока

1. Файл открывается. Это означает, что программа "захватывает" заданный по имени файл, сообщает Windows, что далее она будет с ним работать. Данный шаг нужен, чтобы не возникало конфликтов, когда несколько программ одновременно хотят записывать информацию в один и тот же файл. Правда, считывать данные из файла, очевидно, допустимо одновременно множеством программ, поэтому в операции открытия файла обычно уточняется, что файл открывается "на чтение" (считывание информации, которая не меняется) либо "на запись" (данные в файле модифицируются).
Операция открытия файла возвращает некий идентификатор (как правило, целое число), которое идентифицирует в программе в дальнейшем нужный открытый файл. Этот идентификатор запоминается в переменной; обычно такая переменная называется файловой переменной.

2. Ведется работа с файлом. Из него данные либо считываются, либо в него записываются.

3. Файл закрывается. После этой операции он снова доступен другим программам для обработки.

Работа с потоком начинается с его открытия. Поток можно открыть для чтения и/или записи в двоичном или текстовом режиме. Функция открытия потока имеет формат:

FILE* fopen(const char* filename, const char* mode);

При успешном открытии потока функция возвращает указатель на предопределенную структуру типа FILE, содержащую всю необходимую для работы с потоком информацию, или NULL в противном случае. Первый параметр - имя открываемого файла в виде С-строки, второй - режим открытия файла:

"r" - файл открывается для чтения;

"w" - открывается пустой файл для записи (если файл существует, он стирается);

"a" - файл открывается для добавления информации в его конец;

"r+" - файл открывается для чтения и записи (файл должен существовать);

"w+" - открывается пустой файл для чтения и записи (если файл существует, он стирается);

Режим открытия может также содержать символы t (текстовый режим) или b (двоичный режим), отличающиеся обработкой символов перехода на новую строку. По умолчанию файл открывается в текстовом режиме, при котором комбинация символов "возврат каретки" и "перевод строки" (0x13 0x10) при вводе преобразуются в одиночный символ перевода строки (при выводе выполняется обратное преобразование). В двоичном режиме преобразования не выполняются.

Пример:

FILE *f = fopen("d:\\cpp\\data.txt", "rb+");

Тогда команда открытия (создания пустого) файла запишется так:

FILE * fo;
fo = fopen("test.txt","wt");

Можно задать и полный путь к файлу, например:

fo = fopen("c:\\tmp\\test.txt","wt");

Не забываем, что одиночный символ \ внутри строки Си задается двумя наклонными слэшами \\. Это частая ошибка.

После открытия файла в файловую переменную fo занесется некоторое число. Если таким числом будет ноль, считается, что файл открыть не удалось. В Си нередки записи вида

if( (fo=fopen("c:\\tmp\\test.txt","wt")) == 0) {
// ошибка!
}

где одновременно открывается файл и проверяется, успешно ли это сделано.

Указатель f используется в дальнейших операциях с потоком. Его передают функциям ввода/вывода в качестве параметра.

При открытии потока с ним связывается область памяти, называемая буфером. При выводе вся информация направляется в буфер и накапливается там до заполнения буфера или до закрытия потока. Чтение осуществляется блоками, равными размеру буфера, и данные читаются из буфера.

Существует пять предопределенных потоков, которые открываются в начале работы программы: стандартный ввод stdin, стандартный вывод stdout, стандартный вывод сообщений об ошибках stderr, стандартный дополнительный поток stdaux и стандартная печать stdprn.

Ввод/вывод в поток

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

Операции ввода/вывода выполняются начиная с текущей позиции потока, определяемой положением указателя потока. Указатель устанавливается при открытии на начало или конец файла (в соответствии с режимом открытия) и изменяется автоматически после каждой операции ввода/вывода.

Ниже перечислены основные функции ввода/вывода потока.

  • Чтение и запись потока байтов выполняют функции fread и fwrite.
  • Чтение символа из потока - getc, fgetc, из стандартного потока stdin - getchar.
  • Запись символа в поток - putc, fputc, в стандартный поток stdout - putchar.
  • Чтение строки из потока - fgets, из стандартного потока stdin - gets.
  • Запись строки в поток - fputs, в стандартный поток stdout - puts.
  • Форматированный ввод из потока - fscanf, из стандартного потока stdin - scanf, из строки - sscanf.
  • Форматированный вывод в поток - fprintf, в стандартный поток stdout - printf, в строку - sprintf.

Закрытие потока

Поток закрывается либо при завершении программы, либо явным образом с помощью функции fclose:

int fclose(FILE*);

Перед закрытием потока информация из связанных с ним буферов выгружается на диск. Рекомендуется явным образом закрывать потоки, открытые для записи.

Функция fputc

#include <stdio.h>int fputc(int ch, FILE * stream);

Функция fputc() записывает символ ch в текущую позицию потока stream, a затем увеличивает указатель текущей позиции файла. Хотя на практике при объявлении символа ch он всегда имеет тип int, функцией fputc() тип символа преобразуется в unsigned char. Поскольку в момент вызова символьный аргумент преобразуется к целому типу, в качестве аргументов обычно можно использовать и символьные переменные. При использовании целого значения, старший байт попросту отбрасывается.

Значением, возвращаемым функцией fputc(), является значение записанного символа. При возникновении ошибки возвращается значение EOF. Если файл открыт для выполнения операций в двоичном режиме, значение EOF тоже может оказаться символом. Поэтому, чтобы определить, возникла ли ошибка на самом деле, в таких случаях придется использовать функцию ferror().

Пример

Приведенная функция записывает в заданный поток содержимое строки.

void write_string(char *str, FILE *fp){ while(*str) if(!ferror(fp)) fputc(*str++, fp);}

Функция fgetc

#include <stdio.h>int fgetc(FILE * stream);

Функция fgetc() возвращает символ, взятый из входного потока stream и находящийся сразу после текущей позиции, а также увеличивает указатель текущей позиции файла. Этот символ читается как значение типа unsigned char, преобразованное в целое.

При достижении конца файла функция fgetc() возвращает значение EOF. Ho по скольку значение EOF является действительным целым значением, при работе с двоичными файлами для обнаружения конца файла необходимо использовать функцию feof(). Если функция fgetc() обнаруживает ошибку, она возвращает значение EOF. Для выявления ошибок, возникающих при работе с двоичными файлами, необходимо использовать функцию ferror().

Пример

Следующая программа читает и выводит на экран содержимое текстового файла.

#include <stdio.h>#include <stdlib.h> int main(int argc, char *argv[]){ FILE *fp; char ch; if((fp=fopen(argv[1],"r"))==NULL) { printf("Невозможно открыть файл.\n"); exit(1); } while((ch=fgetc(fp))!= EOF) { printf("%c", ch); } fclose(fp); return 0;}

Функция fprintf

#include <stdio.h>int fprintf(FILE * stream, const char * format,...);

Функция fprintf() выводит в поток, адресуемый параметром stream, значения аргументов, составляющих список аргументов, в соответствии с заданной строкой формата format. Возвращаемое значение равно количеству реально выведенных символов. Если при выводе возникла ошибка, возвращается отрицательное число.

#include <stdio.h>int fscanf(FILE * stream, const char * format,...);

Функция fscanf() работает подобно функции scanf(), но читает информацию не из стандартного потока ввода stdin, а из потока, заданного указателем stream. Подробности рассматриваются в разделе этой главы, посвященном функции scanf.

Функция fscanf() возвращает количество аргументов, которым действительно присвоены значения. Это число не включает опущенные поля. Если возвращаемое функцией значение равно EOF, то это свидетельствует о том, что до выполнения первого присваивания произошел сбой.

#include <stdio.h>

main()

{

FILE *fi;

int age;

fi=fopen("File","r"); /* считывание */

fscanf(fi,"%d",&age); /* fi указывает на File */

fclose(fi);

fi=fopen("Data", "a"); /*дополнение*/

fprintf(fi,"Data is %d.\n",age);

/*fi указывает на Data*/

fclose(fi);

}

Функция fgets()

include <stdio.h>char *fgets(char * str, int num, FILE * stream);

Функция fgets() читает из входного потока stream не более num-1 символов и помещает их в массив символов, адресуемый указателем str. Символы читаются до тех пор, пока не будет прочитан символ новой строки или значение EOF, либо пока не будет достигнут заданный предел. По завершении чтения символов сразу же за последним из них размещается нулевой символ. Символ новой строки сохраняется и становится частью массива, адресуемого элементом str.

/* Программа считывает файл строка за строкой */

#include <stdio.h>

#define MAX 80

main()

{

FILE *f1;

char *string[MAX];

f1=fopen("File","r");

while (fgets(string,MAX,f1)!= NULL)

puts(string);

}

Мы расположили вводимую информацию в символьном массиве string. Первый из трех аргументов функции fgets() является указателем на местоположение считываемой строки. Второй аргумент содержит предельную длину считываемой строки. Функция прекращает работу после считывания символа новой строки или после считывания символов общим числом MAX-1, в зависимости от того, что произойдет раньше. В любом случае нуль-символ '\0' добавляется в самый конец строки. Третий аргумент указывает на файл, который будет читаться.

Разница между gets() и fgets() заключается в том, что gets() заменяет символ новой строки на '\0', в то время как fgets() сохраняет символ новой строки. Подобно gets() функция fgets() возвращает значение NULL, если встречает символ EOF. Это позволяет нам проверить, достигли ли мы конца файла.

Функция fputs()

#include <stdio.h>int fputs(const char * str, FILE * stream);

Функция fputs() записывает в заданный поток stream содержимое строки, адресуемой указателем str. При этом завершающий нулевой символ (т.е. символ конца строки ('0')) не записывается.

В версии C99 к параметрам str и stream применен квалификатор restrict.

При успешном выполнении функция fputs() возвращает неотрицательное значение, а при неудачном — значение EOF.

Если поток открыт в текстовом режиме, могут произойти преобразования некоторых символов. Это значит, что однозначного отображения строки в файл может и не быть. Однако если поток открыт в двоичном режиме, никаких преобразований символов не будет и строка отобразится в файл "один к одному".

l=fputs("Строка", fi);

   
   
   
   

Передает строку "Строка" в файл, на который ссылается указатель fi типа FILE. Конечно, сначала нужно открыть файл при помощи функции fopen().

 


Поток по умолчанию буферизован, поэтому закрытие файла освобождает буфер. Однако имеется возможность явно указать освобождение буфера в любой момент работы программы, не закрывая файл. Для этого используется функция

int fflush(FILE *имя);


Аналогично функции закрытия файла в случае успешной записи буфера в файл возвращается ноль, иначе — EOF.
Важнейшей функцией является функция, проверяющая, достигнут ли конец файла. Ее прототип

int feof(FILE *имя);


Очевидно, конец файла может обнаружиться только при чтении из файла. Если в результате очередной операции ввода достигнут конец файла, система устанавливает внутренний индикатор конца файла. Этот индикатор и проверяет данная функция. Если достигнут конец файла, то функция возвращает ненулевое значение, иначе возвращается 0.


Двоичные файлы
Двоичные и текстовые файлы — это, как говорят в Одессе, «две большие разницы». Обмен данными между программой и двоичным потоком выполняется без всякого преобразования, поэтому работает быстрее. Двоичный ввод выполняется функцией fread(), имеющей следующий прототип:

size_t fread(void *buffer, size_t size, size_t n, FILE *stream);


Тип size_t обычно определен как unsigned int. Первый параметр часто определяет массив (или указатель на динамический массив), в который будет прочитана информация; третий параметр задает размер одного элемента данных в байтах, а второй — количество читаемых элементов. Четвертый параметр определяет двоичный файл, из которого информация вводится. Общее количество считанных байтов равно size*n. Однако возвращает функция количество корректно прочитанных элементов, а не байтов.
Вывод в двоичный файл выполняется функцией fwrite(), которая имеет совершенно аналогичный прототип:

size_t fwrite(const void *buffer, size_t size, size_t n, FILE *stream);


Функция записывает n элементов размера size в двоичный файл stream из буфера, указатель на который задается в качестве первого аргумента. Общее количество выводимых байтов равно size*n. Однако возвращает функция количество корректно записанных элементов, а не байтов.
В качестве элементов могут использоваться любые переменные любых типов, в том числе и динамические. Даже массив может быть одним-единственным элементом! Рассмотрим несколько простых примеров, аналогичных примерам для текстовых файлов (см. листинги 10.8,10.9). Создадим на диске C: каталог BinFiles и все двоичные файлы будем размещать в нем. Переделаем пример создания файла (листинг 10.12).

//Листинг 10.12. Создание и чтение двоичных файлов #include <cstdio> #include <cstdlib> #include <ctime> int main() { int m[10]={0}; srand((unsigned)time(NULL)); // инициализация датчика случайных чисел FILE *stream; /* открываем двоичный файл для записи */ if((stream = fopen("c:/binfiles/number1.bin", "wb")) == NULL) return 1; // ошибка при открытии /* заполняем массив m числами */ for(int i = 0; i < 10; i++) m[i] = rand()%10; // случайные числа от 0 до 9 // заполняем файл number1.bin элементами-числами for(int i = 0; i < 10; i++) fwrite(&m[i], 1, sizeof(int), stream); fclose(stream); // закрываем файл /* открываем другой файл для записи */ if((stream = fopen("c:/binfiles/number2.bin", "wb")) == NULL) return 1; // ошибка при открытии // заполняем файл number2.bin элементом-массивом fwrite(m, 1, sizeof(m), stream); // массив - один элемент fclose(stream); // закрываем файл // вывод второго двоичного файла на экран // открываем файл для чтения if((stream = fopen("c:/binfiles/number2.bin", "rb")) == NULL) return 1; // ошибка при открытии int a = 0; // сюда вводим // читаем второй файл поэлементно // правильный цикл fread(&a, 1, sizeof(int), stream); // предварительное чтение while(!feof(stream)) // пока не конец файла { printf("%d\n", a); fread(&a, 1, sizeof(int), stream); } fclose(stream); // открываем первый файл в режиме чтения if((stream = fopen("c:/binfiles/number1.bin", "rb")) == NULL) return 1; int t[10] = {0}; // массив для чтения // читаем первый файл как массив fread(t, 1, sizeof(t), stream); for(int i = 0; i < 10; i++) // выводим поэлементно printf("%d\n",t[i]); fclose(stream); char ch = getchar(); return 0; }


В этой программе сначала создается два двоичных файла: number1.bin и number2.bin. В первый файл целые числа из массива m записываются по одному в цикле. Во второй файл весь массив записывается сразу как один элемент. Затем файлы открываются для чтения. Сначала открывается файл number2.bin (в который мы писали массив целиком), и чтение из него выполняется по одному числу. Проверка конца файла делается так же, как и для текстовых файлов. На экране видно, что чтение выполняется совершенно правильно.
Первый файл number1.bin, который записывался в цикле по одному числу, читается сразу целиком в массив t, а вывод осуществляется по одному числу. И снова мы наблюдаем на экране, что чтение выполнилось совершенно правильно. Такое «смешивание» для двоичных файлов безопасно, так как и в памяти, и на диске размеры данных равны sizeof(тип)*n, где n — количество элементов, участвующих в обмене.
Теперь добавим в конец этого примера строки, выполняющие суммирование чисел, записанных в файл number1.bin.

// суммирование чисел записанных в файле if((stream = fopen("c:/binfiles/number1.bin", "rb")) == NULL) return 1; // ошибка при открытии // читаем числа по одному из файла и считаем int number, summa = 0, count = 0; fread(&number, 1, sizeof(int), stream); while(!feof(stream)) { printf("%d\n", number); ++count; summa+=number; fread(&number, 1, sizeof(int), stream); } printf("%d %d\n", summa, count); fclose(stream);


Как видим, этот текст отличается от приведенного выше для текстовых файлов только режимом открытия и функцией ввода данных.
Так как функции посимвольного ввода/вывода fgetc() и fputc() фактически не выполняют никакого преобразования информации, то копирование двоичных файлов можно делать точно так же, как и текстовых — посимвольно. Используем функцию filecopy(), представленную в листинге 10.9.

// копирование файлов FILE *in, *out; if((in = fopen("c:/binfiles/number1.bin", "rb")) == NULL) { printf ("Error input file!"); return 1; // ошибка при открытии } if((out = fopen("c:/binfiles/number1.new", "wb")) == NULL) { printf ("Error output file!"); return 1; // ошибка при открытии } filecopy(in, out); // копирование fclose(in); fclose(out);


Соответственно и для объединения файлов можно использовать ту же функцию — все определяется режимом открытия файла.

// дозапись нового файла в конец старого if((out = fopen("c:/binfiles/number1.bin", "ab")) == NULL) { printf ("Error output file!"); return 1; } if((in = fopen("c:/binfiles/number1.new", "rb")) == NULL) { printf ("Error input file!"); return 1; } filecopy(in, out); // объединение – дозапись! fclose(in); fclose(out);


Для проверки правильности объединения выведем содержимое файла на экран. Используем вторую форму проверки окончания файла — внутри цикла:

// вывод нового файла на экран для проверки if((stream = fopen("c:/binfiles/number1.bin", "rb")) == NULL) return 1; while(true) { fread(&a, 1, sizeof(int), stream); if (feof(stream)) break; printf("%d\n", a); } fclose(stream);
Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...