Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.64/25: Рейтинг темы: голосов - 25, средняя оценка - 4.64
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,116
1

Цикл по строке (более изящный вариант)

16.07.2014, 19:55. Просмотров 4456. Ответов 26
Метки нет (Все метки)

когда я хочу пройти по строке я обычно сначала нахожу ее длину, а потом в цикле от 0 до длины прохожу, но я где то видел (никак не найду где) более изящный проход, там было че то со сдвигом указателя, навроде этого

C
1
2
char* str = "hello world";
for(*str; str < ; str++) // хз только какое условие поставить...
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.07.2014, 19:55
Ответы с готовыми решениями:

Есть ли более изящный вариант поиска файлов по нескольким расширениям
private void SetCurrentDirectory(string filePath) { List&lt;string&gt;...

Нужен изящный вариант блокировки вращения
к сожалению не додумался вставить рисунки с своего сайта, когда открывал первую тему (с форума),...

Угадать число от 1 до 100 за 7 попыток: есть ли более изящный подход, чем if/else?
Задача заключается в том что нужно написать программу который угадывает число пользователя от 1 до...

Смена процессора 1-й вариант - Intel Pentium G4560 Kabylake ( более дешевый ), а 2-й вариант - Intel Core i5-6
Хочу обновить комплектующие компьютера полностью. Присмотрел 2 сборки, которые отличаются только...

Какой вариант более оптимальный?
Доброго времени суток. Пишу лабу - распознаватель числовых констант. Возник вопрос, как...

26
Vlad0922
30 / 24 / 5
Регистрация: 20.11.2013
Сообщений: 65
16.07.2014, 20:08 2
Лучший ответ Сообщение было отмечено GetHelp как решение

Решение

C
1
2
3
4
5
6
  char *str="Hello!";
 
  while(*str){
      printf("%c",*str);
      ++str;
    }
Но после такого str будет указывать уже на конец и воспользоваться строкой повторно без манипуляций не получится, так что лучше использовать какой-нибудь промежуточный указатель

C
1
2
3
4
5
6
7
  char *str="Hello!";
  char *ptr=str;
 
  while(*ptr){
      printf("%c",*ptr);
      ++ptr;
    }
Примером такой манипуляции может быть (извините за натянутость) банальный сдвиг указателя на необходимое число памяти:
C
1
2
3
4
5
6
7
8
9
10
11
12
  char *str="Hello!";
  char length;
  length=0;
 
  while(*str){
      printf("%c",*str);
      ++length;
      ++str;
    }
 
  str-=length;
  puts(str);
Но, как видно, это достаточно некрасиво выглядит и по мне второй вариант выглядит лучше.
1
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,116
16.07.2014, 20:27  [ТС] 3
аа понятно спс, т.е. для for это просто

C
1
for(*str;;str++)
0
Vlad0922
30 / 24 / 5
Регистрация: 20.11.2013
Сообщений: 65
16.07.2014, 20:34 4
Почти
C
1
for(;*str;++str)
Т.к. синтаксис такой
C
1
for(инициализация;проверка;постусловие)
инициализация была сделана ранее
C
1
char *str="Hello!";
И теперь нужно проверять валидность указателя.
А вы перепутали проверку и инициализацию местами.
1
16.07.2014, 20:34
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,116
16.07.2014, 20:37  [ТС] 5
Vlad0922, аа т.е.

C
1
for(;*str;str++) //проверка на не NULL
0
Vlad0922
30 / 24 / 5
Регистрация: 20.11.2013
Сообщений: 65
16.07.2014, 20:38 6
Да, все верно
1
Vtulhu
425 / 379 / 200
Регистрация: 12.08.2011
Сообщений: 1,610
16.07.2014, 21:39 7
Может, стоило сначала почитать катехизис? В смысле, K&R? Там указаны идиоматически и идеологически верные конструкции. Вот, например, как бы я написал функцию подсчета пробельных символов в строке:

C
1
2
3
4
5
6
7
8
9
int count_spaces(const char* str)
{
    int counter = 0;
    int c;
    while( c = (unsigned char) *str++ ) {
        counter += !!isspace(c);
    }
    return counter;
}
Для новичка это может выглядеть непонятной мешаниной символов, но на самом деле там все логично и по-своему красиво. Если что-то непонятно - спрашивай. Но лучше попробуй разобраться сам с назначением каждого символа. Пока хоть один символ в этой функции кажется лишним или недостаточным - ты не достиг просветления.

И еще. Попробуй придумать, как сделать эту функцию универсальной. А вдруг нам понадобится определить количество алфавитных (isalpha), цифровых (isdigit), алфавитно-цифровых (isalnum) или еще каких-то символов? Каждый раз такую же функцию писать? Да, она короткая, но копипастить - это в любом случае плохо. Это нарушение принципа DRY. Пытаясь решить эту обманчиво простую задачу, ты узнаешь много нового о языке C.
1
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,116
16.07.2014, 22:25  [ТС] 8
Цитата Сообщение от Vtulhu Посмотреть сообщение
Может, стоило сначала почитать катехизис? В смысле, K&R? Там указаны идиоматически и идеологически верные конструкции.
без понятия что это...

Цитата Сообщение от Vtulhu Посмотреть сообщение
Для новичка это может выглядеть непонятной мешаниной символов
ну мне казалось что я уже не совсем новичек так то... просто и не новички иногда открывают для себя что то новое по функции все вполне понятно, разве что не видел раньше такую функцию isspace и не очень ясно зачем делается приведение типа из char к unsigned char... да и пожалуй не ясно зачем 2 отрицания... вроде ошибка
0
castorsky
1973 / 1076 / 87
Регистрация: 29.11.2013
Сообщений: 3,354
17.07.2014, 01:16 9
Цитата Сообщение от GetHelp Посмотреть сообщение
без понятия что это...
Это уже заметили
Цитата Сообщение от GetHelp Посмотреть сообщение
ну мне казалось что я уже не совсем новичек так то...
перекреститесь и зубрить K&R2.
Цитата Сообщение от Vtulhu Посмотреть сообщение
Попробуй придумать, как сделать эту функцию универсальной
Эти стремления к универсальности породили таких монстров как сначала algol 69, потом ada, потом c++. Все они не находят симпатии в академических кругах.
0
Vtulhu
425 / 379 / 200
Регистрация: 12.08.2011
Сообщений: 1,610
17.07.2014, 11:15 10
Цитата Сообщение от castorsky Посмотреть сообщение
Эти стремления к универсальности породили таких монстров как сначала algol 69, потом ada, потом c++. Все они не находят симпатии в академических кругах.
То есть Вы считаете правильным подходом наплодить кучу функций типа count_spaces, count_alnum, count_digits, отличающихся лишь тем, что функция isspace заменена на какую-то другую? И при чем тут algol 69? Судя по всему, Вы вообще не поняли, о чем речь идет. Мы тут чисто умозрительные примеры рассматриваем, а не С14 придумываем.

Добавлено через 2 минуты
Цитата Сообщение от GetHelp Посмотреть сообщение
ну мне казалось что я уже не совсем новичек так то...
И это говорит человек, который не только не читал K&R, но даже не знает, кто это такие.
1
ValeryS
Модератор
7527 / 5702 / 738
Регистрация: 14.02.2011
Сообщений: 19,515
Завершенные тесты: 1
17.07.2014, 11:18 11
Цитата Сообщение от Vtulhu Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
int count_spaces(const char* str)
{
    int counter = 0;
    int c;
    while( c = (unsigned char) *str++ ) {
        counter += !!isspace(c);
    }
    return counter;
}
можно вот так еще завернуть

C++
1
2
3
4
5
6
7
int count_spaces(const char* str)
{
    int counter = 0;
        while( *str ) 
          counter += ' '== *str++ ;
    return counter;
}
0
Vtulhu
425 / 379 / 200
Регистрация: 12.08.2011
Сообщений: 1,610
17.07.2014, 11:28 12
Если нас устроит подсчет пробелов - то да. А моя функция подсчитывает все пробельные символы.

http://www.cplusplus.com/reference/cctype/isspace/

Да, и отсутствие фигурных скобок я считаю очень плохим стилем. Насколько я знаю, были реальные случаи, когда это приводило к большим проблемам. Если язык позволяет что-то делать, это не означает, что это надо делать.
0
castorsky
1973 / 1076 / 87
Регистрация: 29.11.2013
Сообщений: 3,354
17.07.2014, 13:13 13
Vtulhu, нет. я считаю что каждая программа должна выполнять только одну задачу, но делать это шорошо. Пытаться засунуть весь функционал в одну программу аля windows way приведет к монструозности и избыточности.
0
korvin_
2406 / 1883 / 341
Регистрация: 28.04.2012
Сообщений: 6,481
17.07.2014, 14:00 14
Цитата Сообщение от castorsky Посмотреть сообщение
Vtulhu, нет. я считаю что каждая программа должна выполнять только одну задачу, но делать это шорошо. Пытаться засунуть весь функционал в одну программу аля windows way приведет к монструозности и избыточности.
Какой весь функционал? Vtulhu как раз и предлагает убрать из функции подсчета элементов лишний функционал --- предикат. Тогда функция count_chars будет выполнять ровно одну задачу и выполнять ее хорошо --- считать количество char'ов, удовлетворяющих какому-то критерию.

В семействе языков, к которым принадлежит и язык, чей логотип у тебя на аватарке, так и принято. Да и вообще везде так принято. Модульность, обобщенное программирование и все такое.

Добавлено через 2 минуты
Цитата Сообщение от Vtulhu Посмотреть сообщение
Насколько я знаю, были реальные случаи, когда это приводило к большим проблемам.
Угу, а еще были реальные случаи, когда человек себе гвоздь в голову забивал.
2
Vlad0922
30 / 24 / 5
Регистрация: 20.11.2013
Сообщений: 65
17.07.2014, 14:13 15
Эти стремления к универсальности породили таких монстров как сначала algol 69, потом ada, потом c++. Все они не находят симпатии в академических кругах.
Неужели все, кто пишет на си, так не любят с++?

Кстати, я никак не пойму, зачем вы пишите функции, которые непрозрачны для новичка. Код должен быть простым, если это не вредит эффективности.
Да и то, зачастую микрооптимизация не так важна, как оптимизация с алгоритмической точки зрения.

Я бы написал нечто вроде:
C
1
2
3
4
5
6
7
8
9
10
11
12
int count_spaces(const char* str)
{
    int counter = 0;
        while(*str){
            if(isspace(*str))
              ++counter;
 
            ++str;
          }
 
    return counter;
}
2
castorsky
1973 / 1076 / 87
Регистрация: 29.11.2013
Сообщений: 3,354
17.07.2014, 14:30 16
Цитата Сообщение от korvin_ Посмотреть сообщение
Какой весь функционал?
мой ответ казается этого вопроса
Цитата Сообщение от Vtulhu Посмотреть сообщение
То есть Вы считаете правильным подходом наплодить кучу функций типа count_spaces, count_alnum, count_digits, отличающихся лишь тем, что функция isspace заменена на какую-то другую?
Касательно того как конкретно реализовать conut_chars и возможности ее применения в различных проектах -- отдельный разговор. В раздел философии. И ежу понятно что лучше передать предикат аргументом. Но мы рискуем столкнуться с несоответствием типов (в общем случае), потере скорости на вычислении того что именно мы хотим вычислить и т.п. в таких случаях. Практика: приложение на базе curl api не справляется, рефакторю вычищая весь curl попутно реализуя все то же, но заточенное именно под задачу -- профит. Да, curl удобно, но... цель достигается тем что программа (читай функция) не универсальна и написана для конкретной задачи.

Добавлено через 3 минуты
Цитата Сообщение от Vlad0922 Посмотреть сообщение
Неужели все, кто пишет на си, так не любят с++?
тут вопрос не в любви или нелюбви. Прагматизм.
0
Vtulhu
425 / 379 / 200
Регистрация: 12.08.2011
Сообщений: 1,610
17.07.2014, 15:40 17
Цитата Сообщение от korvin_ Посмотреть сообщение
Угу, а еще были реальные случаи, когда человек себе гвоздь в голову забивал.
А бывает, что его человеку забивают. И тут весь вопрос не в том, забили или нет, а в том, сделал ли он все возможное, чтобы этого избежать. Надел ли каску, лез ли, куда не просят, соблюдал ли технику безопасности...

C
1
2
3
4
5
6
7
8
9
10
11
12
int count_spaces(const char* str)
{
    int counter = 0;
        while(*str){
            if(isspace(*str))
              ++counter;
 
            ++str;
          }
 
    return counter;
}
Замечательный образец кода, на примере которого ясно видно, почему скобки опускать нельзя. Это считается ошибкой с точки зрения многих code guide профессиональных команд. Были случаи, когда люди на этом обжигались. А любые ошибки - это убытки. Поставить фигурные скобки не стоит ничего. Есть даже программы, которые их расставляют принудительно. Единственное исключение можно было бы делать для такого варианта:

C
1
2
3
4
5
6
7
8
9
10
int count_spaces(const char* str)
{
    int counter = 0;
        while( *str ) {
            if(isspace(*str))  ++counter;
            ++str;
          }
 
    return counter;
}
Но я даже в таком случае пишу фигурные скобки. Еще раз уточню: это не блажь, это полезный опыт, добытый чужими потом, кровью, слезами и убытками. Если Вам охота наступать на грабли двадцатилетней давности - ССЗБ.

Что касается универсальности функции, то никакой философии тут нет. Я же не говорю, что всегда надо писать универсально. Вы забыли, в какой теме мы находимся. Речь изначально шла о том, что я посоветовал ТС сделать такую функцию универсальной, чтобы он узнал что-то новое о языке С. Вы когда решали в школе задачу про два яблока у Пети и три яблока у Кати, не спрашивали же у учительницы, зачем решать такую оторванную от жизни задачу, ведь у Пети, который учится в Вашем классе, нет ни одного яблока, а девочек с именем Катя вообще нет?
1
Vlad0922
30 / 24 / 5
Регистрация: 20.11.2013
Сообщений: 65
17.07.2014, 16:19 18
Кхм.
Я, конечно, все понимаю, но здесь фигурные скобки не нужны, лично я даже теоретически не могу придумать ситуацию, где они могут понадобится, когда ветвление одно и после него идет 1 оператор и только 1.

Да даже в таком примере скобки бы не понадобились:

C
1
2
3
4
5
6
7
8
9
10
11
12
int count_spaces(const char* str)
{
    int counter = 0;
        while(*str){
            if(isspace(*str))
              ++counter, printf("no braces!\n");
 
            ++str;
          }
 
    return counter;
}
Другое дело, когда у нас есть конструкция вида:
C
1
2
3
4
5
6
7
8
9
int foo(){
  if(foo2())
    if(foo3())
      return 1;
    else
      return 2;
 
  return 0;
}
Которая сильно отличается по смыслу от:
C
1
2
3
4
5
6
7
8
9
10
int foo(){
  if(foo2()){
    if(foo3())
      return 1;
    }
  else
    return 2;
 
  return 0;
}
Где наличие или отсутствие скобок явно изменяет смысл кода.

Добавлено через 9 минут
P.S.
Беру свои слова обратно: придумал ситуацию.
Такое возможно с макросами, например
C
1
2
3
4
5
6
7
8
9
10
11
12
#define SOME_MACRO  \
  printf("first\n");  \
  printf("second\n");
 
 
int main(void)
{
  if(0)
    SOME_MACRO;
 
  return 0;
}
Но, думаю, это неправильное проектирование самого макроса, т.к. с видом
C
1
2
3
4
5
6
7
8
9
10
11
12
#define SOME_MACRO  \
{ printf("first\n");  \
  printf("second\n"); }
 
 
int main(void)
{
  if(0)
    SOME_MACRO;
 
  return 0;
}
Все работает ожидаемо
1
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10297 / 6179 / 1555
Регистрация: 25.07.2009
Сообщений: 11,762
17.07.2014, 16:41 19
Цитата Сообщение от Vtulhu Посмотреть сообщение
Попробуй придумать, как сделать эту функцию универсальной.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <ctype.h>
 
int count_if(const char * str, int (*func)(int)) {
    return ( *str ) ? !!func(*str) + count_if(str+1, func) : 0;
}
 
int main(void) {
    const char * s = "Any, many, money, morE!";
    
    printf("String: %s\n");
    printf("Spaces: %d\n", count_if(s, isspace));
    printf("Uppers: %d\n", count_if(s, isupper));
    printf("Lower: %d\n", count_if(s, islower));
    printf("Puncts: %d\n", count_if(s, ispunct));
    
    return 0;
}
3
Vtulhu
425 / 379 / 200
Регистрация: 12.08.2011
Сообщений: 1,610
17.07.2014, 17:37 20
Цитата Сообщение от Vlad0922 Посмотреть сообщение
Я, конечно, все понимаю, но здесь фигурные скобки не нужны, лично я даже теоретически не могу придумать ситуацию, где они могут понадобится, когда ветвление одно и после него идет 1 оператор и только 1.
Вы путаете корректность с точки зрения синтаксиса и корректность с точки зрения стандартов кодирования. Можно придумать 1001 ситуацию (и что хуже того, многие из этих ситуаций происходили в действительности), когда эта возможность (писать без скобок) оборачивается против вас же. Например, добавили под иф еще одну строку и забыли ее оформить скобками. Смысл поменялся, не так ли? К тому же код становится хуже читаемым, потому что отступы становятся более значимыми. А они иногда ломаются. Например, в результате неправильной настройки какой-нибудь программы для автоматического форматирования. Я даже смутно припоминаю какой-то случай, когда некий довольно известный алгоритм (кажется, ELFHash) кочевал из одной журнальной статьи в другую с одной и той же опечаткой. Именно потому что автор поленился набрать НЕОБЯЗАТЕЛЬНЫЕ скобки.

Можно попытаться доказать от противного. Сколько существует стандартов кодирования, которые
а) ДОПУСКАЮТ бесскобочную запись одного оператора внутри блока
б) ТРЕБУЮТ бесскобочную запись одного оператора внутри блока

Я знаю:
а) http://habrahabr.ru/post/172091/
б) http://qt-project.org/wiki/Qt_Coding_Style

Конечно, Qt - довольно известный проект, но это все. Других таких я не знаю. Подавляющее большинство коуд гайдов, что я видел (а я видел немало, когда в свое время пытался подобрать подходящий; кончилось тем, что не подобрал, а просто выработал постепенно свой собственный, довольно специфический стиль), согласны со мной.

easybudda, я знаю, что Вы это знаете. Я хотел, чтобы ТС до этого дотумкался... Это обогатило бы его опыт.
0
17.07.2014, 17:37
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.07.2014, 17:37

Более быстрый вариант сравнения фотографий
Всем привет. Нужно сравнить на идентичность несколько сотен фотографий, чтобы убрать...

Encode/Decode - формат в более короткий вариант кода!
Вот сформатировал строку в Unicode: Но мне нужно его переделать в более короткий вариант, но...

Цикл в цикле? Каков лучший вариант?
Господа, поделитесь опытом, пожалуйста, для общего блага среди начинающих. Как лучше ввсего...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Закрытая тема Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru