ТОП 10:

Использование функции fgets() для консольного ввода строк



В связи с тем, что функция gets() пользуется плохой репутацией, в качестве альтернативы этой функции предлагается использовать функцию файлового ввода-вывода fgets().Для обсуждения возможности использования этой функции для консольного ввода приведем прототип функции fgets():

#include<stdio.h>

char*fgets(char* str, int n, FILE* stream);

 

Рассматриваемая функция имеет два дополнительных параметра, которые отсутствуют у функции gets(). Первый из дополнительных параметров (int n) служит для ограничения количества символов, которые могут быть прочитаны в массив str из буфера клавиатуры. Второй дополнительный параметр (FILE* stream) при использовании функции fgets() определяет файл, с которым должна работать эта функция. Для консольного ввода достаточно в ее вызове в качестве параметра stream взять имя стандартного потока, предназначенного для работы с клавиатурой (stdin).

Функция fgets() в форме, предназначенной для ввода с клавиатуры, позволяет записать в массив, на который указывает указатель str, не более n – 1 символа. Ввод прекращается в следующих трех ситуациях:

1. встретился символ новая строка,

2. встретился конец файла.

3. условия 1 и 2 не выполнялись, но прочитан n – 1 символ,

После чтения последнего символа из потока в строку str, строка дополняется нуль символом. Если при чтении встретился символ новая строка (условие 1), то он записывается в строку str и нуль символ записывается за ним. Отсюда следует, что символ новая строка может записываться, а может и не записываться в строку, на которую установлен указатель str.

В случае успешного завершения функция fgets() вернет указатель на строку str. Если прочитан конец файла, а ни один символ не был введен, то содержимое массива оказывается неизменным, а функция вернет значение NULL. Если во время ввода имела место ошибка, то функция вернет значение NULL, а содержимое массива str оказывается неопределенным. Приведем пример.

 

#include<stdio.h>
#include<string.h>
#define MAXSIZE 81

int main(void)
{
char buf[MAXSIZE];
char* s = NULL;
fgets(buf, sizeof(buf), stdin);
s = strchr(buf, '\n');/* Ищем символ ‘\n’ в прочитанной
строке */
if(s != NULL)
*s = '\0'; /* Запись символа ‘\0’вместо
символа ‘\n’ */
return 0;

}

С целью приблизить работу функции fgets() к работе функции gets(), которую она призвана заменить, в рассматриваемом примере добавлен программный код, удаляющий из массива, используемого для ввода строки (buf), символ новой строки (\n). Для этой цели используется функция strchr() и инструкция if.

 

 

Стандартные функции для обработки строк

Функция strlen

Эта функция предназначена для определения длины строки. Ее прототип имеет следующий вид:

#include<string.h>

size_t strlen(const char* str);

Тип size_t является разновидностью целочисленного типа. Функция strlen() возвращает длину строки, на которую установлен указатель str, причем строка должна заканчиваться “нуль – символом”. “Нуль – символ” во время определения длины строки не учитывается. Пример применения функции strlen().

#include<stdio.h>
#include<conio.h>
#include<string.h>

intmain(void)
{
char
str[81];
printf(“Введите строку:”);
gets(str);
printf(“Длина введенной строки =%d”, strlen(str));
return 0;
}

Протокол работы с программой имеет следующий вид.
Введите строку:Это строка

Длина введенной строки=10

 

Функции strcpy() и strncpy()

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

 

/* Программный код, содержащий ошибку */

char str1[30] = “Hello”;

char str2[30];
str2 = str1; /* Недопустимый код, т.к. str2 – константный
указатель */

Для копирования строк в языке Си следует использовать библиотечные функции strcpy() и strncpy(). Обращает на себя похожесть имен этих функций. В соответствии с принципом образования имен, принятым в библиотеке string это означает, что функция strncpy() имеет дополнительный параметр n.

Прототипы функций strcpy() и strncpy() имеют следующий вид:

#include<string.h>
char* strcpy(char* out_str, const char* in_str);
char* strncpy(char* out_str, const char* in_str, size_t n);

Обе функции (strcpy() и strncpy) копируют содержимое строки in_str в строку out_str. Параметр in_str должен указывать на строку, которая заканчивается нуль - символом. До вызова рассматриваемых функций необходимо выделить память для хранения новой строки. Функции strcpy() и strncpy() эту память не выделяют. Обе функции возвращают значение указателя out_str. Обе функции заканчивают копирование в том случае, когда в строке str_in встречается нуль – символ. Функция strncpy() выполняет копирование более осторожным образом. Это связано с наличием у этой функции третьего параметра (параметр n), который ограничивает количество копируемых символов. Количество символов, которые могут быть скопированы функцией strncpy() не может быть больше n. Заметим, что в предельном случае, когда в скопированных n символах строки in_str не встретился нуль - символ, то выходная строка не будет заканчиваться нуль – символом. Если массивы in_str и out_str перекрываются поведение функции strcpy() не определено.

В следующем фрагменте кода строка Hello копируется в строку str.

char str[81];
strcpy(str, "Hello");

Типичной ошибкой при работе с функцией strcpy() является передача ей неправильного указателя на строку str_in. Например, некорректным оказывается следующий фрагмент кода:

void foo()

{

char str1[25] = “Hello”;

char* str2;

strcpy(str1, str2);

/* другой код */

}

Ошибка в приведенном выше коде состоит в отсутствии инициализации указателя str2.

Функции strcat() и strncat()

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

Объявления рассматриваемых функций имеют следующий вид:

