C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 11-22-2009, 05:46 AM   #1
Registered User
 
Join Date: Nov 2009
Posts: 7
Question Now it works, now it won't

Hello. I'm trying to learn C using K&R. I've had some background with Scheme and Java programming so I'm guessing that K&R is the path to take to learning C.

Earlier in the text, I wrote the following program, which allows the user to input a series of lines until EOF is invoked. Then, the program will print out the longest line entered by the user. Here's the code:

Code:
#include <stdio.h>
#define MAXLINE 1000

int getline(char to[], int max){
	int count = 0;
	int c;
	
	while((c = getchar()) != '\n'){
		to[count] = c;
		count++;
	}
	
	return count;
}

void copy(char to[], char from[]){
	int i = 0;
	
	while((to[i] = from[i]) != '\0'){
		i++;
	}
}

main(){
	char text[MAXLINE][MAXLINE];
	char longestline[MAXLINE];
	int i = 0;
	int largest = 0;
	int linelength = 0;
	
	linelength = getline(text[i], MAXLINE);
	while(text[i][0] != EOF){
		if(linelength > largest){
			largest = linelength;
			copy(longestline, text[i]);
			printf("%s%c", longestline, '\n'); //this part works (HEY)
		}
		
		linelength = getline(text[i], MAXLINE);
	}
	
	printf("%s", longestline);
}
Note that the line shouting HEY was just added to aid in debugging.

The way I understand how my program works, it seems that, called from main with the (main local?) variable longestline as an argument, the function copy copies the contents of [i]text into longestline such that, I can access its new value from main. (See the printf line shouting HEY right after the call to copy).

So far so good.

Then, I wrote a program which removes the "0x" part in hexadecimal numbers. Here is my code:

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

void removeOX(char hex[]){
	int i = 0;
	int limit = strlen(hex);
	
	while(i < limit){
		if(hex[i] == 'x'){
			int j = 0;
			int foo = i + 1;
			char Xremoved[limit - i];
			//printf("%s", "caught here");
			while(j < (limit - i)){
				Xremoved[j] = hex[foo];
				j++;
				foo++;
			}
			
			Xremoved[limit - i] = '\0';
			printf("%s%s%s", "from removeOX: ", Xremoved, "\n");
			hex = Xremoved;
			printf("%s%s%s", "from removeOX hex: ", hex, "\n");
			break;
		}
		else{
			i++;
		}
	}
}

int main(){
	char love[] = "0x8f";
	
	removeOX(love);
	printf("%s", love); //This bit doesn't work now!
}
Again, printf lines were added to aid in debugging.

The way I understand it, my use of functions are simillar here, i.e. they follow the following pattern:

1) Declare a variable in main.
2) Invoke a function, pass the variable declared in 1 to that function.
3) Function modifies its argument(s). Since I passed a declared variable, this declared variable also changes, as the function operates on its arguments.
4) modified argument == modified variable. I may now use the variable with its value modified.

I wonder what am I getting wrong here. Any help would be greatly appreciated. Much thanks.

(Note: I just started learning pointers and I tried to write the "0x" remover with pointers. No luck so far. However, my main concern for now is on my understanding of functions. How come the first one works and the "0x" remover won't?

In any case, should it seem appropriate, feel free to include pointers in your discussion .

Much thanks )
skytreader is offline   Reply With Quote
Old 11-22-2009, 12:57 PM   #2
Registered User
 
Join Date: Oct 2008
Location: TX
Posts: 1,368
Note that an array name is not a variable so it cannot be assigned to ie it's not an lvalue.
So all the processing done in removeOX() is lost after it returns because love still points to the original string.
Your best bet is to return a pointer instead of void from removeOX() to the hex string minus the leading "0x".
itCbitC is offline   Reply With Quote
Old 11-22-2009, 12:58 PM   #3
cas
Registered User
 
Join Date: Sep 2007
Posts: 420
Your observations on the K&R code are correct. However, it's a bit more subtle than it appears, which is why your code is not working as you expect.

The first thing to know is that C is a pass by value language. When you pass an object into a function, only a copy is passed. When you modify that object in the function, it is not changed in the caller:
Code:
#include <stdio.h>
static void f(int i)
{
  i = 10;
}
int main(void)
{
  int i = 5;
  f(i);
  printf("%d\n", i); /* i is still 5 */
  return 0;
}
So why does K&R's copy() function work? Because of one of the dark secrets of C: you can't actually pass an array to a function. When you pass an array, C goes behind your back and passes a pointer to the beginning of the array. It is through the magic of pointers that you can simulate pass by reference in C, and thus change the original value. But you can't just use the = operator to assign a new value to the pointer! This is, perhaps, the confusing part: the pointer is still passed by value. That is, the function gets a copy of the pointer. So when you do:
Code:
static void f(char foo[]) /* foo is actually a pointer here, despite the [] syntax */
{
  foo = new_value;
}
The pointer "foo" now points to "new_value", but only in this function. The original array is not modified at all! Instead you have to modify what the pointer points to. This is accomplished (among other ways) with the [] operator:
Code:
static void f(char foo[])
{
  foo[0] = 'x';
}
Now the first character of the array you pass in is changed to an 'x'. foo points to the original data, and so you can indirectly go there by dereferencing the pointer (which is what the [] operator does). You have a copy of the pointer, but it still points to the original data! So in your function, when you do hex = Xremoved you're just pointing your local variable "hex" to "Xremoved", and after the function exits, nothing has changed. You can use strcpy() to copy Xremoved into hex, and that will persist after the function returns.

But before you do that, you'll have to look at your code that copies into Xremoved. Xremoved is an array of (limit - i) size. That means the last element of the array must be (limit - i - 1). To make this clear, say you have an array of size 3: this only has elements 0, 1, and 2. Your code is writing one byte beyond the end of the array.

Despite the fact that pointers and arrays get jumbled up like this, it's important to remember that they are distinct. You can, most of the time, treat an array like a pointer but it is not a pointer, and there are a few times where this distinction matters.
cas is offline   Reply With Quote
Old 11-23-2009, 09:56 AM   #4
Registered User
 
Join Date: Nov 2009
Posts: 7
cas you got it all...much thanks. I'll have more light now in tackling this problem. Will try it out again as soon as I get some sleep...Again, thanks (--,)
skytreader is offline   Reply With Quote
Reply

Tags
functions, pointers

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
COM port CreateFile -> Close Handle Works great, unless the USB device is unplugged, morty346 Windows Programming 1 08-04-2009 08:57 AM
Can anybody show me why this works?? tzuch C Programming 2 03-29-2008 09:03 AM
fprintf works in one function but not in the other. smegly C Programming 11 05-25-2004 03:30 PM
Programs works one way, not another. VC++ 6.0 help. ethic Windows Programming 4 12-10-2002 10:29 PM
it never works... Ryce Game Programming 5 08-30-2001 07:31 PM


All times are GMT -6. The time now is 09:07 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22