LINUX.ORG.RU

конкурс по си

 ,


7

4

На опеннете есть новость про то как сотрудник redhat шлёт левые патчи в ядро чтобы обойти проблемы systemd (http://www.opennet.ru/opennews/art.shtml?num=39476). Собстно, вот патчик:

http://lkml.iu.edu//hypermail/linux/kernel/1404.0/01327.html

Имхо, это ужас. Вот уж действительно товарищ принял упорин. Во-первых, он так и не понял почему редактирование /proc/cmdline это зло. Во-вторых, код ужасен, не? Неужели в сях нет способа проще вырезать подстроку? Ну и само по себе использование «магических» цифр 4 и 5 позорит код.

Так вот, конкурс по вырезанию произвольного слова из строки объявляю открытым! Учтите что слово может встречаться несколько раз.

★★★★★

Последнее исправление: beastie (всего исправлений: 2)

А strtok / strsep уже немодно? // В любом случае это ненужно.

anonymous
()
Ответ на: комментарий от qulinxao

Хорошо.

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

char * _remove(char * string, char * needl) {
  char * next = string;
  while(next = strstr(next, needl))
    strcpy(next, next + strlen(needl) + 1);
  return string;
}

Будет работать для валидных путей, собственно как и твоя мура с пробелами.

Carb
()
Ответ на: комментарий от Carb

Ты таки не прав.

man strcpy: The source and destination strings should not overlap, as the behaviour is undefined.

man memmove: The two strings may overlap; the copy is always done in a non-destructive manner.

А теперь марш обратно в школу, скильный осилятор ты мой.

beastie ★★★★★
()
Ответ на: комментарий от qulinxao

ах да, просити - я что-то загнался и думал, что ты мне отвечаешь.

Carb
()
Ответ на: комментарий от qulinxao

Ken Thompson, “Regular expression search algorithm,” Communications of the ACM 11(6) (June 1968), pp. 419–422

LOL, решение будет или не способе?

П.С. мое уже на pastebin, если что

wota ★★
()
Последнее исправление: wota (всего исправлений: 1)
#include <java.h>

public static void main(String... args) {
    if (args.length < 2) {
        throw new IllegalArgumentException();
    }
    String target = args[0];
    String wordToRemove = args[1];
    String result = target.replace(wordToRemoce, "");
    System.out.println(result);
}
CARS ★★★★
()
Последнее исправление: CARS (всего исправлений: 1)
Ответ на: комментарий от CARS

Ну, раз уж пошла такая пьянка :)

ackage main

import (
        "fmt"
        "strings"
)

var debug = "debug some debug and not only debug=debug but also debug debug"

func cutout(hay, needle, delim string) string {
        var r []string
        s := strings.Split(hay, delim)
        for _, x := range s {
                if !strings.HasPrefix(x, needle) {
                        r = append(r, x)
                }
        }
        return strings.Join(r, delim)
}

func main() {
        fmt.Println("Original:", debug)
        fmt.Println("Ugly:", strings.Replace(debug, "debug", "", -1))
        fmt.Println("Pretty:", cutout(debug, "debug", " "))
}

beastie ★★★★★
()
Ответ на: комментарий от Carb

Хрен оно работать будет:

gcc 1.c -o del_substr -Wall -Werror && ./del_substr "длинная строка, в которой строка - текст, который строка удалить надо строка вот" строка
длинная строка, в которой строка - текст, который строка удалить надо строка вот with deleted строка:
длинная , в которой  - текст, который  удалить надо  вот
А вот - результат пердящего в лужу краба:
длинная  в которой - теторыйкоторый удадо страдо вот

вот и код:

cat 1.c 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *delsubstr(char *strin, char *substr){
  size_t sl = strlen(substr), ol = strlen(strin);
  char *strout = NULL, *iptr, *optr, *eptr;
  if(sl > ol) return strdup(strin);
  strout = strdup(strin);
  if(!strout) return NULL;
  optr = strout; eptr = strout + ol;
  do{
    iptr = strstr(optr, substr);
    if(!iptr) break;
    optr = iptr;
    iptr += sl;
    if(iptr >= eptr) break;
    ol = strlen(iptr) + 1;
    memmove(optr, iptr, ol);
  }while(1);
  optr = strdup(strout);
  free(strout);
  return optr;
}

char * _remove(char * string, char * needl) {
  char * next = string;
  while((next = strstr(next, needl)))
    strcpy(next, next + strlen(needl) + 1);
  return string;
}

