Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Instr

tesmu [13.01.2006 12:50:49]

#

Joops elikkä tässä kehittelin vb:n instr funktiota vastaavan funktion tai oikeastaan yritän kehitellä no tässä kuitenkin koodi

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

char *substr(char *tmp, int x, int y);
int instr(char *teksti, char *merkki);

int main(void) {
        //oli vaan et nään toimiiko
	printf("Alku\n");
	char joo[1000];
	int y;
	sprintf(joo,"Moicca jee");
        //käytetään instr funktiota
	y = instr(joo,"a");
	printf("%i\n",y);
}


int instr(char *teksti,char *merkki) {
	int t,a;
        //otetaan ylös tekstin pituus
	a = strlen(teksti);
	for(t=0; t>a; t++)
	{
                //verrataan merkkiin
		if (!strcmp(substr(teksti,t,1),merkki)) {
			return t;
                        //jos löytyy niin palautetaan paikka
			break;
		}
		else {
                        //jos ei niin palautetaan 0
			return 0;
		}
	}
}
char *substr(char *tmp, int x, int y){
	char *string = strdup(tmp);
	string[x + y - 1] = '\0';
	return string + x - 1;
}

Mutta tämä funktio palauttaa joka tapauksessa 134516398.
Mistä tämä johtuu?

tesmu [13.01.2006 13:59:36]

#

Korjaus vielä

for(t=1;

Metabolix [13.01.2006 19:04:59]

#

t<a eikä t>a. Ja t=0 on oikeampi, koska voihan se olla alussa asti. return -1 tai muu virhearvo for-loopin jälkeen vielä. Mitään elseä ei myöskään tarvita. Substr ei tee uutta tekstiä, joten et voi nollamerkkiä siihen laittaa. Vertaile tekstejä etsittävän pituuden verran memcmp-funktiolla.

os [13.01.2006 20:02:24]

#

else-lohkon takia funktio palauttaa aina nollan, jos etsittävä merkki ei ole "teksti":n alussa. Myös huolimaton muistinkäsittely substr-funktiossa voi aiheuttaa ongelmia. Jos tosiaan etsii merkkiä, ei merkkijonoja tarvita. Etsinnän voi toteuttaa vaikka näin:

int instr(char *teksti, char merkki) {
  for(int i=0, teksti[i]!='\0'; i++)
   if(teksti[i]==merkki) return i;
  return -1; // ei löydy
}

Tätä funktiota kutsuttaisiin: instr("asdlkdf", 'k'); Voi myös käyttää string.h:n valmista strcspn-funktiota.

Metabolix [13.01.2006 20:31:13]

#

Nyt siis os etsii vain yhtä merkkiä, kuten hänen kertomansa string.h:n funktiokin. Kokonainen tekstinpätkä oli tarkoitus löytää.

Jos kelpaa string.h:ta käyttävä funktio, niin homma menee helposti

int InStr(const char * const teksti, const char * const etsittava)
{
  // Pointteri oikeaan kohtaan
  char * kohta = strstr(teksti, etsittava);

  // Jos löytyi, palautetaan kohdan ja alun osoitinten erotus.
  if (kohta != NULL)
    return (kohta - teksti);

  // Muuten palautetaan -1
  return -1;
}

Jos pitää itse tehdä, niin silloin tehdään kaikki ilman kirjastoja:

int InStr(const char * const teksti, const char * const etsittava)
{
  int i, j, p1, p2;

  // Merkkijonojen pituudet
  for (p1 = 0; teksti[p1] != 0; ++p1);
  for (p2 = 0; etsittava[p2] != 0; ++p2);

  // Jos tekstissä ei olisi enää tilaa etsittävälle, sitä ei voi olla enää
  p1 = p1 - p2 + 1;

  // Joka kohdasta
  for (i = 0; i < p1; ++i)
  {
    // Koko etsittävä jono
    for (j = 0; j < p2; ++j)
    {
      // Onko eri merkki kuin pitäisi?
      if (teksti[i+j] != etsittava[j])
      {
        break; // Ei siis tässä ainakaan
      }
    }
    // Jos päästiin loppuun, palautetaan tämä kohta
    if (j == p2)
      return i;
  }

  // Eipä löytynyt.
  return -1;
}

Alkuperäisen koodisi virheellinen palautusarvo tulee siis siitä, että väärän ehdon takia silmukkaa ei suoriteta kertaakaan ja palautusarvo jää laittamatta. Kääntäjä sanoo kyllä, että joka tavalla ei tule arvoa palautettua. Ja tosiaan tuo else on virheellinen ajatus.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta