17 berichten aan het bekijken - 1 tot 17 (van in totaal 17)
  • Q:

    Bijdrager
    dj bazzie wazzie

    [C]Karakters in tekenreeks vervangen(Volgend probleem)

    Is er in C ook een mogelijkheid om tekenreeksen te wijzigen? Soms staat er namelijk in een bestandsnaam een quote en deze moet dan escaped worden. Als het niet wil zal ik dus karakter voor karakter kijken of het gelijk is aan een quote en zo ja dan in de nieuwe tekenreeks een quote ervoor plaatsen.

    EDIT: Ik zoek een functie in C maar ik heb het niet kunnen vinden in string.h. Anders is mijn post misschien een beetje onduidelijk


    Bijdrager
    DeMaccer

    misschien dit:

    void replace( iterator start, iterator end, const TYPE& old_value, const TYPE& new_value );


    Bijdrager
    dj bazzie wazzie

    Ik kan het niet vinden en mijn xcode maakt mijn code niet af dus zal in een library zijn die ik niet include heb. Welke library hoort hierbij dan?


    Bijdrager
    dj bazzie wazzie

    Opgelost,

    ik heb net op een andere website gevonden dat er geen functie is voor C dus moet ik maar even verder zoeken hoe ik dat moet aanpakken zodat het snel en goed werkt.

    Alsvast bedankt


    Bijdrager
    ottovds

    mss een kleine tip: het programma popchar X (dan vind je alle tekens snel)


    Bijdrager
    dj bazzie wazzie

    Dank je wel… Ik gebruik zelf het programma ‘full key codes’ en ‘ascii table’


    Bijdrager
    dj bazzie wazzie

    Hoi ik heb nu deze code geschreven en ik ben nog niet zo heel erg bekend met C. Ik vroeg mij nu af waarom ik hier een warning krijg van mijn compiler. De warning die ik krijg is

    warning: incompatible implicit declaration of built-in function ‘malloc’

    op regel 13: stringbuffer = malloc(strlen(search) + 1);

    [code:1:ab7a2b93f0]char * str_replace (char *string, char *search ,char *replace) {
    char *stringbuffer;
    char *tmpstring;
    char *newstring;
    int bufferlength;
    int stringlength;
    int i;

    bufferlength = strlen(search);
    stringlength = strlen(string);
    stringbuffer = malloc(strlen(search) + 1);

    for (i = 0; i < (stringlength – bufferlength + 1); i++) {

    strncpy(stringbuffer, string+i, strlen(search));
    stringbuffer[bufferlength + 1] = ‘’;

    if (strcmp(stringbuffer, search) == 0){
    newstring = malloc(strlen(string) – strlen(search) + strlen(replace)+1);
    tmpstring = malloc(i + strlen(replace) + 1);

    strncpy(tmpstring, string, i);
    strcat(tmpstring, replace);

    newstring = str_replace(string+(i+strlen(replace)), search, replace);

    strcat(tmpstring, newstring);
    strcpy(newstring, tmpstring);
    free(tmpstring);
    free(stringbuffer);
    return newstring;
    }

    }
    free(stringbuffer);
    return string;
    } [/code:1:ab7a2b93f0]

    Alvast bedankt.

    p.s. ik heb deze code zelf geschreven omdat ik ten eerste dacht dat ik er iets van op zou steken en de examples op internet deden het niet


    Bijdrager
    Reflex

    de standaardimplementatie van malloc returned een void pointer. Er is niets mis met een cast naar een char pointer, maar de compiler waarschuwt je even… je kunt dit wegwerken door (char *)malloc(..) te schrijven.

    Let wel op dat je de juiste pointers released enzo, en dat alles wat je mee geeft ook goed is. Ik heb niet je code reviewed, dit was enkel een antwoord op je vraag.


    Bijdrager
    TGV

    Zet eens
    [code:1:893666e16e]
    #include <stdlib.h>
    #include <string.h>
    [/code:1:893666e16e]
    aan het begin van je programma.

    Verder is je code nogal inefficient (maar dat zal je wel niet zo erg vinden, maar je gebruikt herhaaldelijk strlen() voor strings die niet van lengte veranderen terwijl je de lengte al hebt en zou je strncmp kunnen gebruiken in plaats van strncpy en dan strcmp). Erger is dat je nergens controleert of malloc wel een goede pointer teruggeeft (dus != NULL). Dat moet je echt wel doen en dan ook zelf NULL teruggeven (niet vergeten alle gemallocte strings even vrij te geven).

    Je vervangt op deze manier trouwens maar een voorkomen van je zoekstring ipv allemaal. Als je het allemaal wat makkelijker wilt doen, kan ik je deze functie aanraden: strpos. En als je meerdere substituties wilt doen, moet je dus in een lusje door je string heenlopen zolang strpos nog voorkomens vindt.


    Bijdrager
    dj bazzie wazzie

    Ja goed na mijn eerste progje om wortel te trekken in C is dit mijn tweede progje.

    @reflex: Ik weet dat jij veel ervaring hebt en er niet aan twijfelde dat je de code graag anders wou zien. Bedankt voor je info

    @tgv: Ja ik ben dus niet bekend met deze dingen. ik beheers PHP, shel scripten, applescript en nog een paar simpelere programmeertalen waar geheugen automatisch wordt aangemaakt voor je als je een string wil aanmaken. Ik zal ook zoveel mogelijk proberen wat jij verteld hebt maar het is een functie die ongeveer iedere run 1.400.000 keer wordt aangeroepen. Hoe schoner en vloeiender de code hoe beter het zal zijn natuurlijk. Ik vervang alle zoek strings wel hoor. Als ik namelijk de eerste heb vervangen dan stuur ik mijn volgende stukje string wat allemaal erna komt in de dezelfde functie. Dus je hebt een functie in een functie in een functie etc… net zoveel als er een match is

    Die includes heb ik erbij staan. Maar ik dacht dat het niet nodig was om alles hier te plaatsen. omdat het programma inmiddels al 800 regels lang is.

    ook bedankt voor jou bijdrage


    Bijdrager
    Reflex

    Ik heb even gegoogled, daar ik momenteel geen tijd heb om het zelf te coden (search string: “C string replace routine”, 2e hit)

    [code:1:117d26c333]
    /* Given a string, replaces all instances of "oldpiece" with "newpiece".
    *
    * Modified this routine to eliminate recursion and to avoid infinite
    * expansion of string when newpiece contains oldpiece. –Byron
    */
    char *replace(char *string, char *oldpiece, char *newpiece) {

    int str_index, newstr_index, oldpiece_index, end,

    new_len, old_len, cpy_len;
    char *c;
    static char newstring[MAXLINE];

    if ((c = (char *) strstr(string, oldpiece)) == NULL)

    return string;

    new_len = strlen(newpiece);
    old_len = strlen(oldpiece);
    end = strlen(string) – old_len;
    oldpiece_index = c – string;

    newstr_index = 0;
    str_index = 0;
    while(str_index <= end && c != NULL)
    {

    /* Copy characters from the left of matched pattern occurence */
    cpy_len = oldpiece_index-str_index;
    strncpy(newstring+newstr_index, string+str_index, cpy_len);
    newstr_index += cpy_len;
    str_index += cpy_len;

    /* Copy replacement characters instead of matched pattern */
    strcpy(newstring+newstr_index, newpiece);
    newstr_index += new_len;
    str_index += old_len;

    /* Check for another pattern match */
    if((c = (char *) strstr(string+str_index, oldpiece)) != NULL)
    oldpiece_index = c – string;

    }
    /* Copy remaining characters from the right of last matched pattern */ strcpy(newstring+newstr_index, string+str_index);
    return newstring;
    }

    [/code:1:117d26c333]

    Ziet er volgens mij wel goed uit… Vergelijk en leer!


    Bijdrager
    TGV

    De implementatie bevat een enorme mogelijkheid voor buffer overflow. Als je het goed wilt doen, moet je eerst tellen hoe vaak je zoekstring voorkomt, dan de lengte van de nieuwe string uitrekenen (= oude_string_lengte – aantal_hits * (lengte_vervanging – lengte_zoekstring)), ruimte alloceren en dan de vervanging daadwerkelijk uitvoeren.


    Bijdrager
    koen

    Dit is allemaal veeeeel makkelijker in Objective-C. :P


    Bijdrager
    dj bazzie wazzie

    @reflex: Ik heb ook gezocht met de zelfde zoek functie in google maar ik zag alleen maar c++ code.

    @tgv: ik dacht dat het mooi snel zou zijn als ik maar 1 keer door de char heen hoef te lopen en te kijken wat er vervangen moet worden en dan poer direct actie ondernemen. zodat uiteindelijk de gehele tekenreeks maar in 1 loop is uitgevoerd in principe.

    @koen: in php en applescript nog makkelijker


    Bijdrager
    Reflex

    [code:1:558822e093]
    #import "NSString+stringByReplacingString.h"

    @implementation NSString (stringByReplacingString)

    + (NSString *)stringByReplacingString:(NSString *)source forString:(NSString *)dest inString:(NSString *)origin {
    NSString * retVal = origin;
    NSRange pos;

    while( (pos = [retVal rangeOfString:source]).length > 0 ) {
    retVal = [NSString stringWithFormat:@"%@%@%@",
    [retVal substringToIndex:pos.location],
    dest,
    [retVal substringFromIndex:pos.length+pos.location]];
    }

    return (retVal);
    }

    @end
    [/code:1:558822e093]

    Zoiets:)

    werking:

    [code:1:558822e093]
    myString = [NSString stringByReplacingString:@"koe" forString:@"aap" inString:@"De koe hing in de boom. Een koe is erg lenig"];
    // myString autoreleased
    [/code:1:558822e093]

    Niet erg efficient tho…


    Bijdrager
    TGV

    En op de command line nog makkelijker: sed ‘s/…/…/’…

    Je moet de afweging maken wat meer tijd kost: steeds een nieuwe buffer alloceren en de nieuwe string erin kopieren of twee keer door de string lopen. Als het om meer dan 1 vervanging gaat, wint de eerste, omdat het kopieren steeds langer gaat duren. Elke keer wordt een groot deel van de string gekopieerd en dat duurt minstens net zo lang als een simpele zoekactie in die string. Daarnaast is malloc/free relatief duur.


    Bijdrager
    dj bazzie wazzie

    Oke dank je wel allemaal…

    @reflex: na enig aanpassingen doet de functie van jou het goed. bedankt hiervoor een beetje balen dat ik die niet zelf heb gevonden:( .

17 berichten aan het bekijken - 1 tot 17 (van in totaal 17)

Je moet ingelogd zijn om een reactie op dit onderwerp te kunnen geven.