2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Массив строк в С
Сообщение16.07.2012, 21:22 
Аватара пользователя


26/02/11
332
Продолжаю изучение си. Вот написал простенькую прогу, чтобы убедиться, что форматом %s можно вывести целый массив символов.
код: [ скачать ] [ спрятать ]
Используется синтаксис C
#include <stdio.h>
#include <conio.h>
 
#define MAXLINE 10 /*длина строки*/

int main()
{
    char line[MAXLINE];
    int i;
   
    i = 0;
   
    while ((line[i] = getchar()) != EOF)
          ++i;
    if (i < 10)
        printf("%s", line);
         
    getch();
    return 0;
}

Объявил значит небольшой массив из 10 символов, вроде ввел как надо, но когда работаешь с программой, нужно два раза вводить EOF, в конце строки, потом Enter, потом снова EOF(Сtrl-z). При этом выводится строка со стрелочкой вправо в конце. Почему так?

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 21:44 
Аватара пользователя


31/10/08
1244
Потому что Сtrl-z это не EOF, а стрелочка.

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 21:47 


03/05/12
56
Судя по всему, неправильный конец строки. Так работает:
Используется синтаксис C
    char line[10];


         int i = 0;

         while ((line[i] = getchar()) != '\n')
               ++i;
         if (i < 10)
             printf("%s", line);

         getchar();
         return 0;
 

Выдаёт результат после нажатия Enter. Так и привычней, и в конце массива переход на следующую строку.

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 21:49 
Аватара пользователя


26/02/11
332
Pavia в сообщении #595955 писал(а):
Потому что Сtrl-z это не EOF, а стрелочка.

Joker_vD в сообщении #595331 писал(а):
Вообще-то EOF вводится по Ctrl+D (UNIX) / Ctrl+Z (Win). Ctrl+C — это прерывание работы программы.

Получается это неверно?

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 22:06 


03/05/12
56
Кстати, если ввести строку, потом нажать Enter, потом Ctrl+Z, потом опять Enter, то можно увидеть правильный результат и в начальном варианте программы :-)

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 23:02 
Аватара пользователя


31/10/08
1244
Цитата:
Получается это неверно?


Это вопрос передачи информации. Человеческий язык очень неточен. И проблема формулировки терминов в программирование стоит очень остро.
Мне не хватает терминов чтобы это всё сформулировать кратко, но я могу описать как это всё происходит.

Условимся называть вашу программу как test.exe.

getchar() возвращает число.
Далее встаёт вопрос как интерпретировать это число. А делать это мы можем по разному.

Так вот число "-1"=EOF согласно стандарту С++ следует понимать как булевую константу false.
А вот всё остальное следует понимать как символ*.


Что касается CTRL+Z это клавиши. Стандарт С++ не говорит как следует интерпретировать нажатые клавиш. Это дело компьютера, ОС, консоли.


Нажатие клавише посылает сигнал. Клавиатура обрабатывает этот сигнал** преобразовывает в скан-код отправляет в компьютер, а тот в ОС. ОС преобразовывает этот код в свой код. Посылая сигнал программе.
Какой программе? Да той которая обрабатывает эти клавиши в данный момент. В WinXP, Win7 есть такая программа как cmd.exe в простонародье известная как консоль.
Так вот эта cmd.exe получив сообщения что были нажаты CTRL+Z интерпретирует их по своему.

ДОПУСТИМ мы не знаем как работает консоль, а просто по рассуждаем.
Когда мы запускаем test.exe в ОС Win XP. ОС выяснив что это консольное приложение запустила cmd.exe передав в качестве параметра "test.exe". А cmd.exe уже запустила программу test.exe.
Как консоль cmd.exe интерпретирует CTRL+Z? Да так, как захочет.
1) Консоль может преобразовать в ASCII символ и передать его в test.exe.
2) Консоль может интерпритировать комбинацию как команду на закрытие файла***. Это файл который используется для ввода символов*** в программу test.exe.
3) Она может отреагировать и подругому к примеру поменять цвет шрифта.

