Jump to content

char *pointeri, masīvi un printf, rekursīvā funkcijā


Satan
 Share

Recommended Posts

Vingrinājuma programma, kurā rekursīva funkcija stringā nomaina visus "pi" uz "3.14"
ar komentāriem kodā atzīmētas jautājumu vietas:
1. Kā ir labāk , iekopēt temp stringā vienu char un atgriezt temp, vai atgriezt pointeri uz pirmo elementu, vai vēl kāds labāks risinājums kad funkcijai ir jāatgriež viens char?
2. un 3. Kāpēc nestrādā temp atgriešana ( neizprintējas pēdējais "3.14", kad printē st2), bet sāk strādāt kad pašā funkcijā pirms temp atgriešanas tiek izsaukts printf  temp?
4. Kāpēc neizvadās pareizi stringi ja visus mēģina izvadīt uz reiz bet izvadās pareizi, ja katru izvada atsevišķi?
 

// uzdevums no http://codingbat.com/java/Recursion-1

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

char *changePi(char *string)
{
	char temp[256] = "";

	if(strlen(string) == 0)
		return "\0";

	 if(strlen(string) == 1)
	 {
		 //1. kaa ir labaak

		 //strncpy(temp, string, 1);
		 //return temp;
		 return &string[0];
	 }

	if(strlen(string) == 2)
	{
		if(string[0] == 'p' && string[1] == 'i')
		{
			/* 2 .kaapeec nestraadaa?
			strcpy(temp,"3.14");

			//kaapeec saak straadaat kad pieliek sho?
			//printf("temp is %s\n", temp);

			return temp;
			*/

			/* 3 kaapeec nestraadaa?
			temp[0] = '3';
			temp[1] = '.';
			temp[2] = '1';
			temp[3] = '4';
			temp[4] = '\0';

			//kaapeec saak straadaat kad pieliek sho?
			//printf("temp is %s\n", temp);

			return temp;
			*/

			//ar sho straadaa
			return "3.14";
		}
		else
			return strncpy(temp, string, 2);
	}
	else
	{
		if(string[0] == 'p' && string[1] == 'i')
		{
			strcpy(temp,"3.14");
			return strcat(temp, changePi(string +2));
		}
		else
		{
			strncpy(temp, string, 1);
			return strcat(temp, changePi(string +1));
		}
	}
}

int main (void)
{
	char st1[] = "a", st2[] = "pi what is pi", st3[] = "";

	/* 4 kaapeec nestraadaa 
	printf("original string - modified string\n%s - %s\n%s - %s\n%s - %s\n",
			st1, changePi(st1),st2, changePi(st2), st3, changePi(st3));
	*/

	printf("original string - modified string\n%s - %s\n", st1, changePi(st1));
	printf("%s - %s\n", st2, changePi(st2));
	printf("%s - %s\n", st3, changePi(st3));

	getchar();

	return 0;
}
Link to comment
Share on other sites

char *changePi(char *string){

    char temp[256] = ""; //šie dati funkcijas beigās "pazūd".

    return strcat(temp, changePi(string +1)); //šeit funkcija atgriež pointeri uz datiem, kas funkcijas beigās "pazūd"

}

Viens risinājums ir izdalīt atmiņu dinamiski:

char *temp = (char *) malloc(sizeof(char) * 256);

 

Šeit aprakstīts tavs gadījums un sniegts viens risinājums kā darīt.

http://stackoverflow.com/questions/14416759/return-char-string-from-a-function

Labots - Salmo
Link to comment
Share on other sites

ja kodē iekš C, tad ir jāizprot, kuri mainīgie tiek izvietoti stekā  (kas "iet bojā" pēc f-jas return)   

Link to comment
Share on other sites

Paldies par palīdzību, sapratu kļūdu, palasīju par stack un heap un uzrakstīju šo funkciju šādi:

 

Vai pareizi saprotu, ka būs vairākas reizes izveidoti neatkarīgi pointeri *out, katrs savā rekursīvajā izsaukšanas reizē savādāks, un aizņemtais atmiņas daudzums būs visu *out summa, kura tiks atbrīvota tikai tad, kad aiztaisīs programmu. Vai tomēr ir iespēja to atbrīvot bez programmas aizvēršanas, ja nu gadījumā būtu nepieciešams?

#define MAX_STRING_SIZE 256

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

char *changePi(char *string)
{
	char temp[MAX_STRING_SIZE], *out;

	int stringSize;

	out = ( char *) malloc ( 5 * sizeof (char) );

	out[0] = '\0';
	out[1] = '\0';

	if(strlen(string) == 0)
		return out;

	 if(strlen(string) == 1)
	 {
		 out[0] = string[0];
		 return out;
	 }

	if(strlen(string) == 2)
	{
		if(string[0] == 'p' && string[1] == 'i')
			return strcpy(out, "3.14");
		else
			return strncpy(out, string, 2);
	}
	else
	{
		if(string[0] == 'p' && string[1] == 'i')
		{
			strcpy(out,"3.14");
			strcpy(temp, changePi(string +2));
			stringSize = (strlen(temp) + 5) * sizeof (char);
			out = ( char *) realloc (out, stringSize);
			return strcat(out, temp);
		}
		else
		{
			strncpy(out, string, 1);
			strcpy(temp, changePi(string +1));
			stringSize = (strlen(temp) + 2) * sizeof (char);
			out = ( char *) realloc (out, stringSize);
			return strcat(out, temp);
		}
	}
}

int main (void)
{
	char st1[] = "", st2[] = "a", st3[] = "pi what is pi";

	printf("original string - modified string\n%s - %s\n%s - %s\n%s - %s\n",
			st1, changePi(st1),st2, changePi(st2), st3, changePi(st3));
	
	getchar();

	return 0;
}
Link to comment
Share on other sites

Vai strtok() spēj kā vienu delimiteru pieņemt "pi" ? Pēc maniem eksperimentiem iznāk ka viņš ņem divus atsevišķus delimiterus 'p' un 'i', ja ievada "pi" ka delimitera parametru.

Link to comment
Share on other sites

nevertell

Nē, bet tu iebaro strtok lielo stringu un tokenu, un pēc tam velc ārā pa vārdam. Tas, ko tev vajag, ir kā tokenu lietot tukšumu, jebšu ' '. Un tad rekursīvā funkcija velk no strtok() ārā kamēr kautkas nāk ārā un konkrētos stringus no sākuma salīdzini pēc garuma strlen. Ja garums atbilst tad varēsi salīdzināt pa burtam. Protamistiski, ir arī strcmp(). 

Link to comment
Share on other sites

Izveido kontu, vai pieraksties esošajā, lai komentētu

Jums ir jābūt šī foruma biedram, lai varētu komentēt tēmas

Izveidot jaunu kontu

Piereģistrējies un izveido jaunu kontu, tas būs viegli!

Reģistrēt jaunu kontu

Pierakstīties

Jums jau ir konts? Pierakstieties tajā šeit!

Pierakstīties tagad!
 Share

×
×
  • Izveidot jaunu...