Gå til innhold

C: hvordan lage en split() funksjon?


Anbefalte innlegg

Hei, jeg driver og sliter litt med C som jeg nettopp har begynt å lære på studiet.

 

Problemet mitt, er at jeg trenger en split\trim funksjon som tar en string, deler den opp ved hvert ' '(space) til en array og returnerer arrayen.

 

Såvidt jeg har googlet så kan man ikke returnere arrays i C. Jeg har hittil funnet en løsning, men den fungerer ikke som den skal. (segmentation error).

 

Forsovet vet jeg hva problemet er, men ikke hvordan det kan fikses, eller om det finnes en penere måte å løse dette på.

 

Siden det er en viktig innlevering ønsker jeg ikke legge ut koden min her, men den delen som virker(alt virker fint inne i funksjonen) gjør at jeg har følgende resultat:

 

input: "Dette er en test";

output: res[0] = Dette\0; res[1] = er\0; res[2] = en\0; res[3] = test\0; res[4] = NULL;

 

Inne i funksjonen prøver jeg å skrive ut arrayen, og stopper løkken når den finner NULL. Dette funker fint.

Når jeg gjør det samme etter å ha returnert arrayen, så stopper den ikke det NULL skal være, og jeg får noen rare utskrifter etterfulgt av segmentation error.

 

Er det noen som har en bra pseudekode for en split\trim funksjon eller som har en alternativ løsning på problemet?

 

På forhånd takk! :)

Lenke til kommentar
Videoannonse
Annonse

Du kan ikke returnere en array, men du kan vel returne en pointer til et array?

 

Hvordan kan jeg gjøre dette og likevel få en 'array-lignende' struktur på resultatet?

 

Jeg ønsker å kunne traversere resultatet akkurat slik som man kan i java.

 

må jeg ha en:

 

char *split(char *str)?

 

og hvordan kan jeg da hente den samme strukturen?

 

char *arr?

eller

char arr[100]?

 

Enn sålenge har jeg løst problemet, men bruker ikke en funksjon, dermed blir main-funksjonen min ganske lang og rotete :(

Lenke til kommentar

I C blir du mest sannsynlig nødt til å returnere en liste av pekere, altså, peker til peker.

 

Funksjonen strtok() (i <string.h>) splitter opp strenger. strtok() endrer data på strengen den jobber på, så den er litt uvandt fra Java, men svært kjapp og effektiv. Den er ikke re-entrant (problem hvis du multithreader typisk, men det finnes strtok_r for dette ...) Hvis du er villig til å ødelegge strengen du skal splitte, så er løsningen ganske grei.

 

Utestet kode:

#define MAX_ELEMS 32
unsigned index = 0;
const char *split_list[MAX_ELEMS]; // Hardkoda maks. Normalt bør denne være dynamisk allokert.
char some_string[] = "I want to split this string!";

const char *tok = strtok(split_list, " ");
while (tok)
{
  split_list[index++] = tok;
  tok = strtok(NULL, " ");
}

// Split_list inneholder pekere som peker inni i some_string et eller annet sted.

for (unsigned i = 0; i < index; i++)
{
  printf("String #%u: %s\n", i, split_list[i]);
}

 

Så, det er ikke helt trivielt å lage en split funksjon, siden du må tenke på hvordan minnet allokeres, og hvem som har til ansvar å rydde det opp etter deg.

  • Liker 1
Lenke til kommentar

I C blir du mest sannsynlig nødt til å returnere en liste av pekere, altså, peker til peker.

 

Funksjonen strtok() (i <string.h>) splitter opp strenger. strtok() endrer data på strengen den jobber på, så den er litt uvandt fra Java, men svært kjapp og effektiv. Den er ikke re-entrant (problem hvis du multithreader typisk, men det finnes strtok_r for dette ...) Hvis du er villig til å ødelegge strengen du skal splitte, så er løsningen ganske grei.

 

Utestet kode:

#define MAX_ELEMS 32
unsigned index = 0;
const char *split_list[MAX_ELEMS]; // Hardkoda maks. Normalt bør denne være dynamisk allokert.
char some_string[] = "I want to split this string!";

const char *tok = strtok(split_list, " ");
while (tok)
{
  split_list[index++] = tok;
  tok = strtok(NULL, " ");
}

// Split_list inneholder pekere som peker inni i some_string et eller annet sted.

for (unsigned i = 0; i < index; i++)
{
  printf("String #%u: %s\n", i, split_list[i]);
}

 

Så, det er ikke helt trivielt å lage en split funksjon, siden du må tenke på hvordan minnet allokeres, og hvem som har til ansvar å rydde det opp etter deg.

 

Dette ser veldig bra ut!

I oppgaven så er det gitt et max antall elementer, så det er greit.

const char er det det samme som en final i java?

Det ser uansett ut som om du traff spikeren på hodet!

Skal gå igjennom koden litt grundigere senere i kveld å prøve å implementere inn i programmet :)

 