Это все было 3 предположения так как же на самом деле действует консоль cmd.exe?
На это ответит эксперемент и документация по конкретной ОС и её консоли.
Эксперимент показал что консоль Win Vista интерпретирует нажатие клавиш CTRL+Z, корректнее сказать их коды, как символ. И преобразовывает их скан-коды в код символа который передается в нашу программу. Символ этот имеет код который соотвествует в таблице ASCII стрелочке.
CTL+Z не вызывает генерацию EOF.

Возможно в Windows98 CTRL+Z выполнял функцию EOF, а возможно и нет.

----------------------------------------------------------
* Нет точных рекомендаций что понимать под символом. И тем более понимать EOF как символ или нет?
Лучше EOF не называть символом. Хотя не всегда это возможно.

**Сигнал - посмотрите определение в словаре. В контексте слово использовалось как нечто интуитивно понятное.
***Файл - в данном случае под файлом понимается набор данных,структур используемые ОС, для ввода и вывода данных с использованием так называемых файловых функций.

Символ - данные воспринимаемые и интерпретируемые одновременно ОС, программой, человеком,
компьютером - как число из ASCII таблице.

Есть такая вещь. Как ASCII таблица. Эта таблица описывает правило которое принято для интерпретации данных в виде символов выводимых на экран монитора или печать.
Таблица ASCII была разработана в Америке в последствие была расширена. По настоящее время применяется хотя почти и вытеснена UNICODE.
В ASCII символ имеет номера от 0 до 255. Для хранения одного символа ASCII достаточно байта.

Тип Char в Cи не имеет определённого размера. А размер зависит от платформы. Но чаще всего равен байту.

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 23:10 
Заслуженный участник


04/05/09
4582
Dosaev в сообщении #595944 писал(а):
Объявил значит небольшой массив из 10 символов, вроде ввел как надо, но когда работаешь с программой, нужно два раза вводить EOF, в конце строки, потом Enter, потом снова EOF(Сtrl-z). При этом выводится строка со стрелочкой вправо в конце. Почему так?
Проблем несколько.
Первая:
venco в сообщении #595578 писал(а):
EOF - не символ, а число (-1), не пересекающееся с реально прочитанными символами, возвращаемыми из getchar() (0...255). Одна из распространённых ошибок - сохранять результат getchar() в переменную типа char. В результате, если char - signed, то чтение остановится и на символе с кодом 255 (буква 'я' в виндовой кодировке), а если unsigned, то получится бесконечный цикл.
Т.е. после сохранения результата getchar() в массив char, символ с кодом 255 ('я') будет трактоваться как EOF.

Вторая:
После чтения надо закончить массив нулевым символом, причём без EOF.

А что до двойного Ctrl-Z, то это особенность терминала - он не закрывается после передачи EOF, а остаётся открытым, и последующий getch() опять ждёт ввода. В принципе не обязательно жать Ctrl-Z, достаточно и Enter.

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 23:21 
Аватара пользователя


26/02/11
332
Спасибо за столь обширный ответ. Что такое EOF вроде бы как понятно, но вы меня еще больше запутали в его предназначении. Хорошо, тогда такой прямой вопрос: в каком случае функция getchar примет это значение? Иными словами можно ли с клавиатуры ввести это значение, для того чтобы показать что входной поток (строка) закончился? Я ведь его и использую в качестве "конца" строки.

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 23:27 
Аватара пользователя


31/10/08
1244
Dosaev
Немного поэкспериментировал с CTRL+Z оказывается если нажать
CTRL+Z затем enter то он интерпитируется как EOF
А если вначале ввести символ потом CTRL+Z, а затем Enther то уже CTRL+Z интерпретируется как стрелка

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 23:32 
Заслуженный участник


04/05/09
4582
Dosaev в сообщении #596007 писал(а):
Спасибо за столь обширный ответ. Что такое EOF вроде бы как понятно, но вы меня еще больше запутали в его предназначении. Хорошо, тогда такой прямой вопрос: в каком случае функция getchar примет это значение? Иными словами можно ли с клавиатуры ввести это значение, для того чтобы показать что входной поток (строка) закончился? Я ведь его и использую в качестве "конца" строки.
Это зависит от операционной системы. В Windows надо нажать Ctrl-Z. В Unix - Ctrl-D (причём это по умолчанию, командой stty можно изменить эту комбинацию, например, на Ctrl-Z). На Маке, может быть что-то ещё. В Windows символ Ctrl-Z обрабатывается в библиотеке stdio, не только для консоли, но и для любого файла открытого в текстовом режиме. В Unix этот символ обрабатывается где-то в драйвере консоли, и до программы сам символ Ctrl-D не уже доходит (в Unix нет различия между текстовым и бинарным режимом ввода).

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 23:35 
Аватара пользователя


31/10/08
1244
Цитата:
Спасибо за столь обширный ответ. Что такое EOF вроде бы как понятно, но вы меня еще больше запутали в его предназначении. Хорошо, тогда такой прямой вопрос: в каком случае функция getchar примет это значение? Иными словами можно ли с клавиатуры ввести это значение, для того чтобы показать что входной поток (строка) закончился? Я ведь его и использую в качестве "конца" строки.

EOF следует применять когда вы пишите консольную утилиту и она должна обрабатывать файлы поданные на вход. К примеру так test.exe <1.txt
А для ручного в вода лучше обрабатывать нажатие клавиши Enter.
lim(f(x)) уже привел пример.

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 23:36 
Заслуженный участник


04/05/09
4582
Дополнительная путанице с EOF в C ещё в том, что кроме символа ASCII, неформально называемом EOF (тот же Ctrl-Z), есть ещё символическая константа EOF равная -1. Вам важна именно эта константа, а каким именно символом конец ввода обозначается в консоли, изнутри программы, в коде на C - это не важно.

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 23:42 
Аватара пользователя


26/02/11
332
Pavia, спасибо.
venco,
venco в сообщении #596003 писал(а):
Проблем несколько.
Первая:
venco в сообщении #595578 писал(а):
EOF - не символ, а число (-1), не пересекающееся с реально прочитанными символами, возвращаемыми из getchar() (0...255). Одна из распространённых ошибок - сохранять результат getchar() в переменную типа char. В результате, если char - signed, то чтение остановится и на символе с кодом 255 (буква 'я' в виндовой кодировке), а если unsigned, то получится бесконечный цикл.
Т.е. после сохранения результата getchar() в массив char, символ с кодом 255 ('я') будет трактоваться как EOF.

Ответ на первую проблему:
код: [ скачать ] [ спрятать ]
Используется синтаксис C
#include <stdio.h>
#include <conio.h>
 
#define MAXLINE 10

int main()
{
    char line[MAXLINE];
    int i, c;
   
    i = 0;
   
    while ((c = getchar()) != EOF) {
          line[i] = c;
          ++i;
    }
    if (i < 10 && c == '\n') {
          line[i] = '\0';
        printf("%s", line);
    }
         
    getch();
    return 0;
}

Что здесь не так? :-(

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение16.07.2012, 23:51 
Заслуженный участник


11/05/08
32166

(Оффтоп)

Pavia в сообщении #595955 писал(а):
Потому что Сtrl-z это не EOF, а стрелочка.

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

 Профиль  
                  
 
 Re: Массив строк в С
Сообщение17.07.2012, 00:06 
Аватара пользователя


31/10/08
1244
Цитата:
Что здесь не так?

В цикле произойдёт переполнение массива раньше чем дайдёт до условия проверки переполнения.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 18 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group