Цитата(Метценгерштейн @ Nov 17 2014, 22:58)

спасет ли ситуацию, если я сразу инициализирую z нулем?
Не спасет, т.к. запятая вполне может оказаться в самом начале строки (str[0]), а потому индекс z1==0 для запятой вполне легален.
Цитата(Метценгерштейн @ Nov 17 2014, 22:58)

if ((str[i] >= 97) && (str[i] <= 122) || (str[i] >= 65) && (str[i] <= 90))
мне нужен диапазон латинских букв.
так корректно && писать? Вообще, думал, что надо все же одну &, т.к. это обязательное условие, что диапазон от 97 до 122.
Корректно так:
if ((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z')
где оператор || соединяет два логических выражения, заключенных в скобки (лишние скобки я удалила, чтобы не мешали видеть логику).
Как я вижу, вы по-прежнему не понимаете разницы между операциями & и &&, а так же между | и ||, а потому я вынуждена продолжить объяснения. Бинарные операторы & и | работают с ЦЕЛЫМИ ЧИСЛАМИ, и в результате своей операции тоже дают ЦЕЛОЕ ЧИСЛО. В этом смысле они родные братья арифметических операторов + - * / и по существу от них ничем не отличаются. Тогда как логичеcкие операторы && и || работают с БУЛЕВЫМИ величинами типа TRUE и FALSE. И результат их операции тоже БУЛЕВАЯ величина.
Переход от числовых величин к булевым осуществляют обычно операторы сравнения < <= > >= == !=. Именно они работают с числами, а в результате дают буля. После того, как вы что-то сравнили, у вас все числа и литеры превратились в булей, а потому дальше работать с булями возможно лишь с помощью && и ||,а про остальную арифметику забыть.
Язык C зачастую позволяет смешение типов, порой даже не выдавая на этот счет предупреждения, однако НЕ НАДО (!!!) без особой необходимости этим злоупотреблять. Этим вы не компилятору сделаете хуже, а самому себе! А если C++ будете осваивать, то там со смешением типов и вовсе строго. Поэтому чем раньше приучаться к дисциплине, тем лучше. А по началу предлагаю вам писать в качестве комментария обоснование причины, когда вы смешиваете разные типы, подсовывая операторам плохоперевариваемые продукты.
Вы ведь не делите букву на букву, когда понимаете, что в этих байтах лежат буквы, а не цифры? А, значит, разницу должны понимать, несмотря на то, что компилятору разделить две буквы друг на друга не составит труда. Это потому что язык С такой покладистый и малоругачий.
Например, почему я заменила выражение
str[i] >= 97
на
str[i] >= 'a'
хотя это в кодах одно и тоже? А потому что в первом случае в комментариях должно быть написано:
str[i] >= 97 // Я, Метценгерштейн, старый м...к, до сих пор не понимаю разницы между буквами и цифрами

Между тем, второй вариант был бы совершенно правильным, если бы по смыслу массив str был бы набит числами, скажем, от 8-разрядного АЦП.
Вот и в том старом варианте резало глаз, когда вы скармливали числовому оператору & два булевских аргумента. Я сразу же его пожалела, а вы не заметили, что ему скормили.
Бывают случаи, когда действительно есть необходимость подвергнуть букву числовой операции. Например, чтобы превратить большую литеру в маленькую и обратно. Но это тот самый уважительный случай, когда возникла НЕОБХОДИМОСТЬ! А вот заменять литеру 'z' на число 122 у вас такой необходимости не было, а потому и должны писать в комментарии оправдание своим действиям.
Цитата(Метценгерштейн @ Nov 17 2014, 22:58)

давайте тогда сразу уже по критике. Что еще глаз режет? Данный код полностью рабочий.
Ваш код режет глаз тем, что с фиговым z1 вообще на надо входить в цикл f! Лучше было бы написать проще, оно и понятнее:
Код
int z1 = 0; // начало первого слова
for (int i = 0; i < sizeof(str); i++)
{
if (str[i] == ',' || str[i] == '.') // если нашли запятую или точку, то
{ for (int f = z1; f < i; f++) printf("%c", str[f]); // печатаем слово до запятой или точки
printf("\n");
z1 = i+1; // запоминаем начало следующего слова
}
}
А если требуется фильтрация алфавитных литер от прочих, то вставляете выражение
if ((str[f] >= 'a' && str[f] <= 'z') || (str[f] >= 'A' && str[f] <= 'Z')
в цикл f перед печатью.