int main(int argc, char **argv){
  if(argc != 3){
    printf("usage: %s string_ori substring\n", argv[0]);
    return 1;
  }
  printf("%s with deleted %s:\n%s\n", argv[1], argv[2], delsubstr(argv[1], argv[2]));
  printf("А вот - результат пердящего в лужу краба:\n%s\n", _remove(argv[1], argv[2]));
  return 0;
}
Eddy_Em ☆☆☆☆☆
()

Вроде, чисто сишный тред, а срач как какие-нибудь лишперы развели.

Virtuos86 ★★★★★
()

Если не обращать внимание на тотальный маразм самой этой идеи, почему debug просто не забить пробелами?

anonymous
()

Выложу и я свой вариант

#include <string.h>
#include <assert.h>

char * strdel(const char *needle, char *haystack) {
    const size_t n_length = strlen(needle);
    const size_t h_length = strlen(haystack);
    size_t i, j;

    assert(needle);
    assert(haystack);

    if (n_length == 0)
        return haystack;

    for (i = 0, j = 0; i < h_length; i++) {
        if (haystack[i] == needle[0] && strncmp(&haystack[i], needle, n_length) == 0) {
            i += n_length;              // shift iterator position forward
        } else {
            haystack[j] = haystack[i];  // copy symbol to non-shifted position (backwards)
            j++;
        }
    }
    haystack[j] = '\0';                 // FINISH HIM!

    return haystack;
}

Eddy_Em, мсти! :)

KennyMinigun ★★★★★
()
Ответ на: комментарий от beastie

Ещё раз, мув левее и в ноль безопасен, мув же правее опасен, но он тут и не используется. В чем же я не прав?

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

Т.е. когда ты говоришь мне «маршвшколу» - ты не оскарбляешь, а когда говорю я - это оскарбление, флуд и прочее. Это «нешкольность» во все поля.

Carb
()
Ответ на: комментарий от KennyMinigun

Выложу и я свой вариант
strncmp

Ы. Народ, вы и правда верите, что вручную напишете более эффективный strstr, чем в libc, и перекроете быстродействие варианта beastie? Публикуйте уж цифры.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Народ, вы и правда верите, что вручную напишете более эффективный strstr

да.

чем в libc

Смотря в какой.

перекроете быстродействие варианта beastie

В говно. Нунужный меммув, ненужный strchr(), который заменяется на +1, либо на if(*cur == ' ') +=1;

А так же тормазнутость вообще всех функций glibc, в которых они самый илитные из всех либц. Это всё можно сделать за memcpy_not(), который в один проход копируя выбрасывает нужные подстроки.

Публикуйте уж цифры.

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

Carb
()
Ответ на: комментарий от tailgunner

Народ, вы и правда верите, что вручную напишете более эффективный strstr,

Не в том дело :) Тут подход такой, копирование посимвольно.

А цифры, да, интересно.

KennyMinigun ★★★★★
()
Ответ на: комментарий от Carb

К сожалению мой ответ тебе тоже пал смертью храбрых от руки Ъ-Админа. Повторюсь:

Напомню тебе только про скандальчик с тем же Торвальдсом, Адобе и разрабами libc, когда вдруг флеш хрипеть начал. А всё от того, что порядок, с какого конца strcpy копировать начнёт не обговорен, может в любой момент поменяться и может быть вообще разным для разных архитектур.

Т.ч. прекращай умничать пожалуйста, у тебя это плохо получается.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)

Патч всё равно отклонили же. И не потому что код говно, а потому что сама идея говно.

Date Wed, 2 Apr 2014 11:57:41 -0700 Subject Re: [RFC PATCH] cmdline: Hide «debug» from /proc/cmdline From Linus Torvalds <>

On Wed, Apr 2, 2014 at 11:42 AM, Steven Rostedt <rostedt@goodmis.org> wrote:


The response is:

«Generic terms are generic, not the first user owns them.»

And by «their» you mean Kay Sievers.

Key, I'm f*cking tired of the fact that you don't fix problems in the code *you* write, so that the kernel then has to work around the problems you cause.

Greg - just for your information, I will *not* be merging any code from Kay into the kernel until this constant pattern is fixed.

This has been going on for *years*, and doesn't seem to be getting any better. This is relevant to you because I have seen you talk about the kdbus patches, and this is a heads-up that you need to keep them separate from other work. Let distributions merge it as they need to and maybe we can merge it once it has been proven to be stable by whatever distro that was willing to play games with the developers.

But I'm not willing to merge something where the maintainer is known to not care about bugs and regressions and then forces people in other projects to fix their project. Because I am *not* willing to take patches from people who don't clean up after their problems, and don't admit that it's their problem to fix.

Kay - one more time: you caused the problem, you need to fix it. None of this «I can do whatever I want, others have to clean up after me» crap.

Linus

PolarFox ★★★★★
()
Ответ на: комментарий от Carb

перекроете быстродействие варианта beastie

В говно

Ну ты-то герой, понятное дело. Где исходники со сравнением?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Народ, вы и правда верите, что вручную напишете более эффективный strstr, чем в libc

нет, по крайней мере это будет точно не в пару строк, но тут вроде и не требовался самый быстрый вариант, а так - да, strncmp по каждой позиции - очень неэффективно

wota ★★
()
Ответ на: комментарий от CARS
gcc 1.c
1.c:1:18: фатальная ошибка: java.h: Нет такого файла или каталога
 #include <java.h>
                  ^
компиляция прервана.
comp00 ★★★★
()
Ответ на: комментарий от beastie

Напомню тебе только про скандальчик с тем же Торвальдсом, Адобе и разрабами libc, когда вдруг флеш хрипеть начал.

Это было для копирование в правую сторону, и про то, что мемкопи не всегда работает - это так. Другое дело, что неосиляторы не понимают когда она работает, а когда нет.

А всё от того, что порядок, с какого конца strcpy копировать начнёт не обговорен

Обговорён - логикой. Нет никакого смысла копировать сконца строки, ну никакого.

может в любой момент поменяться

Не может. Нет ни одного юзкейса в котором нужен именно обход вниз, кроме каких-то кастыльных махинаций. В большенстве же юзкейсов растут адерса вверх, и никогда не будет в юзкейсах где на это покласть юзать обход вниз, если везде юзается вверх - это основа. Попрать которую может только дебилушка. Что-то необычное юзается только тогда, когда в этмо есть смысл, а не отпопа.

может быть вообще разным для разных архитектур

Не может. В большенсте юзкейсов адреса обходят снизу вверх. Поэтому никто в здравом уме не будет это ограничивать, либо запиливать подругому.

А оптимальный strcpy() работает ТОЛЬКО вверх строки. У него объеденены strlen() и memcpy() в одну.

Carb
()
Ответ на: комментарий от tailgunner

А на что тогда конкурс? :)

размер кода, например

wota ★★
()

Эй, разбаньте суперхаккиллера! Это же удобно, когда он зарегистрированный.

tailgunner ★★★★★
()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *remove_string(const char *haystack, char *needle) {
  int n = strlen(needle);
  char *result = malloc(1+strlen(haystack));
  memset(result, 0, 1+strlen(haystack));

  int state = -1; // will be from 0 to strlen(needle)-1
  int i=0; // writing output
  
  for (; *haystack; haystack++) {
    if (*haystack == needle[state+1]) {
      state++;
      if (state == n-1) {
        state = -1;
        continue;
      }
    }
    else if (state == -1) {
      result[i++] = *haystack;
    }
    else {
      // dump the (state + 1) chars to the result
      memcpy(result+i, needle, state+1);
      i += state+1;
      state = -1;
    }
  }
  result[i] = '\0';
  return result;
}

int main() {
  char teststring[] = "debug some debug and not only debug=debug but also debug";
  printf("%s\n", remove_string(teststring, "debug"));
  return 0;
}
nokachi
()
Ответ на: комментарий от beastie
Блокирован 03.04.2014 19:31:58, модератором beastie по причине: дебил

Хм. Я, конечно, понимаю, что достал. Но таки можно же формулировку попроще сделать.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от nokachi

годно , почти как и планировал я :)

тока добавь что бы не выкусывала из строки когда игла часть другого слова ( в начале, середине, конце) , филить пробелами(тут аноним остроумно выше отметил) нужно только когда игла отдельное слово .

qulinxao ★★☆
()
Ответ на: комментарий от Eddy_Em

Куда ещё проще? У человека напрочь отсутствуют социальная компетенция и способность учиться. Знаний ноль, а гонору на целую толпу анонимусов. Я его уже год гоняю. По началу я его даже ещё защищал и надеялся, что исправится. Надежда эта окончательно потеряна. Диагноз неблагоприятный.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от beastie

