Linux программирование в примерах | страница 63



В этом случае аргументами являются указатель на свободную область буфера, размер оставшейся части буфера и указатель >FILE для чтения.

Комментарии в строках 32–36 очевидны; если встречается нулевой байт, программа выводит сообщение об ошибке и представляет вывод как пустую строку. После компенсирования нулевого байта (строки 30–41) код продолжает работу.

>43 /* Обойти только что прочитанный текст. */

>44 p += len;

>45

>46 /* Если последний символ - не конец строки, она не поместилась

>47    целиком в буфер. Увеличить буфер и попытаться снова. */

>48 if (p[-1] != '\n')

>49  goto more_buffer;

>50

>51 /* Мы получили новую строку, увеличить число строк. */

>52 ++nlines;

Строки 43–52 увеличивают указатель на участок буфера за только что прочитанными данными. Затем код проверяет, является ли последний прочитанный символ символом конца строки. Конструкция >p[-1] (строка 48) проверяет символ перед p, также как >p[0] является текущим символом, а >p[1] — следующим. Сначала это кажется странным, но если вы переведете это на язык математики указателей, >*(p-1), это приобретет больший смысл, а индексированная форма, возможно, проще для чтения.

Если последний символ не был символом конца строки, это означает, что нам не хватило места, и код выходит (с помощью >goto) для увеличения размера буфера (строка 49). В противном случае увеличивается число строк.

>54 #if !defined(WINDOWS32) && !defined(__MSDOS__)

>55 /* Проверить, что строка завершилась CRLF; если так,

>56    игнорировать CR. */

>57 if ((p - start) > 1 && p[-2] == '\r')

>58 {

>59  --p;

>60  p[-1] = '\n';

>61 }

>62 #endif

Строки 54–62 обрабатывают вводимые строки, следующие соглашению Microsoft по завершению строк комбинацией символов возврата каретки и перевода строки (CR-LF), а не просто символом перевода строки (новой строки), который является соглашением Linux/Unix. Обратите внимание, что >#ifdefисключает этот код на платформе Microsoft, очевидно, библиотека > на этих системах автоматически осуществляет это преобразование. Это верно также для других не-Unix систем, поддерживающих стандартный С.

>64  backslash = 0;

>65  for (p2 = p - 2; p2 >= start; --p2)

>66  {

>67   if (*p2 != '\\')

>68   break;

>69   backslash = !backslash;

>70  }

>71

>72  if (!backslash)

>73  {

>74   p[-1] = '\0';

>75   break;

>76  }

>77

>78  /* Это была комбинация обратный слеш/новая строка. Если есть

>79     место, прочесть еще одну строку. */

>80  if (end - p >= 80)

>81   continue;

>82

>83  /* В конце буфера нужно больше места, поэтому выделить еще.