Rozdělení pole podle znaku – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Rozdělení pole podle znaku – C / C++ – Fórum – Programujte.comRozdělení pole podle znaku – C / C++ – Fórum – Programujte.com

 

Hanule
~ Anonymní uživatel
37 příspěvků
21. 11. 2012   #1
-
0
-

Ahoj, potřebovala bych poradit, jak mám rozdělit řetězec, bez použití funkce strtok. Pole obsahujeme znak, a když se narazí na něj, má se ta část před ním uložit do pole a tak opakovat, až se dojde na konec pole. Ale nevím, jak to mám udělat bez funkce strtok.

Děkuji za radu

Nahlásit jako SPAM
IP: 93.181.80.–
Chrasty
~ Redaktor
+4
Posthunter
21. 11. 2012   #2
-
0
-

#1 Hanule
Ahoj,

neřekla jsi, co používáš za jazyk. Třeba v C++ je metoda Find, která ti vrátí index (mimo jiné) znaku v zadaném stringu. Když tohle zkombinuješ s while cyklem, tak se dostaneš k řešení.

Pokud ani tohle nevyhovuje, tak existuje ještě polopatičtější řešení - string je pole znaků, kterým můžeš normálně procházet. Můžeš procházet pomocí cyklu znak po znaku a ukládat si je do jiného stringu. Když narazíš na ten určitý znak, při kterém se máš zastavit, tak začneš ukládat do jiné proměnné.

Nahlásit jako SPAM
IP: 109.246.196.–
Hanule
~ Anonymní uživatel
37 příspěvků
21. 11. 2012   #3
-
0
-

Aha...promiň, používám C. Já jsem to tak nějak sesmolila takto:

while (cil[i]!='\0')
{
    if (cil[i]!=delimiter)
    { //když najde delimiter, vypise vse od zacatku az narazi na delimiter
        for (int i=0;cil[i]!=delimiter;i++)
        { //prochazi po znacich a a pak vlozi do p
            char a=cil[i];
            char p[]=a;
        }
            }
}

    return values[i];
}

ale nefunguje to a já si s tím moc nevím rady...myslela jsem to tak, že to právě bude procházet po znacích a až narazí na delimiter, tak ulozí do pole a pak bude pokračovat. ale nevím jak mám udělat to "pokračovat" protože ten cyklus mi zkončí když narazí na delimiter a další už nehledá...

Nahlásit jako SPAM
IP: 93.181.80.–
ingiraxo+15
Grafoman
21. 11. 2012   #4
-
0
-

noo, já bych použil asi linkedList, šlo by to i jako pole slov, ale to si myslim, že by bylo komplikovanější a takto mi to prijde snažší

jinak takto to může vypadat, není to moc težký.. prostě procházíš znak po znaku a jak to narazí na požadovanej, tak vše předtim (mezi hledanýma znakama) přida do linku a vesele  jedeš dál... akorát poslední slovo musíš přidat dodatečně

takto to teda může vypadat: 

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

typedef struct LINK
{
    char* text;
    struct LINK* next;
} Link;

Link* getChar(const char* text, const int length)
{
    Link* chr = (Link*)calloc(1, sizeof(Link));
    chr->text = (char*)calloc(length, sizeof(char));
    strcpy(chr->text, text);
    chr->next = NULL;
    return chr;
}

void addChar(Link** first, Link** last, Link* newChar)
{
    if (!*first) *first = newChar;
    else (*last)->next = newChar;
    *last = newChar;
}

void freeChar(Link* first)
{
    Link* temp = first;

    while (first != NULL)
    {
        temp = first;
        first = first->next;
        free(temp);
    }
}

void printChar(Link* first)
{
    while (first != NULL)
    {
        printf("%s\n", first->text);
        first = first->next;
    }
}

Link* parse(char* text, const int length, const char delim)
{
    int i, count = 0;
    char buffer[128];
    Link* result = NULL;
    Link* last = NULL;

    for (i = 0; i < length; i++)
    {
        if (*(text + i) != delim) *(buffer + count++) = *(text + i);
        else
        {
            *(buffer + count) = '�';
            addChar(&result, &last, getChar(buffer, count));
            count = 0;
        }
    }
    *(buffer + count) = '�';
    addChar(&result, &last, getChar(buffer, count - 1));
    return result;
}

int main()
{
    // retezec, ktery je oddeleny carkama
    char text[] = "one,two,three";
    // prida do linku slova (one->two->three)
    Link* result = parse(text, sizeof(text), ',');

    printChar(result); // vypise pod sebe
    freeChar(result);  // uvolni link

    return EXIT_SUCCESS;
}
Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
vitamin+8
Grafoman
21. 11. 2012   #5
-
0
-

Ja by som to spravyl takto:


int main()
{
	char retazec[] = "one,two,three";

	for(char *begin = retazec, *end = retazec; 1; ++end){
		if(*end == '\0'){
			puts(begin);
			break;
		}
		if(*end == ','){
			*end = '\0';
			puts(begin);
			begin = end +1;
		}
	}
	
	return EXIT_SUCCESS;
}

Kedze sa upravuje povodny retazec, tak si staci odpametat begin (pred puts() ) napr do listu ako napisal ingiraxo alob do niakeho pola (pripadne niecoho ako vektor)

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Hanule
~ Anonymní uživatel
37 příspěvků
22. 11. 2012   #6
-
0
-

#5 vitamin
Děkuju za radu, zkusím to nějak takto...Já se jenom  zeptám. Jsem nováček v C (asi měsíc programuju) a nerozumím v tom kódu těm hvězdičkám? To jsou ukazatelé?

Nahlásit jako SPAM
IP: 93.181.80.–
Hanule
~ Anonymní uživatel
37 příspěvků
22. 11. 2012   #7
-
0
-

#4 ingiraxo
To je moc složitý na mě...:( My jsme brali zatím jen základní funkce, podmínky, cykly....:) Ale děkuju

Nahlásit jako SPAM
IP: 93.181.80.–
KIIV
~ Moderátor
+43
God of flame
22. 11. 2012   #8
-
0
-

#7 Hanule
a to to mate rvat do poli jo? Kdyz znate sotva zaklady?

Kdyz neznas pointery tak pravdepodobne budes mit nejake pole retezcu do, ktereho to mas narvat...

takze budes jen kopirovat znaky a pokud narazis na delimiter, tak misto nej hodis ukonceni retezce '\0' a posunes se do dalsiho stringu na zacatek... a kopirujes dal...

ale pokud mas jen vyrobit strtok, tak ten pracuje primo v predanem retezci... misto delimiteru zapise '\0' a vrati ukazatel na zacatek te casti hned za delimiterem (nebo NULL pokud dosahl konce)

Nahlásit jako SPAM
IP: 62.216.147.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Hanule
~ Anonymní uživatel
37 příspěvků
22. 11. 2012   #9
-
0
-

#8 KIIV
Máme to uložit do jiného pole a potom vrátit počet hodnot.

př. když je řetězec 10;ab;30 a delimiter je ; tak vals[0] bude obsahovat 10, vals[1]  ab, vals[2] 30 a funkce vrátí trojku.

A mám udělat jen strtok - ale nesmím použít tu funkci. Ale podle toho, co jste mi odpověděli to snad půjde...

Nahlásit jako SPAM
IP: 93.181.80.–
KIIV
~ Moderátor
+43
God of flame
22. 11. 2012   #10
-
0
-

jo takhle .. do pole cisel dat jen ty pocty... to je jeste jednodussi...

staci vesmes jedno pocitadlo na pozici v retezci (nebo pointer na aktualni pozici) + pocitadlo podretezce + index do druheho pole (ten se pak bude vracet)

Pak uz jen pri nalezeni zapsat delku podretezce, vynulovat to pocitadlo, pricist jedna k poctu podretezcu a pokracovat dokud nenajdes dalsi delimiter nebo dokud neni konec retezce (znak '\0')

Nahlásit jako SPAM
IP: 62.216.147.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Hanule
~ Anonymní uživatel
37 příspěvků
22. 11. 2012   #11
-
0
-

#10 KIIV
Mno já mám uložit jak pořadí, tak hodnotu řetězce do char values[250][250]. ..:)

Nahlásit jako SPAM
IP: 93.181.80.–
KIIV
~ Moderátor
+43
God of flame
22. 11. 2012   #12
-
0
-

tak to pak kopiruj rovnou za behu...

Nahlásit jako SPAM
IP: 62.216.147.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Hanule
~ Anonymní uživatel
37 příspěvků
23. 11. 2012   #13
-
0
-

