Използвам gcc на Ubuntu 4.6.1 и SUSE 4.6.2 със следната команда
gcc gets_s.c
Моят изходен код е
// Read and Display Lines
// gets_s.c
#include <stdio.h>
int main(void)
{
char first_name[11];
char last_name[11];
printf("First Name : ");
gets_s(first_name, 11);
printf("Last Name : ");
gets_s(last_name, 11);
puts(first_name);
puts(last_name);
return 0;
}
Доразвивам въпроса си:
Основният проблем за мен е съответствието едно към едно между въведените и запазените редове.
При успех разликата между fgets и gets_s е, че fgets включва терминатора за нов ред, докато gets_s заменя знака за край на нов ред с нулевия знак, така че да поддържа съответствие едно към едно между въведените редове и успешните извиквания към gets_s.
За вход, който препълва дължината на буфера, fgets приема броя знаци, които се побират в буфера, и оставя останалите във входния буфер за следващите fgets.
Стандартът (K.3.5.4.1) гласи, че с gets_s (за разлика от gets) изисква нов ред, EOF или грешка при четене в рамките на n-1 знака. Следователно препълването е нарушение на ограничението за изпълнение. Ако има нарушение на ограничението по време на изпълнение, първият знак в буфера е зададен на нулев знак и знаците във входния буфер stdin се четат и отхвърлят, докато не бъде прочетен знакът за нов ред, възниква край на файла или възниква грешка при четене.
Съответно на успеха очаквах:
>fgets
First Name : Chris
Last Name : Szalwinski
Chris
Szalwinski
>
>gets_s
First Name : Chris
Last Name : Szalwinski
Chris
Szalwinski
>
При препълване очаквах различно поведение от fgets и gets_s. С други думи,
>fgets
First Name : Christopher
Last Name : Christophe
r
>
>gets_s
First Name : Christopher
Last Name : Szalwinski
Szalwinski
>
Обърнете внимание как очаквах gets_s да премахне изцяло съдържанието на първия ред на въвеждане.
Ако основният проблем е съответствието едно към едно между въведените редове и запазените редове, което е важно при отстраняване на грешки, все още трябва да напишем собствена функция (подобно на getline на K&R)
char *gets_s(char *s, int n)
{
int i, c;
for (i = 0; i < n - 1 && (c = getchar()) != EOF && c != (int)'\n'; i++)
s[i] = c;
s[i] = '\0';
while (n > 1 && c != EOF && c != (int)'\n')
c = getchar();
return c != EOF ? s : NULL;
}
С такава функция се поддържа съответствието едно към едно, буферът е наситен и няма нарушение на ограничението за изпълнение.
Правилно ли правя този извод.