Tusen takk for hjelpen!:)

Lenke til kommentar
  • 1 måned senere...

const char * betyr en peker til const char, som nok blir noe ala final i Java ja. Det betyr at du kan ikke endre på innholdet via pekeren, men du kan lese i hvertfall, som er det vi trenger.

 

For å være presis betyr final at pekeren ikke kan endres til å peke på noe annet. Tilsvarende i C er char * const, altså konstant peker til character(s).

 

...men det er litt off-topic. Unnskyld.

Lenke til kommentar

siden tråden allerede ble dratt opp (og fordi jeg ikke så den var gammmel allerede), så har jeg laget en dynamisk løsning som bruker liket-liste.

Regner ikke med TS har bruk for den lenger, men når jeg først har skrevet koden så kan jeg vel like gjerne poste den ^^

 

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

typedef struct node_t
{
   struct node_t *next;
   char *item;
} node;

typedef struct list_t
{
   node *head;
   node *cur;
} list;

list *new_list()
{
   list *l = malloc(sizeof(list));
   l->head = NULL;
   l->cur = NULL;
   return l;
}

char *pop(list *l)
{
   if(l->head == NULL)
       return NULL;
   node *n = l->head;
   l->head = l->head->next;
   char *i = n->item;
   free(n);
   return i;
}

void release_list(list *l)
{
   char *i;
   while(1)
   {
       i = pop(l);
       if(i==NULL)
           break;
   }
   free(l);
   l = NULL;
}

void push(list *l, char *item)
{
   node *n = malloc(sizeof(node));
   n->next = l->head;
   n->item = item;
   l->head = n;
}

char *getNext(list *l)
{
   if(l->cur==NULL)
       return NULL;
   char *c = l->cur->item;
   l->cur = l->cur->next;
   return c;
}

void rewind_list(list *l)
{
   l->cur = l->head;
}

char *get_word(char *s, int offset, char split)
{
   int size=0, x;
   while(s[size++] != split);
   char *new = malloc(size);
}

list *string_split(char *s, char split)
{
   list *l = new_list();
   int size=0, offset=0, splitting=1, x;

   while(splitting)
   {
       offset += size;
       size = 0;
       while(s[offset+size] != split)
       {
           size++;
           if(s[offset+size] == '\0')
               splitting = 0;
       }
       char *new = malloc(size);
       for(x=0; x<size; x++)
           new[x] = s[offset+x];
       new[x] = '\0';
       push(l, new);
       size++;
   }
   rewind_list(l);
   return l;
}

int main()
{
   char *string = "This is a string for splitting!";

   list *l = string_split(string, ' ');    

   while(1)
   {
       char *d = getNext(l);
       if(d == NULL)
           break;
       printf("msg: %s\n", d);
   }

   release_list(l);
}

  • Liker 1
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...