Tak jsem se snažila to nějak splácat dohromady, ale moc se mi nedaří...Vytvořila jsem si pozici, na které se bude delimiter nacházet, delku retezce, který se má rozdělit a celkový počet delimiterů v řetězci. A teď mám naplnovat dvourozměrné pole těmi rozdělenými řetězci. Takže jestli jsem to dobe pochopila a "naplánovala", tak budu kopírovat znaky do výstupního Pole, a až narazí ten cyklus na delimiter, tak odřádkuje na další řádek.

A tím by se mi mělo vyplnit pole  a poté mi vrátí hodnotu, kolik "řádků" jsem zaplnila.

Teď mi ovšem nastává problém jak to udělat.

char p;
   for (int i=0;i<delka;i++)
   {
       for(int j=0;i<delka;j++)
       {
          p=cil[i];
          //vkladej znaky do vals
          vals[i][j]=p;
          printf("%c",vals);

          //kdyz bude p=delimiter, odskoc na dalsi radek
          if(cil[i]==delimiter) j++;
       }
   }

toto mi nefunguje...a nevím co s tím...zaprvé ten cyklus nekoncí, i když je delka=8; a pak to vypisuje uplně špatný znak pořád dokola.

Nahlásit jako SPAM
IP: 91.219.242.–
KIIV
~ Moderátor
+43
God of flame
23. 11. 2012   #14
-
0
-

no chce to udelat spravne podminky... napriklad v norenem cyklu kontrolujes i ale pripocitavas k j...

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Hanule
~ Anonymní uživatel
37 příspěvků
23. 11. 2012   #15
-
0
-

#14 KIIV
Aha...toho jsem si nevsimla...Mno ale stejně to nepomohlo.

Nahlásit jako SPAM
IP: 91.219.242.–
KIIV
~ Moderátor
+43
God of flame
23. 11. 2012   #16
-
0
-

mas nekde celej kod... takhle naslepo se to tezko opravuje... kazdopadne pochybuju ze mas mit u obou cyklu srovnavani s delkou... pak kdyz narazis na ten delimiter, je potreba ukoncit retezec pomoci znaku '\0' a tak dale...

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Hanule
~ Anonymní uživatel
37 příspěvků
23. 11. 2012   #17
-
0
-

Tady je kod:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int strChrPos(const char *cil, int c)
{
    char *p;

    p=strchr(cil,(char)c);
    if (p) return p-cil;
    else return -1;
}


int csvParse(const char str[], char delimiter, char vals[250][250])
{
    size_t pozice;
    int pocet;
    int i=0;

    char cil[250];
    //zkopiruje øetìzec aby s ním mohl pracovat
    strcpy(cil,str);

    //celkový poèet delimiterù
    int delka = strlen(cil);
    printf("Delka: %d",delka);
    puts("");

    //kolik delimiteru
    while (i<=delka)
    {
        i++;
        if (cil[i]==delimiter) pocet++;
    }
    printf("Celkem del: %d",pocet);
    puts("");
    char znak=';';
    //pozice prvního delimiteru
    pozice=strChrPos(cil,znak);
    printf("Prvni vyskyt znaku '%c' v retezci \"%s\" je na pozici %d\n\n",znak,cil,pozice);

   //val[0][0]
strcpy(vals,cil);
   char p;
   for (int i=0;i<delka;i++)
   {
       for(int j=0;j<delka;j++)
       {
          p=vals[i][j];
          //vkladej znaky do vals
          vals[i][j]=p;
          printf("%c",vals);

          //kdyz bude p=delimiter, odskoc na dalsi radek
          if(cil[i]==delimiter) {printf("\n");}
       }
   }

   return 0;

}

int main()
{   int i=250; int j=250;
    char values [250][250];
    int count = csvParse("10;ab;30",';',values);
    for (int i=0; i<count; i++)
    {
        printf("%s\n",values[i]);
    }
    return 0;

}

Nahlásit jako SPAM
IP: 91.219.242.–
KIIV
~ Moderátor
+43
God of flame
23. 11. 2012   #18
-
0
-

strcpy(vals,cil); ??? ve vals snad jeste vubec nic neni ne?

