WinterWolf, ты-то вещественные числа ввёл сам, конечно, какие там расхождения могут быть . А при вычислениях обычно возникают погрешности, другое дело - будут ли они влиять на результат в конкретном случае.
Насчет case тоже в недоумении... ни к селу ни к городу для такой задачи.
Tomb_and_Jerry, никогда не понимала преподавателей, не поощряющих применение знаний, которых он не давал сам (если это действительно знание, которое предполагает еще и понимание).
При желании она вполне могла назвать его и по-другому, а вместо логики использовать любой целочисленный тип (тогда в case были бы, например, 0 и 1).
Это неоптимальное использование памяти - для нолика и единицы огроменный тип использовать! =) Тогда уж в паскале диапазон лучше применить: var flag: 0..1.
Сообщение изменено: Invisible (17 November 2010 - 18:30)
"Given enough eyeballs, all bugs are shallow". Э. Рэймонд
WinterWolf, ты-то вещественные числа ввёл сам, конечно, какие там расхождения могут быть . А при вычислениях обычно возникают погрешности, другое дело - будут ли они влиять на результат в конкретном случае.
При вычислении функции, согласен, погрешности возникнуть могут, но x ведь мы по условию задачи задаем сами.
Это неоптимальное использование памяти - для нолика и единицы огроменный тип использовать! =) Тогда уж в паскале диапазон лучше применить: var flag: 0..1.
Согласен с той лишь оговоркой, что byte, как и boolean, занимает в памяти 1 байт.
Сообщение изменено: WinterWolf (17 November 2010 - 18:37)
Слова - лакмусовая бумажка, определяющая тип сознания.
Значит так, я царапаю программульки на Visual C++ Express Editon 2008 при помощи замечательного учебника (вернее, учебников два: том 1 и том 2). Это для начала.
Идём дальше. Дошёл до темы "Стандартный файловый ввод - вывод". Речь идёт про операции последовательного чтения из файла. Вот текст программы:
Spoiler
#include <stdio.h>
#include <conio.h>
int main (void)
{
FILE* pf = NULL;
int pos; unsigned char dat;
pf = fopen ("C\\TEMP\\MyText.txt","rb");
if ( pf != NULL )
{
while ((dat = fgetc(pf))!= EOF)
{
pos = ftell (pf);
printf ("Byte on %d position in file = %c\n", pos, dat);
}
fclose (pf);
}
else
printf ("Failed to open file MyText.txt");
//Screen delay:
printf ("Enter any key to exit");
getch();
return 0;
}
В содержимое файла "MyText.txt" накатал следующее: "qwerty".
Всё понятно, всё ясно. Ещё: потом немножко дополнил текст под свой лад, но суть не изменилась:
Spoiler
#include <stdio.h>
#include <conio.h>
#include <windows.h>
int main (void)
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
FILE* pf = NULL;
int pos; unsigned char dat;
pf = fopen ("C:\\Users\\Евгений\\Documents\\Visual Studio 2008\\Projects\\Работа с файлами\\Работа с файлами\\MyText.txt","rb");
if ( pf != NULL )
{
while ((dat = fgetc(pf))!= EOF)
{
pos = ftell (pf);
printf ("Байт на %d позиции в файле = %c\n", pos, dat);
getch();
}
fclose (pf);
}
else
printf ("Неудачная попытка открытия файла: %s\n",strerror(errno));
printf ("Нажмите любую клавишу, чтобы выйти: \n");
getch();
return 0;
}
Далее. Запускаю проект, Всё работает. Молодец, но не правильно. По идее, программа должна была вывести каждый символ из qwerty с новой строки. Да, программулька с этим справилась. Но вместо того, чтобы вывести "Нажмите любую клавишу, чтобы выйти: ", она выводит бесконечно вот это:
Ладно, в головёшке моей бестолковой вертятся следующие мысли:
EOF - это есть конец файла, типа енд оф файл, ну или проще говоря, константа "-1". Окей, а функция fgetc() возвращает значение символа и автоматом переводит указатель текущей позиции на следующий, а когда достигнет конца файла, то вернёт "-1". Хорошо, но у нас же dat = fgetc(pf). То есть, по идее, когда мы доползём до конца файла, то значение переменной dat должно быть -1, но в объявлении этой переменной ясно сказано, что это есть unsigned char, то есть, эта переменная принимает значение от 0 до 255. Ага, тогда: когда переменной dat посылается значение "-1", то эта переменная принимает значение 255 (логично, кстати, о такой интересной штучке про переменную типа char подробнее было описано главой назад). А эта переменная из таблицы ASCII есть буковка "я". Тогда вот программа и выводит эту зловещую букву бесконечно раз. Ладно - ладно. Тогда я совсем чуть - чуть поменял код: вместо строки while ((dat = fgetc(pf))!= EOF) я написал while ((dat = fgetc(pf))!= 255). Вроде бы всё нормально, программа теперь полноценно идёт, но блин. А если в файле будет бувка "я", то программа тупо закончит выполнять цикл, ибо "я" есть 255... Нет, так не идёт. На свой страх и риск я вместо "unsigned char dat;" написал "int dat;", ибо теперь -1 это и есть -1 (тупо объяснил =D). В общем это я сделал из - за вот этого (выделено красным): printf ("Байт на %d позиции в файле = %c\n", pos, dat);. То есть, в итоге вы всё равно выведем буковку))) А вот собственно и вопрос: а так естественно/ я хоть правильно сделал? И почему автор написал программу именно так (в смысле, как в самом начале, не предусмотрев зацикливания)? В итоге у меня такой код:
Spoiler
#include <stdio.h>
#include <conio.h>
#include <windows.h>
int main (void)
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
FILE* pf = NULL;
int pos; int dat;
pf = fopen ("C:\\Users\\Евгений\\Documents\\Visual Studio 2008\\Projects\\Работа с файлами\\Работа с файлами\\MyText.txt","rb");
if ( pf != NULL )
{
while ((dat = fgetc(pf))!= EOF)
{
pos = ftell (pf);
printf ("Байт на %d позиции в файле = %c\n", pos, dat);
//getch();
}
fclose (pf);
}
else
printf ("Неудачная попытка открытия файла: %s\n",strerror(errno));
printf ("Нажмите любую клавишу, чтобы выйти: \n");
getch();
return 0;
}
Сообщение изменено: Smile (29 December 2012 - 21:04)
Сразу отвечу на вопрос: да, сделал всё правильно, так делать вполне можно и допустимо.
Теперь расскажу, что я бы делал немного по-другому:
1) Если обратиться к документации http://msdn.microsof...ibrary/c7sskzc1(v=vs.71).aspx , то видно, что функция возвращет int, то бишь 32-битное значение со знаком, тогда как один символ в ASCII-кодировке - это 8 бит (хотя например fgetwc вернет двухбайтный символ или даже символ из нескольких байт). По сути такая избыточность введена лишь для того, чтобы была возможность вернуть EOF, не заменяя никакой символ (как букву "я" в твоём случае). Таким образом, наиболее правильным вариантом мне видится сначала проверка символа на eof как int, а потом, если символ не оказался EOF, то его можно преобразовать к unsigned char и работать с ним как изначально было задумано.
2) как видно в том же примере в документации к fgetc - там для проверки на eof используется (на мой взгляд более наглядное и правильное) feof(FILE*), которое вернёт не ноль, если достигнут конец файла
3) в образовательных целях fgetc простая и понятная функция, однако на практике она применяется довольно редко для чтения информации из файлов из-за низкой производительности. То есть если например написать функцию копирования файла через функции fgetc и fputc, то с большой вероятностью копирование файла будет выполняться на порядок (если не на два) медленее, чем это может сделать например операционная система. Чтобы чтение выполнялось быстро надо читать не по байту, а большими кусками (например по несколько килобайт). И тут уже надо читать про функцию fread http://msdn.microsof...ibrary/kt0etdcs(v=vs.71).aspx