Странно, что он еще не начал срать из-под анонима.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от beastie

А тебя предупреждали. Все с пациентом было понятно с самого начала.

anonymous
()
Ответ на: комментарий от qulinxao

А, я думал просто подстроку вырезать. Ну тогда так

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *remove_string(const char *haystack, const char *needle) {
  int n = strlen(needle);
  char *result = malloc(1+strlen(haystack));
  memset(result, 0, 1+strlen(haystack));

  int state = -1; // will be from 0 to strlen(needle)-1
  int i=0; // writing output

  char prev = ' ';
  
  for (; *haystack; prev=*haystack, haystack++) {
    if (*haystack == needle[state+1]) {
      if (state == -1 && prev != ' ') {
        result[i++] = *haystack;
        continue;
      }

      state++;
      if (state == n-1) {
        state = -1;
        if (!*(haystack+1) ||
            *(haystack+1)==' ')
          continue;
        else {
          memcpy(result+i, needle, n);
          i += n;
        }
      }
    }
    else if (state == -1) {
      result[i++] = *haystack;
    }
    else {
      // dump the (state + 1) chars to the result
      memcpy(result+i, needle, state+1);
      i += state+1;
      state = -1;
    }
  }
  result[i] = '\0';
  return result;
}

int main() {
  char teststring1[] = "debug some debug and not only debug=debug but also debug but not undebug";
  char teststring2[] = "debug some debug and not only debug=debug but also debug but not debugging";
  printf("%s\n", remove_string(teststring1, "debug"));
  printf("%s\n", remove_string(teststring2, "debug"));
  return 0;
}

nokachi
()
Ответ на: комментарий от tailgunner

А на что тогда конкурс?

На размер и понятность кода. Я хотел выяснить правда ли задача решается настолько криво как это сделал девелопер по ссылке.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Я хотел выяснить правда ли задача решается настолько криво как это сделал девелопер по ссылке.

Девелопер по ссылке решал другую задачу в других условиях.

tailgunner ★★★★★
()
Ответ на: комментарий от Harald

а вы помните, что дело происходит в ядре?

Да. Но, вроде, strstr там есть :)

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

Если это действительно в ведре предполагалось делать, то это уж совсем зверский быдлокод!

Подобные подходы "индусов" из тормозиллы и хромого приводят к тому, что неделька аптайма раздувает потребляемую память до небес! Здесь же — страшно представить! Ведь, в отличие от тормозиллы или хромого, ведро не перезапустишь с сохранением всего остального! Это только компьютер перезагружать...

Похоже, поцтерингомания совсем уже людям мозг выела.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от tailgunner

Девелопер по ссылке решал другую задачу в других условиях.

я думаю, в ядре достаточно функций для работы со строками.

true_admin ★★★★★
() автор топика
Ответ на: комментарий от true_admin

При чём, что мне ещё не понятно — то что мало того, что там всё нужное есть, так ещё и то, что операция это имхо не такая частая, что бы городить такой ужасный хак и жертвовать ради сомнительной экономии тактов читаемостью.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от true_admin

ищу работу , кушать охота.

как то вот: достаточно медленно , но вроде как прозрачно.

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
inline char*nxt(char* s){while(isalpha(*++s));return s;}
//fill space in memory
char*
wordstrips(char *src, char * needle)
{
        if(!*needle)return src;
        int n=strlen(needle);
        char *l=src-1,*r;
        do{
                r=nxt(l);
                if(r-++l!=n)continue;
                if(strncmp(l,needle,n))continue;
                while(l<r)*l++=' ';
        }while(*(l=r));
        return src;
}


void
test(char *s,char *ndl)
{
        char *res = (char*)malloc(1+strlen(s));
        printf( "from:%s\n  to:%s\n",s,wordstrips(strcpy(res,s),ndl));
        free(res);
}
int
main( void)
{
        char *test1="db dbb bdb bbdbb db dbdb db";
        test(test1,"db");
        return 0;
}

wota

прошу найти баги.

qulinxao ★★☆
()
Ответ на: комментарий от qulinxao

но-но. ты разговариваешь с настоящим сварщиком^W программистом.

не вникал в срач на lkml, но если надо вырезать из строки нехорошие слова, то сначала строка бьётся на слова, и каждое из них сравнивается с нехорошим(и). при отрицательном результате сравнения пишется в выхлоп. если оптимизация зачесалась в ягодицах — будь мужыком, запили итератор.

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

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.