ty cykly co tam mas by teoreticky mely rozkopirovat ten vstupni retezec do vsech poli.. zadny podretezce.. proste uplne cely... tj. chtelo by to ten vnitrni cyklus uplne vynechat.. a nechat si jen j ... (a hlavne prohodit indexovani pole.. aby bylo vals[j][i]... taky by to sneslo nacitat data z toho vstupniho retezce.. ne z vals.. tam vesmes nic neni...

a tak dale a tak dale

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Ondra
~ Anonymní uživatel
244 příspěvků
23. 11. 2012   #19
-
0
-

Ahoj, co takhle ?

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

char vals[250][250];

char test[] = "1234;ab;5678;hovno;prdel;kameni";

char * csvstrtok(char *line, char sep)
{
  static char *current;
  char *start;
  int quoted = 0;

  if (line != NULL)
  {
    current = line;
  }

  start = current;

  if (*current == '\0') return NULL;

  while (*current != '\0' && ((*current != sep) || quoted))
  {
    if (*current == '"')
    {
      quoted = !quoted;
    }
    current++;
  }

  if (*current == sep)
  {
    *current = '\0';
    current ++;
  }

  return (start);
}

int main(int argc, char *argv)
{

  char *s;
  int i;

  int cnt = 0;

  s = csvstrtok(test, ';');
  while (s)
  {
    strcpy(vals[cnt++], s);
    s = csvstrtok(NULL, ';');
  }

  for (i=0; i<cnt; i++)
    printf("%d=%s\n", i, vals[i]);

  system("pause");

  return 0;

}

Ondra

Nahlásit jako SPAM
IP: 37.188.225.–
KIIV
~ Moderátor
+43
God of flame
23. 11. 2012   #20
-
0
-

   

//nebo taky takhle:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int csvParse(const char * pos, char delimiter, char vals[250][250]) {
  int count=0, j=0;
  do {
    vals[count][j] = *pos;
    if( *pos == delimiter) {
      vals[count][j] = '\0';
      count++;
      j=0;
    } else {
      ++j;
    }
  } while ( *(pos++) != '\0' );
  return count+1;
}

int main() {
  int i;

  char values[250][250];

  int count = csvParse("10;ab;30",';',values);
  for (i=0; i<count; ++i) {
    printf("%s\n",values[i]);
  }

  return 0;
}
Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Hanule
~ Anonymní uživatel
37 příspěvků
23. 11. 2012   #21
-
0
-

#19 Ondra
Já nemůžu použít funkci strtok...Mám to v zadání úlohy. Prý bysme to měli moc jednoduchý.

Nahlásit jako SPAM
IP: 93.181.80.–
Hanule
~ Anonymní uživatel
37 příspěvků
23. 11. 2012   #22
-
0
-

#20 KIIV
Jj, takhle nějak to má fungovat. Já jsem právě moc nechápala, proč tam mám dvourozměrné pole, tak jsem ho chtěla vyplňovat klasicky znaky jako vícerozměrné.  Jenom se chci ještě zeptat, já to s ukazateli moc neumím. Tu hlavičku funkce csvParse mám zadanou jako int csvParse(const chat str, char delimiter.....) a když jsem to zkoušela tedy přepsat takto, tak nevím, jak mám potom vytvořit ukazatel *pos, který bude ukazovat na první znak řetězce str.

Zkoušela jsem napsat char *pos=str; ale program spadl.

Nahlásit jako SPAM
IP: 93.181.80.–
KIIV
~ Moderátor
+43
God of flame
23. 11. 2012   #23
-
0
-

csvParse(const chat str[], char delimiter.....)

ne  csvParse(const chat str, char delimiter.....)  s timdle druhym to opravdu moc fungovat nebude

Nahlásit jako SPAM
IP: 94.112.32.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Ondra
~ Anonymní uživatel
244 příspěvků
24. 11. 2012   #24
-
0
-

#21 Hanule
Ty někde vidíš že bych použil funkci strtok() ? csvstrtok(), která je tam použita, je její náhrada, je tam její kompletní definice.

O.

Nahlásit jako SPAM
IP: 37.188.225.–
Hanule
~ Anonymní uživatel
37 příspěvků
24. 11. 2012   #25
-
0
-

#23 KIIV
Aha...taková blbá chyba...:)

Nahlásit jako SPAM
IP: 93.181.80.–
Hanule
~ Anonymní uživatel
37 příspěvků
24. 11. 2012   #26
-
0
-

#24 Ondra
Já to jenom tak prolítla, protože to je na mě moc složitý ten tvůj kod. Tak se omlouvam...

Nahlásit jako SPAM
IP: 93.181.80.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 71 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý