Thread: value gets lost in passing to a function

  1. #1
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305

    value gets lost in passing to a function

    I am trying to write a program for infix to prefix conversion. I have the code fragment shown below and while i was trying to debug it a strange thing seems to happen. I am calling a function convert with the source string and passing it to the argument in convert (which is a char *). As soon as i come into the function on debugging i figured out that the argument has the value which i am passing into it. But as soon as i enter the first line of the function the value of the expression seems to get lost and gets corrupted by some garbage arguments.

    [insert]
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX 100
    
    char * xstrrev(char *s);
    void initstack(struct infix *s);
    void push(struct infix *s, char data);
    char  pop(struct infix *s);
    void convert(char *s, char *target, int len);
    
    struct infix
    {
    	char arr[MAX]; // stack to hold elements
    	int top;  // store target string
    };
    
    struct infix in;
    
    int main(void)
    {
    	char arr[MAX];
    	char *t, *source;
    	int count, i;
    
    	fputs("\nPlease enter an arith exp in infix form\n", stdout);
    	fflush(stdout);
    	if(fgets(arr, sizeof arr, stdin) != NULL)
    	{
    		char *newline = strchr(arr, '\n');
    
    		if(newline != NULL)
    		{
    			*newline = '\0';
    		}
    	}
    	
    	// initialize the stack infix
    	initstack(&in);
    
    	count = strlen(arr);
    
    	t = arr;
    	printf("\n%s", t);
    	// make t point to the last char 
    	for(i = 0;i<count;i++)
    		t++;
    
    	// Reverse the string 
    	source = xstrrev(arr);
    	convert(source, t, count);
    
    	printf("\nPrefix exp %s", t);
    	return 0;
    }
    
    void convert(char *s, char *target, int len)
    {
    	int i;
    	char a, b;
    	char ........;
    	int pria, prib;
    
    	ss = s;
    	for(i = 0;i< len;i++)
    	{
    		a = ........;
    		if(a == ' ')
    		{
    			break;
    		}
    
    		// check if a is digit or alphabet
    		else if((a >= '48' && a<= '57') || (a >= '65' && a<= '90') || (a >= '97' && a<= '121'))
    		{
    			*target = a;
    			--target;
    			break;
    		}
    		else if(a == ')')
    		{
    			push(&in, a);
    			break;
    		}
    		else if(a == '(')
    		{
    			b = pop(&in);
    			while(b != ')')
    			{
    				*target = b;
    				-- target;
    				++ss;
    				b = pop(&in);
    			}
    			break;
    		}
    		else if(a == '$'||a == '/'||a == '*'||a == '+'||a == '-')
    		{
    			b = pop(&in);
    			pria = getpriority(a);
    			prib = getpriority(b);
    			if(prib < pria)
    				push(&in, a);
    			else
    			{
    				while(prib > pria)
    				{
    					*target = b;
    					--target;
    					++ss;
    					b = pop(&in);
    					pria = getpriority(a);
    					prib = getpriority(b);
    				}
    				push(&in, b);
    				push (&in,a);
    			}
    			break;
    		}
    		++ss;
    	}	
    }
    
    int getpriority(char a)
    {
    	int pri;
    
    	switch (a)
    	{
    		case '$':
    			pri = 3;
    			break;
    		case '*':
    			pri = 2;
    			break;
    		case '/':
    			pri = 2;
    			break;
    		case '+':
    			pri = 1;
    			break;
    		case '-':
    			pri = 1;
    			break;
    		default:
    			pri = 0;
    			break;
    	}
    	return pri;
    }
    
    void initstack(struct infix *s)
    {
    	s->top = -1;
    }
    
    
    void push(struct infix *s, char data)
    {
    	// check if stack is full
    	if(s->top == MAX -1)
    	{
    		printf("\nStack is full");
    	}
    	// adding the element for the first time
    	else if(s->top == -1)
    	{
    		s->top++;
    		s->arr[s->top] = data;
    	}
    	else
    	{
    		if(s->top < MAX -1)
    		{
    		s->top++;
    		s->arr[s->top] = data;
    		}
    	}
    }
    
    char pop(struct infix *s)
    {
    
    	char item;
    	// check if elements are there
    	if(s->top == -1)
    	{
    		printf("No more elements");
    		return 0;
    	}
    
    	else
    	{
    		item = s->arr[s->top];
    		s->top--;
    		return item;
    	}
    }
    
    char * xstrrev(char *s)
    {
    	char arr[MAX];
    	int len, i;
    
    	len = strlen(s);
    
    	while(*s != '\0')
    		++s;
    
    	s--;
    
    	for(i  = 0;i< len; i++)
    	{
    			arr[i] = *s;
    			s--;
    	}
    	
    	arr[i++] = '\0';
    	printf("\n%s", arr);
    	return arr;
    }
    The program compiles but it does not give the correct result. I am still debugging it.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > return arr;
    You're returning a pointer to a local variable.
    This is a strict no-no.

    Either reverse the string "in place", or pass another pointer to where you want the reversed answer placed.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    Oh yes the same mistake i did yesterday of passing the local pointer. Foolish me :-)

  4. #4
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    To do a workaround to the problem of passing a local pointer i simply declare it as a global variable outside main.

    Is this a good and healthy practice in c or i should avoid this sort of workaround?

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by roaan
    Is this a good and healthy practice in c or i should avoid this sort of workaround?
    You should avoid this sort of workaround. In general, avoid the use of global variables.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    Hi ,

    Now i am fully lost in this application. I am debugging it for quite some time now.

    The expression i am entering is
    4$2*3-3+8/4/(1+1)

    and the result shoudl be
    +-*$4233//84+11

    and what is happening is that it works fine ( i am able to get the output till 33//84+11) but after that something is going crazy of which i have no idea (or may be after so much time my mind has gone crazy)

    The code for this is

    [insert]
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX 100
    
    char * xstrrev(char *s);
    void initstack(struct infix *s);
    void push(struct infix *s, char data);
    char  pop(struct infix *s);
    void convert(char *s, char *target, int len);
    
    struct infix
    {
    	char arr[MAX]; // stack to hold elements
    	int top;  // store target string
    };
    
    struct infix in;
    char arrrev[MAX];
    
    int main(void)
    {
    	char arr[MAX];
    	char *t, *source;
    	int count, i;
    
    	fputs("\nPlease enter an arith exp in infix form\n", stdout);
    	fflush(stdout);
    	if(fgets(arr, sizeof arr, stdin) != NULL)
    	{
    		char *newline = strchr(arr, '\n');
    
    		if(newline != NULL)
    		{
    			*newline = '\0';
    		}
    	}
    	
    	// initialize the stack infix
    	initstack(&in);
    
    	count = strlen(arr);
    
    	t = arr;
    	printf("\n%s", t);
    	// make t point to the last char 
    	for(i = 0;i<count;i++)
    		t++;
    
    	// Reverse the string 
    	source = xstrrev(arr);
    	convert(source, t, count);
    
    	printf("\nPrefix exp %s", t);
    	return 0;
    }
    
    void convert(char *s, char *target, int len)
    {
    	int i;
    	char a, b;
    	char ........;
    	int pria, prib;
    
    	ss = s;
    	for(i = 0;i< len;i++)
    	{
    		a = ........;
    		if(a == ' ')
    		{
    			// do nothing
    		}
    
    		// check if a is digit or alphabet
    		else if((a >= '0' && a<= '9') || (a >= '65' && a<= '90') || (a >= '97' && a<= '121'))
    		{
    			*target = a;
    			--target;
    		}
    		else if(a == ')')
    		{
    			push(&in, a);
    		}
    		else if(a == '(')
    		{
    			b = pop(&in);
    			while(b != ')')
    			{
    				*target = b;
    				-- target;
    				b = pop(&in);
    			}
    		}
    		else if(a == '$'||a == '/'||a == '*'||a == '+'||a == '-')
    		{
    			b = pop(&in);
    			// check if stack is empty
    			if(b == -1)
    				push(&in, a);
    			else
    			{
    				pria = getpriority(a);
    				prib = getpriority(b);
    
    				if(prib < pria)
    				{
    					push(&in, b); 
    					push(&in, a);
    				}
    				else
    				{
    					while(prib > pria)
    					{
    						*target = b;
    						--target;
    						++ss;
    						b = pop(&in);
    						pria = getpriority(a);
    						prib = getpriority(b);
    					}
    					if(b == -1)
    						push (&in,a);
    					else
    					{
    						push(&in, b);
    						push (&in,a);
    					}
    				}
    			}
    		}
    		++ss;
    	}	
    }
    
    int getpriority(char a)
    {
    	int pri;
    
    	switch (a)
    	{
    		case '$':
    			pri = 3;
    			break;
    		case '*':
    			pri = 2;
    			break;
    		case '/':
    			pri = 2;
    			break;
    		case '+':
    			pri = 1;
    			break;
    		case '-':
    			pri = 1;
    			break;
    		default:
    			pri = 0;
    			break;
    	}
    	return pri;
    }
    
    void initstack(struct infix *s)
    {
    	s->top = -1;
    }
    
    
    void push(struct infix *s, char data)
    {
    	// check if stack is full
    	if(s->top == MAX -1)
    	{
    		printf("\nStack is full");
    	}
    	// adding the element for the first time
    	else if(s->top == -1)
    	{
    		s->top++;
    		s->arr[s->top] = data;
    	}
    	else
    	{
    		if(s->top < MAX -1)
    		{
    		s->top++;
    		s->arr[s->top] = data;
    		}
    	}
    }
    
    char pop(struct infix *s)
    {
    
    	char item;
    	// check if elements are there
    	if(s->top == -1)
    	{
    		printf("No more elements");
    		return -1;
    	}
    
    	else
    	{
    		item = s->arr[s->top];
    		s->top--;
    		return item;
    	}
    }
    
    char * xstrrev(char *s)
    {
    	int len, i;
    
    	len = strlen(s);
    
    	while(*s != '\0')
    		++s;
    
    	s--;
    
    	for(i  = 0;i< len; i++)
    	{
    			arrrev[i] = *s;
    			s--;
    	}
    	
    	arrrev[i++] = '\0';
    	printf("\n%s", arrrev);
    	return arrrev;
    }

  7. #7
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    Oh the two dots .......... are the following lines (char ........, and a = ........)

    [insert]
    Code:
    char ........;
    a = ........;
    I dont know why it appears at dot when i insert in within code tags.

  8. #8
    Banned ಠ_ಠ's Avatar
    Join Date
    Mar 2009
    Posts
    687
    probably because you wrote something naughty
    ╔╗╔══╦╗
    ║║║╔╗║║
    ║╚╣╚╝║╚╗
    ╚═╩══╩═╝

  9. #9
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    @ above

    Thanks for the compliment

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Just a heads up: instead of
    for(i = 0;i<count;i++) t++;
    ...you can simply do:
    t += count;
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    Finally it works :-)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-13-2011, 08:28 AM
  2. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  3. Passing A Function Into A Constructor
    By fourplay in forum C++ Programming
    Replies: 6
    Last Post: 03-15-2009, 06:06 AM
  4. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  5. Passing a byte and its bits to a function
    By rtarbell in forum C Programming
    Replies: 9
    Last Post: 12-04-2008, 09:24 AM