Thread: Segmentation fault issue

  1. #1
    Registered User
    Join Date
    Sep 2009
    Posts
    11

    Segmentation fault issue

    Hi

    I'm currently learning C and I have ran into an issue I cant figure out.

    I am trying to copy one char from a char array into another, and I am getting a segmentation fault.

    The code currently looks like this:

    Code:
    int i;
    
    for(i = 0; i < 10; i++){
         if(vowel(name[i])){
            vowels[vowelcounter] = name[i];
            vowelcounter++;
         }
    }
    I have also tried the strcpy function to no avail(I am getting a compiler error), as well as the strcat function(Segmentation fault).

    If you guys could help me solve this issue(which probably has a very simple solution) or point me in the right direction that would be very appreciated
    Last edited by Stenland; 09-19-2009 at 01:01 AM.

  2. #2
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    depends on how you declared the array 'vowels', 'name' and the initial value of 'vowelcounter'.
    Have you allocated enough space for the arrays?

  3. #3
    Registered User
    Join Date
    Sep 2009
    Posts
    11
    I have allocated enough space, both arrays are size 10(im only using very short test names, in my example a name with the length 6)

    Vowelcounter has an initial value of 0

    The 2 arrays are declared as follows:

    Code:
    char vowels[10];
    char name[10];

  4. #4
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Instead of us having to make wild guesses, why not post the entire code (or at least a stripped-down (and compilable) example that demonstrates the problem)?

  5. #5
    Registered User
    Join Date
    Sep 2009
    Posts
    11
    Variable names and printf segments are in norwegian, but that shouldnt really matter:

    Code:
    #include <stdlib.h>
    #include <string.h>
    
    
    int vocal(char a)
    {
      if(a == 'a' || a == 'e' || a == 'i' || a == 'o' ||  a == 'u' || a == 'y' || a == 'ø') return 1;
      else return 0;
    }
    
    int main(void)
    {
    
      int counter = 0;
      int vokalcounter = 0;
      printf("Skriv inn navnet ditt: ");
      char navn[10];
      char vokaler[10];
      scanf("%s", &navn);
      
      int i;
      for(i = 0; i < 10; i++){
        if(vocal(navn[i])){
    	counter++;
    	vokaler[vokalcounter] = navn[i];
    	vokalcounter++;
    	
        }
      }// end for
    
      printf("Navnet ditt har %d vokaler i seg!\n", counter);
      printf("Vokalene i ditt navn er: ");
    
      int j = 0;
    
      while(vokaler[j] != 0){
        printf("%s", vokaler[j]);
        j++;
      }// end for
      printf("\n");
    
    }

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> scanf("%s", &navn);

    Remember: scanf takes the address of a variable, but in the case of a character string, the array name itself resolves to a pointer. In other words, you're giving scanf the wrong address (eg: drop the amperstand).

  7. #7
    Registered User
    Join Date
    Sep 2009
    Posts
    11
    Thanks for your help so far. Unfortunately the problem still persists after I removed the amperstand. The rest of the code is identical to what I pasted on these boards. Did it work properly for you or?

    Edit: Also clarifying: The error is in the part where I give "vokaler" its values. The counter for number of vowels in a string is working properly for me, so I dont think the variable "navn" is the issue. Then again I only started C this morning so I'm a complete beginner to it(although Im quite proficient in Java)
    Last edited by Stenland; 09-19-2009 at 02:52 AM.

  8. #8
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> scanf("%s", navn);

    This is dangerous. scanf doesn't know how big the array is, so it could easily overflow. You should specify the maximum length in the format string, eg:

    scanf("%9s", navn);

    >> for(i = 0; i < 10; i++){

    For one thing, character arrays are null-terminated, so this is going one too far. At any rate, you should be looping until you reach the terminator, not the size of the buffer. After the loop exits, you need to make sure the array vokaler is null-terminated.

    >> printf("%s", vokaler[j]);

    vokaler[j] is a character, but you're telling printf that it's a null-terminated string. Use the %c modifier to print a single character.

  9. #9
    Registered User
    Join Date
    Aug 2009
    Posts
    26
    I guess you would require to do a memset on both of these character arrays before you actually use it...Can you just give it a try?

  10. #10
    Registered User
    Join Date
    Sep 2009
    Posts
    11
    Thanks a lot for your help Sebastiani, learned some valuable lessons

    One last question for anyone that has time, that is related to you showing me that you can max the input size in the scan f function. I delved a bit into c++ some months ago, and there I could leave the character arrays without a size, so that the size of the input determined the size of the array, including the null terminator. Is this possible in c? I tried playing around with it a little, but couldnt come up with a similar solution

  11. #11
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    No, for that you would need to allocate the array with malloc/realloc. A more typical approach is to declare a reasonably large input buffer and just limit the user input to that. So say you expect the use to enter 10 characters. Declare an array of 64 and it should be more than ample, etc. Anyway, a much safer way to read input, incidentally, is by using fgets. You don't need do hard-code the array size in the string, and integers/floats can be converted with atoi/strtol/atof. The drawback is that fgets and scanf create problems when used together (eg: scanf leaves the newline in the input buffer while fgets stores it).

    I put together a little example, though I may have goteen a bit carried away...

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    char* getline( char* buf, size_t max, FILE* inf )
    {
    	char* fnd, * ret = fgets( buf, max, inf );
    	if( ret != 0 )
    	{
    	/*
    		Remove the newline
    	*/
    		fnd = strchr( ret, '\n' );
    		if( fnd )
    			*fnd = 0;
    	}
    /*
    	An error/eof occured, set first character to 0, 
    	making sure that there is room, though, first
    */	
    	else if( max )
    	{
    		*buf = 0;
    	}	
    	return ret;
    }
    
    int text_to_double( const char* dat, double* ret )
    {
    	char* ptr;
    	*ret = strtod( dat, &ptr );
    	if( *dat == 0 || *ptr != 0 )
    	{
    		*ret = 0;
    		return 0;
    	}
    	return 1;
    }
    
    int text_to_integer( const char* dat, int* ret )
    {
    	char* ptr;
    	*ret = strtol( dat, &ptr, 0 /*guess*/ );
    	if( *dat == 0 || *ptr != 0 )
    	{
    		*ret = 0;
    		return 0;
    	}
    	return 1;
    }
    
    int main(void)
    {
    	const size_t size = 128;
    	char buffer[ size ], temp[ size ];
    	int mode, i;
    	double d;
    	enum { text_mode = 0, integer_mode, double_mode, invalid_mode };
    	
    	for( ;; )
    	{
    		printf( "Enter some text (press [ENTER] to exit) > " );
    		getline( buffer, size, stdin );
    		if( buffer[ 0 ] == 0 )
    		{
    			break;
    		}
    		for( ;; )
    		{
    			printf( "Mode? (0) Text (1) Integer (2) Float > " );
    			if( !text_to_integer( getline( temp, size, stdin ), &mode ) )
    			{
    				puts( "Error: expected integer. Please try again." );
    			}
    			else if( mode >= invalid_mode )
    			{
    				puts( "Error: invalid option. Please try again." );
    			}
    			else
    			{
    				break;
    			}	
    		}	
    		if( mode == text_mode )
    		{
    			printf( "You entered the text: '%s'\n", buffer );
    		}
    		else if( mode == integer_mode )
    		{
    			if( !text_to_integer( buffer, &i ) )
    			{
    				printf( "Sorry, '%s' is not a valid integer value!\n", buffer );
    			}			
    			else
    			{
    				printf( "You entered the number '%d'\n", i );
    			}	
    		}
    		else if( mode == double_mode )
    		{
    			if( !text_to_double( buffer, &d ) )
    			{
    				printf( "Sorry, '%s' is not a valid floating point value!\n", buffer );
    			}			
    			else
    			{
    				printf( "You entered the floating point number '%f'\n", d );
    			}	
    		}		
    	}
    	return 0;
    }
    Sorry if it has bugs, it's just an example, really. But my point is simply that scanf really isn't necessary in most cases.

    EDIT: Whoops should have been "press ENTER" not "press SPACEBAR".
    Last edited by Sebastiani; 09-19-2009 at 04:29 AM.

  12. #12
    Registered User
    Join Date
    Sep 2009
    Posts
    11
    Thanks again Sebastiani for taking the time to learn me these things, really appreciated and it is going to be a massive help for me(I'm doing a course at uni this semester where we basically have to teach ourselves the programming parts(C specifially, we get trained in Java here in other courses), since the course isnt about programming, but you need to be pretty good at C to get good grades.

  13. #13
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Your welcome. Good luck.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Segmentation fault problem
    By odedbobi in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2008, 03:36 AM
  2. Segmentation fault
    By bennyandthejets in forum C++ Programming
    Replies: 7
    Last Post: 09-07-2005, 05:04 PM
  3. Segmentation fault
    By NoUse in forum C Programming
    Replies: 4
    Last Post: 03-26-2005, 03:29 PM
  4. Locating A Segmentation Fault
    By Stack Overflow in forum C Programming
    Replies: 12
    Last Post: 12-14-2004, 01:33 PM
  5. Segmentation fault...
    By alvifarooq in forum C++ Programming
    Replies: 14
    Last Post: 09-26-2004, 12:53 PM