Thread: Manipulating data in an array...

  1. #1
    Registered User
    Join Date
    Oct 2006
    Location
    Omaha, Nebraska
    Posts
    116

    Manipulating data in an array...

    I wanted to write a program to scan an array and remove the double characters that it finds. On top of that I wanted to challenge myself by using pointers and i think that might where my problem is. Or my logic. Both are entirely possible.
    Here's what I've got so far:
    Code:
    /****************************************************************/
    /*				doublekiller			*/
    /*		searches through a given word and removes 	*/
    /*		double letters					*/
    /****************************************************************/
    
    #include <stdio.h>
    #include <string.h>
    
    
    #define MAXLEN	400
    
    char isTwo(char *line, int size);
    
    
    int main(void)
    {
    	char array[MAXLEN];
    	char *p;
    	p = &array[0];
    
    	fgets(array, MAXLEN, stdin);
    	
    	isTwo(p, strlen(array)); //this addresses the INITIAL element to the function. so '&array' == '&array[0]' 
    	printf("%s\n", array);
    	
    	return 0;
    
    }
    
    
    
    char isTwo(char *line, int size) //tests the given string for doubles and removes them 
    {
    	int next = (*line) + 1;
    	while(next < size)//this could have been a for loop. i decided to write the entire thing out for my clarity.
    	{
    		if(*line == next)
    		{
    			next = '_';
    			*line = '_';
    			*line++;
    		}
    		else *line++;
    	}
    }
    If you guys would take a look and see what I might be doing wrong I'd really appreciate it.
    Thanks.

  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
    > int next = (*line) + 1;
    So if the first char of the line is 'A', you initialise next to 'B' ?

    > *line++;
    Again, why increment a character in the buffer?

    Shouldn't you be incrementing subscripts?

    Better variable names might help.
    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
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Salem
    Again, why increment a character in the buffer?
    Actually, that increments the pointer, with the dereference having no net effect.
    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

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    the while loop in isTwo() never happens because next is bound to be bigger than size right off the bat. The value of line here will be the ascii value of the first letter, probably in the range 32-127:

    Code:
    int next = (*line) + 1;
    See what you get if you insert this line next:
    Code:
    printf ("isTwo(): %d\n", next);
    Now a question from me: why do you do this:
    Code:
            char array[MAXLEN];
    	char *p;
    	p = &array[0];
    and then pass isTwo() p? It would have been sufficient to just use char array[MAXLEN] and then pass array.

    Anyway, here is a somewhat corrected version of your program that I think does want you want:
    Code:
    /****************************************************************/
    /*				doublekiller			*/
    /*		searches through a given word and removes 	*/
    /*		double letters					*/
    /****************************************************************/
    
    #include <stdio.h>
    #include <string.h>
    
    
    #define MAXLEN	400
    
    void isTwo(char *line, int size);
    
    
    int main(void)
    {
    	char array[MAXLEN];
    
    	fgets(array, MAXLEN, stdin);
    	
    	isTwo(array, strlen(array)); //this addresses the INITIAL element to the function. so '&array' == '&array[0]' 
    	printf("%s\n", array);
    	
    	return 0;
    
    }
    
    
    
    void isTwo(char *line, int size) //tests the given string for doubles and removes them 
    {
    	int next = 0;
    	while(next < size)//this could have been a for loop. i decided to write the entire thing out for my clarity.
    	{
    		if(line[next] == line[next+1]) line[next]='_';
    		next++;
    	}
    }
    Output:
    Code:
    thiis
    th_is
    A version using pointers in isTwo() might be:
    Code:
    void isTwo(char *line, int size) //tests the given string for doubles and removes them 
    {
    	int i=0;
    	char *next=line+1;
    	while(i < size)//this could have been a for loop. i decided to write the entire thing out for my clarity.
    	{
    		if(*line == *next) *line='_';
    		line++; next++;
    		i++;
    	}
    }
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Oct 2006
    Location
    Omaha, Nebraska
    Posts
    116
    The reason I did
    Code:
     char array[MAXLEN];
    	char *p;
    	p = &array[0];
    was because I'm just learning how to use pointers so it was probably some confusion on my part.
    The same reason i wrote the isTwo() function like i did. I know that once you de-reference the pointer you can use it like a "normal" variable but i was getting confused and frustrated and making apparently nonsensical changes to my code. Thanks for everyone's help

    I've made the changes that you've suggested but now I get a segmentation fault.

    Code:
    /****************************************************************/
    /*				doublekiller			*/
    /*		searches through a given word and removes 	*/
    /*		double letters					*/
    /****************************************************************/
    
    #include <stdio.h>
    #include <string.h>
    
    
    #define MAXLEN	400
    
    char isTwo(char *line, int size);
    
    
    int main(void)
    {
    	char array[MAXLEN];
    
    	fgets(array, MAXLEN, stdin);
    	
    	isTwo(&array[MAXLEN], strlen(array)); //this addresses the INITIAL element to the function. so '&array' == '&array[0]' 
    	printf("%s\n", array);
    	
    	return 0;
    
    }
    
    
    
    char isTwo(char *line, int size) //tests the given string for doubles and removes them 
    {
    	int i = 0;
    	int next = i + 1;
    	while(next < size)//this could have been a for loop. i decided to write the entire thing out for my clarity.
    	{
    		if(line[i] == line[next]) 
    		{	
    			line[i]='_';
    			line[next] = '_';
    		}
    		i++;
    	}
    }
    can anyone see what i'm missing?
    Thanks again.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    array[MAXLEN] doesn't exist, so finding its address is a fool's game.

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by tabstop View Post
    array[MAXLEN] doesn't exist, so finding its address is a fool's game.
    Because MAXLEN is the number of elements in array, and they are numbered from 0, the last one will be MAXLEN-1.

    You pass the pointer array to isTwo(), not an element of the array it points to (or the address of a non-existent element, as you did above).

    Code:
    isTwo(array, strlen(array));
    should work.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    Registered User
    Join Date
    Oct 2006
    Location
    Omaha, Nebraska
    Posts
    116
    Again, I made the changes, but I'm still getting
    Code:
    Segmentation fault: 11
    here's exactly what I have:
    Code:
    ****************************************************************/
    /*				doublekiller			*/
    /*		searches through a given word and removes 	*/
    /*		double letters					*/
    /****************************************************************/
    
    #include <stdio.h>
    #include <string.h>
    
    
    #define MAXLEN	400
    
    char isTwo(char *line, int size);
    
    
    int main(void)
    {
    	char array[MAXLEN];
    
    	fgets(array, MAXLEN, stdin);
    	
    	isTwo(array, strlen(array)); //this addresses the INITIAL element to the function. so '&array' == '&array[0]' 
    	printf("%s\n", array);
    	
    	return 0;
    
    }
    
    
    
    char isTwo(char *line, int size) //tests the given string for doubles and removes them 
    {
    	int i = 0;
    	int next = i + 1;
    	while(next < size)//this could have been a for loop. i decided to write the entire thing out for my clarity.
    	{
    		if(line[i] == line[next]) 
    		{	
    			line[i]='_';
    			line[next] = '_';
    		}
    		i++;
    	}
    }
    Can anyone see what I've done wrong?
    Thanks again for everybody's help.
    Last edited by MikeyIckey; 01-03-2009 at 02:49 PM.

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Code:
    char isTwo(char *line, int size) //tests the given string for doubles and removes them 
    {
    	int i = 0;
    	int next = i + 1;
    	while(next < size)//this could have been a for loop. i decided to write the entire thing out for my clarity.
    	{
    		if(line[i] == line[next]) 
    		{	
    			line[i]='_';
    			line[next] = '_';
    		}
    		i++;
    	}
    }
    Thanks again for everybody's help.[/QUOTE]

    You have an endless loop in the isTwo() function. The problem is that you increment i, but never increment "next", so on the second letter, they have the same value, which the if statement then changes the line[next] to be an underscore, and that's the end of any good comparisons. Since next never increments, the loop is never left.

    So increment next, right next to where you increment i.

    Also, you should really remove the newline '\n' from the end of your array[] from fgets().

    This will do that:

    Code:
    array[strlen(array) - 1] = '\0';
    and put an end of string char into that spot.


    Now when I run your program and put in "jeff", I get je__ at the end. Is that what you wanted?
    When I enter "Jeff's hooch is in Hawaii.", I get "Je__'s h__ch is in Hawa__."

    Look OK?
    Last edited by Adak; 01-03-2009 at 03:09 PM.

  10. #10
    Registered User
    Join Date
    Oct 2006
    Location
    Omaha, Nebraska
    Posts
    116
    *phew*
    ok, that was the problem!

    and yes that's exactly what i wanted.
    And i'm sorry to hear about your alcohol being so far away.
    ...
    unless of course you are, in fact, in hawaii.
    in which case; drink up!

    Now, my next question is why didn't the variable i in isTwo( ) control the variable next?
    when
    Code:
    int i = 0;
    int next = i + 1;
    shouldn't 'next' always be one more then 'i' with the assignments that i've made?
    Last edited by MikeyIckey; 01-03-2009 at 03:15 PM.

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Because you set next up properly ONCE, *outside* the loop.

    For the first letter, it's fine, after that "i" increments, and next never does - because it's being set up only once, outside the while loop.
    Last edited by Adak; 01-03-2009 at 03:21 PM.

  12. #12
    Registered User
    Join Date
    Oct 2006
    Location
    Omaha, Nebraska
    Posts
    116
    Quote Originally Posted by Adak View Post
    Because you set next up properly ONCE, *outside* the loop.

    For the first letter, it's fine, after that "i" increments, and next never does - because it's being set up only once, outside the while loop.
    OOOH, the variable is never reinitialized to be 'i + 1'.
    Ok, that makes sense, thank you!

    And big thank you's again for everyone's help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. can any1 plz make this assignment
    By jean in forum C Programming
    Replies: 17
    Last Post: 05-13-2009, 09:19 PM
  2. Replies: 48
    Last Post: 09-26-2008, 03:45 AM
  3. Dynamic Array substitution in composite data variable
    By DavidDobson in forum C Programming
    Replies: 2
    Last Post: 08-12-2008, 04:29 AM
  4. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  5. Template Array Class
    By hpy_gilmore8 in forum C++ Programming
    Replies: 15
    Last Post: 04-11-2004, 11:15 PM