#include<string.h>
char* strcat(char* out_str, const char* in_str);
char* strncat(char* out_str, const char* in_str,
size_t n);

 

Функция strcat() присоединяет содержимое строки in_str к строке out_str. Параметр in_str должен указывать на строку, которая заканчивается нуль - символом. Конечный “нуль – символ”, первоначально завершающий строку out_str, перезаписывается первым символом строки in_str. Функция strcat() возвращает значение указателя out_str. Если массивы in_str и out_str перекрываются поведение функции strcat() не определено.

В следующей программе две строки читаются с клавиатуры, затем объединенная строка выводится на экран дисплея.

#include<stdio.h>
#include<string.h>

int main(void)
{
char buf1[64], buf2[64];
gets(buf1);
gets(buf2);
strcat(buf1, buf2);
printf(buf1);
return 0;
}

Перейдем к рассмотрению функции strncat(). Эта функция присоединяет не более n символов строки in_str в конец строки out_str. Если “нуль – символ” строки in_str достигнут раньше, чем будут прочитаны n символов строки in_str, то этот символ копируется, и процесс присоединения заканчивается. Если среди скопированных n символов не встретился нуль – символ, то он добавляется в строку in_str и процесс присоединения на этом заканчивается. В этом случае в выходную строку записывается n + 1 символ. Если в вызове функции n или отрицательно, то функция не изменяет выходную строку out_str.

Функция strcmp()

Объявление этой функции имеет следующий вид

#include<string.h>
int strcmp(const char* in_str1, const char* in_str2);

 

Функция strcmp() выполняет так называемое лексографическое сравнение строк. Функция возвращает нулевое значение, если строки совпадают. Функция возвращает положительное значение, если строка in_str1 > in_str2. Наконец, функция возвращает отрицательное значение, если in_str1 < in_str2. Строка in_str1 считается больше строки in_str2, если первый несовпадающий ее символ имеет код, превышающий код соответствующего ему символа строки in_str2.

Ниже приводится пример применения функции strcmp().

#include<stdio.h>
#include<string.h>

int main(void)
{
char name[32] = "Tom";
/* Выводится положительное число */
printf("%d\n", strcmp(name, "Alic"); /*

/* Выводится отрицательное число */
printf("%d\n", strcmp(name, "Victor");

/* Выводится нуль */
printf("%d\n", strcmp(name, "Tom");
return 0;
}

 

Функция strtok()

Для разделения строки на лексемы можно использовать функцию strtok(). Объявление этой функции имеет следующий вид:

#include<string.h>

char* strtok(char* str1, const char* str2);

Последовательные вызовы функции strtok() можно использовать для разбиения строки, адресуемой указателем str1, на цепочку лексем, завершаемых символом нуль - символом (\0). Символы, образующие строку, адресуемую параметром str2, представляют собой разделители, которые используются для выделения лексемы.

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

Каждый последующий вызов функции strtok() должен принимать в качестве первого параметра нулевой указатель. Поиск очередной лексемы начинается с того символа, на который указывает внутренний указатель функции strtok(). Поиск выполняется по схеме, описанной выше. Функция strtok() возвращает указатель на первый символ лексемы или нулевой указатель.

Рассмотрим пример применения функции strtok(). Пусть дана строка, в которой слова отделяются одним или несколькими пробелами. Сформировать две строки. В первую из этих строк записать строки, длина которых len удовлетворяет условию len <= lmax, а во вторую - все оставшиеся слова исходной строки.

Программа состоит из двух функций. Основную работу по решению поставленной задачи выполняет функция select_word. Эта функция принимает четыре параметра. Первый из ее параметров in - указатель на исходную строку. Обратите внимание, на то обстоятельство, что функция select_word этот параметр не изменяет. Параметры out1 и out2 - указатели на выходные строки. Последний параметр lmax определяет критическое значение длины слова, которое используется для разделения исходной строки. Функция select_word использует внутренний буфер. Это позволяет обеспечить неизменность исходной строки.

 

#include<stdio.h>
#include<string.h>
void select_word(const char* in, char* out1, char* out2,
int len);

int main(void)
{
char str[] = "1 22 333 4444 55555 666666 555555 4444
333 22\ 1";
char out1[128], out2[128];
select_word(str, out1, out2, 4);
puts(out1);
puts(out2);
return 0;
}

 

/* Выделение в строке in слов. Формирование выходных строк out1
и out2. Строка out1 содержит те слова исходной строки in,
которые удовлетворяют условию len <= lmax, а строка out1 -
оставшиеся слова исходной строки.*/

void select_word(const char* in, char* out1, char* out2,
int lmax)
{
char buf[128];
char* p;
strcpy(buf, in);
strcpy(out1, "");
strcpy(out2, "");
p = strtok(buf, " ");
while(p)
{
if(strlen(p) <= (unsigned)lmax)
{
strcat(out1, p);
strcat(out1, " ");
}
else
{
strcat(out2, p);
strcat(out2, " ");
}
p = strtok(NULL, " ");
}
}

 

Массивы строк

Массив строк в языке Си может быть представлен в виде двумерного массива, элементами которого являются символы. Приведем пример, Пусть в некоторой программе необходимо работа со строками, длина которых (без учета нуль-символа) не превышает 128, а количество строк не превосходит 25. В этом случае в программе можно предусмотреть следующее определение массива для работы со строками:

#define MAXLENGTH 129
#define MAXSIZE 25

int main(void)
{
char arr_str[MAXSIZE][MAXLENGTH];
/* */
return 0;
}

 







Последнее изменение этой страницы: 2016-04-26; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.226.243.36 (0.012 с.)