Сохранение ведущий пробел при чтении>> запись файла линию за линией в ударе

Продолжение моей предыдущей регистрации.

Шаблоны являются одной из главных причин, почему C++ перестал работать так плачевно в intellisense, независимо от используемого IDE. Из-за шаблонной специализации IDE никогда не может быть действительно уверен, существует ли данный участник или нет. Рассмотрите:

template <typename T>
struct X {
    void foo() { }
};

template <>
struct X<int> { };

typedef int my_int_type;

X<my_int_type> a;
a.|

Теперь, курсор в обозначенном положении, и это чертовски трудно для IDE для высказывания в той точке, если, и что, имеют участники a. Для других языков парсинг был бы прост, но для C++, довольно мало оценки необходима заранее.

Это ухудшается. Что, если my_int_type были определены в шаблоне класса также? Теперь его тип зависел бы от другого аргумента типа. И здесь, даже сбой компиляторов.

template <typename T>
struct Y {
    typedef T my_type;
};

X<Y<int>::my_type> b;

После небольшого количества взглядов, программист пришел бы к заключению, что этот код совпадает с вышеупомянутым: Y<int>::my_type твердость к int, поэтому b должна быть тем же типом как a, правильно?

Неправильно. В точке, где компилятор пытается разрешить этот оператор, он еще на самом деле не знает Y<int>::my_type! Поэтому это не знает, что это - тип. Это могло быть что-то еще, например, функция членства или поле. Это могло бы дать начало неоднозначностям (хотя не в данном случае), поэтому компилятор перестал работать. Мы должны сказать ему явно, что обращаемся к имени типа:

X<typename Y<int>::my_type> b;

Теперь, компиляции кода. Чтобы видеть, как неоднозначности являются результатом этой ситуации, рассмотрите следующий код:

Y<int>::my_type(123);

Этот оператор кода совершенно допустим и говорит C++ выполнять вызов функции к [1 111]. Однако, если бы my_type не функция, а скорее тип, этот оператор все еще был бы допустим и выполнил бы специальный бросок (бросок функционального стиля), который часто является вызовом конструктора. Компилятор не может сказать, который мы имеем в виду, таким образом, мы должны снять неоднозначность здесь.

6
задан Joel Hooks 30 October 2009 в 04:49
поделиться

4 ответа

Вместо:

4
ответ дан 8 December 2019 в 02:07
поделиться

это слишком дорогой способ объединения файлов.

cat ../best-practices/*.textile >  ../best_practices.textile

, если вы хотите добавить пробел (новую строку) к каждому файлу при объединении, используйте awk

awk 'FNR==1{print "">"out.txt"}{print > "out.txt" }' *.textile

ИЛИ

awk 'FNR==1{print ""}{print}' file* > out.txt
4
ответ дан 8 December 2019 в 02:07
поделиться

Это позволяет вам вставлять новые строки между каждым входным файлом, как вы это делали в исходном скрипте:

for f in $FILES; do echo -ne '\n\n' | cat "$f" -; done > $OUTPUT

Обратите внимание, что $ FILES не цитируется, чтобы это работало (в противном случае дополнительные символы новой строки появляются только один раз в конце всего вывода), но $ f необходимо заключить в кавычки, чтобы защитить пробелы в именах файлов, если они существуют.

1
ответ дан 8 December 2019 в 02:07
поделиться

Как отмечали другие, использование cat или awk вместо цикла чтения-эха - гораздо лучший способ сделать this - позволяет избежать проблемы с обрезкой пробелов (и пары других, на которые вы еще не наткнулись), работает быстрее и, по крайней мере, с cat, это просто более чистый код. Тем не менее, я хотел бы попытаться заставить цикл чтение-эхо работать правильно.

Во-первых, проблема обрезки пробелов: команда чтения автоматически обрезает начальные и конечные пробелы; это можно исправить, изменив определение пробела, установив для переменной IFS пустое значение. Кроме того, read предполагает, что обратная косая черта в конце строки означает, что следующая строка является продолжением и должна быть соединена с этой; чтобы исправить это, используйте его флаг -r (raw). Третья проблема заключается в том, что многие реализации эхо интерпретируют escape-последовательности в строке (например, они могут превратить \ n в фактическую новую строку); чтобы исправить это, используйте вместо этого printf. Наконец, как и общее правило гигиены сценариев, вы не должны использовать cat, когда вам это действительно не нужно; вместо этого используйте перенаправление ввода. С этими изменениями внутренний цикл выглядит так:

while IFS='' read -r line; do 
  printf "%s\n" "$line">>$OUTPUT
done <$f

... есть еще пара проблем с окружающим скриптом: строка, которая пытается определить ФАЙЛЫ как список доступных файлов .textile, заключена в кавычки, это означает, что он никогда не расширяется до фактического списка файлов. Лучший способ сделать это - использовать массив:

FILES=(../best-practices/*.textile)
...
for f in "${FILES[@]}"

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

Наконец, есть echo ""> $ OUTPUT в верхней части циклических файлов, которые собираются стереть вывод файл каждый раз (т.е. в конце он содержит только последний файл .textile); это нужно переместить до цикла. Я не уверен, что здесь имелось в виду поместить одну пустую строку в начало файла или три пустые строки между файлами (одну в начале и две в конце), поэтому я не уверен, что именно соответствующая замена есть. В любом случае, вот что я могу сделать после исправления всех этих проблем:

#!/bin/sh
OUTPUT="../best_practices.textile"
FILES=(../best-practices/*.textile)

: >"$OUTPUT"
for f in "${FILES[@]}"
do
  echo "Processing $f file..."
  echo >>"$OUTPUT"

  while IFS='' read -r line; do 
    printf "%s\n" "$line">>"$OUTPUT"
  done <"$f"

  echo >>"$OUTPUT"
  echo >>"$OUTPUT"
done
40
ответ дан 8 December 2019 в 02:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: