late night coding

This is a discussion on late night coding within the C Programming forums, part of the General Programming Boards category; As the title suggest i'm coding at late o'clock over here and My code just hangs. I'm sure its something ...

  1. #1
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751

    late night coding

    As the title suggest i'm coding at late o'clock over here and My code just hangs. I'm sure its something simple but I'd like to get it before bed.
    thanks.
    Code:
    /* my getWord.c 
    GetWord reads characters from stdin up until the first space. it stores it in its
    argument a char * and appends a '\n' then returns the word */
    #include <stdio.h>
    #include <string.h>
    #define STOP ' '
    #define SIZE 100
    
    char *GetWord(char *);
    int main(void){
        char store[SIZE];
        
       char *word = GetWord(store);
        printf("The word is %s", word);
        getchar();
        return 0;
    }
    
    char *GetWord(char vault[]){
        int ch,ndx=0;
        while( (ch = getchar()) !=STOP || ch !=EOF){
             vault[ndx] = ch;
            ndx+=1;
        }
        vault[ndx] = '\0';
        while(getchar() !='\n');
        return vault;
    }
    Last edited by caroundw5h; 09-01-2004 at 10:46 PM.
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  2. #2
    C Programmer Stack Overflow's Avatar
    Join Date
    Apr 2004
    Posts
    477
    You could always try this:

    Code:
    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #include <ctype.h>
    
    int getword(char *word, int lim) {
    	int c;
    	char *w = word;
    
    	while (isspace(c = getch()))
    		;
    	if (c != EOF)
    		*w++ = c;
    	if (!isalpha(c)) {
    		*w = '\0';
    		return c;
    	}
    	for ( ; --lim > 0; w++)
    		if (!isalnum(*w = getch())) {
    			ungetch(*w);
    			break;
    		}
    	*w = '\0';
    
    	return word[0];
    }
    
    int main() {
    	char word[128];
    
    	printf("Enter your password: ");
    	if (getword(word, 128) != EOF)
    		printf(word);
    
    	return 0;
    }
    Heh, kinda late for me tonight too. Just tossing some ideas around.


    - Stack Overflow
    Segmentation Fault: I am an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

  3. #3
    Software Developer jverkoey's Avatar
    Join Date
    Feb 2003
    Location
    University of Waterloo
    Posts
    1,903
    fix
    Code:
        while( (ch = getchar()) !=STOP && ch !=EOF){

  4. #4
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    Thanks for the replies guys.
    Quote Originally Posted by jverkoey
    fix
    Code:
        while( (ch = getchar()) !=STOP && ch !=EOF){

    I knew it was something simple it I was drinking i'd have an excuse. right now its just lack of sleep. Thanks again.

  5. #5
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,528
    Something else you might want to add into your Getword() function is some limitation on the input, so that the user cannot go outside the bounds of your array. Perhaps pass the size of the 'vault' to the function, and make sure that the input stops at one less than size, in order to leave room for the '\0'

    ~/

  6. #6
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    Of course your right Kermit. I wasn't worried or thinking about buffer overflows and I should always be, espeacially when working with arrays you should have pass the size of the array as a parameter. Thanks.
    Good think i'm not working on a kernal of anything

  7. #7
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751

    same problem different notation.

    I'm having some logic problems I think again. This code simply returns "". Its the same problem as the above. it fetches the first word from input. Sorry If i was supposed to start a new thread. wasnt' really sure.
    Code:
    char *GetWord(char *vault){
    //get word using advance pointer notation 
    int ch;
    while( (ch = getchar()) !=STOP && ch !=EOF){
        *(vault++) = ch;
    }
    *vault ='\0';//whatever indice vault is at
    while ( (getchar()) !='\n'); 
    return  vault;   
    }

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    It returns nothing, because you're incrementing vault throughout the function, and at last check, you assign it a null:
    Code:
    *vault ='\0';//whatever indice vault is at
    Then you return that location.

    You'll need to add a pointer, and increment that instead of incrementing vault, and then return vault.

    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    thanks for the reply. couple questions.
    When i return vault am i not returning it to vault[0] really. since vault is a pointer to character? then when I call it in main it should start printing from vault[0].

    also what is the diference between this code. I just found out my book has an answer to this problem. It works fine, but it looks identical to mine.
    Code:
    char * getword(char * str)
    {
        //int i;
        int ch;
    
        while ((ch = getchar()) != EOF && !isspace(ch))
            *str++ = ch;
        *str = '\0';
        if (ch == EOF)
            return NULL;
        else
        {
            while (ch != '\n')
                ch = getchar();
            return str;
        }
    }
    and mine
    Code:
    char *GetWord(char *vault){
    //get word using advance pointer notation 
    int ch;
    
    while( (ch = getchar()) !=STOP && ch !=EOF){
        *(vault++) = ch;
    }
    *vault ='\0';//whatever indice vault is at
    while ( (getchar()) !='\n'); 
    return  vault;   
    }
    The only thing i can see is I don't provide a conditional for EOF.

    You'll need to add a pointer, and increment that instead of incrementing vault, and then return vault.
    can you give me an example of what you mean please.
    Last edited by caroundw5h; 09-03-2004 at 08:01 PM.
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Code:
    char *GetWord(char *vault){
        //get word using advance pointer notation 
        int ch;
        while( (ch = getchar()) !=STOP && ch !=EOF){
            *(vault++) = ch;
        }
        *vault ='\0';//whatever indice vault is at
        while ( (getchar()) !='\n'); 
        return  vault;   
    }
    Should be:
    Code:
    char *GetWord(char *vault){
        //get word using advance pointer notation 
        int ch;
        char *ptr = vault;
        while( (ch = getchar()) !=STOP && ch !=EOF){
            *(ptr++) = ch;
        }
        *ptr ='\0';//whatever indice vault is at
        while ( (getchar()) !='\n'); 
        return  vault;   
    }
    That way you retain your origional pointer, so you can return it. This returns the start of the string, so you can actually use it. Or perhaps:
    Code:
    char *GetWord(char *vault){
        //get word using advance pointer notation 
        int ch, count = 0;
        char *ptr = vault;
        while( (ch = getchar()) !=STOP && ch !=EOF){
            vault[count++] = ch;
        }
        vault[count] ='\0';//whatever indice vault is at
        while ( (getchar()) !='\n'); 
        return  vault;   
    }
    Or you could do the same, but use a bit of pointer math:

    Code:
    char *GetWord(char *vault){
        //get word using advance pointer notation 
        int ch, count=0;
        while( (ch = getchar()) !=STOP && ch !=EOF){
            *(vault + count++) = ch;
        }
        *(vault + count ) ='\0';//whatever indice vault is at
    while ( (getchar()) !='\n'); 
    return  vault;   
    }
    I think all of those should work, I'm on the phone, so this is what you get.

    Quzah.
    Hope is the first step on the road to disappointment.

  11. #11
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,796
    >When i return vault am i not returning it to vault[0] really.
    No. You're using vault to walk along the memory where you are storing the characters. When you return vault, it points to the end of the string. If you want to keep the beginning you must save it before starting your run:
    Code:
    #include <ctype.h>
    #include <stdio.h>
    
    char *getword ( char *buffer, FILE *in )
    {
      char *p = buffer;
      int ch;
    
      /* Stop at whitespace or end-of-file */
      while ( ( ch = fgetc ( in ) ) != EOF && !isspace ( ch ) )
        *p++ = (char)ch;
    
      /* Finalize the string */
      *p = '\0';
    
      /* Return end-of-file only if the buffer is empty */
      if ( buffer[0] == '\0' )
        return NULL;
      else
        return buffer;
    }
    
    int main ( void )
    {
      char buffer[BUFSIZ];
    
      printf ( "%s\n", getword ( buffer, stdin ) );
    
      return 0;
    }
    My best code is written with the delete key.

  12. #12
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    Alright Quzah. your first two fragmenets are equivalent to what i've already done while playing around with this function.
    Code:
    GetWord using array notation. 
    
    char *GetWord(char vault[]){
        int ch,ndx=0;
        while( (ch = getchar()) !=STOP && ch !='\n' && ch !=EOF){
            //*(vault++) = ch;
             vault[ndx] = ch;
            ndx+=1;
        }
        //(*vault) = '\0';
        vault[ndx] = '\0';
        while((getchar()) !='\n');
        return vault;
    }
    and the other
    Code:
    char *GetWord(char vault[]){
    //get word using pointer notation 
    int ch,ndx=0;
    while( (ch = getchar ()) != STOP && ch !='\n' && ch !=EOF){
        *(vault + ndx) = ch;
        ndx+=1;
    }
    *(vault + ndx) = '\0';
    while((getchar() ) !='\n');
    return vault;
    }
    Thanks. I think the lesson to be learned here is what both you an prelude are pointing to that i need to use another pointer and increment that instead of the char *vault. It seems to be the equivalent of a index counter if i'd done it with array notation.
    You'll need to add a pointer, and increment that instead of incrementing vault, and then return vault.
    I actually understood this and how to implement it when you said it. I just didn't and still don't understand why - though I can see how it works - I would have need to do it. but you guys are right.

    No. You're using vault to walk along the memory where you are storing the characters. When you return vault, it points to the end of the string. If you want to keep the beginning you must save it before starting your run:
    Once again ma'am you've taught me something new just when I thought I understood it all. I'll think on it and see why I confused it and thought it would work. I'm probably just not thinking I'm so use to throwing together python code an having it work.
    If i think on it i'm sure i'll realise why it couldn't work.

    Thank you guys both.

  13. #13
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,796
    >I just didn't and still don't understand why
    Why is very simple. You have a pointer that points to the beginning of a block of memory. If you assign a value to that location and then increment the pointer, you no longer point to the beginning of the block:
    Code:
    #include <stdio.h>
    
    int main ( void )
    {
      char buffer[2] = {'a','b'};
      char *p = buffer;
    
      printf ( "Before increment: %p -- %c\n", p, *p );
      ++p;
      printf ( "After increment:  %p -- %c\n", p, *p );
    
      return 0;
    }
    After your loop, the pointer has been incremented N times and the current memory that it points to contains the null terminator for the string. Therefore you're pointing to the end of the string. The only way to get back to the beginning is to either save the address of the beginning of the string:
    Code:
    #include <ctype.h>
    #include <stdio.h>
    
    char *getword ( char *buffer )
    {
      char *p = buffer;
      int ch;
    
      while ( ( ch = getchar() ) != EOF && !isspace ( ch ) )
        *p++ = (char)ch;
    
      *p = '\0';
    
      return buffer;
    }
    
    int main ( void )
    {
      char buffer[BUFSIZ];
    
      printf ( "%s\n", getword ( buffer ) );
    
      return 0;
    }
    Or to save the number of increments performed so that you can decrement that many times and find yourself back where you started:
    Code:
    #include <ctype.h>
    #include <stdio.h>
    
    char *getword ( char *buffer )
    {
      int i = 0;
      int ch;
    
      while ( ( ch = getchar() ) != EOF && !isspace ( ch ) ) {
        *buffer++ = (char)ch;
        ++i;
      }
    
      *buffer = '\0';
    
      return buffer - i;
    }
    
    int main ( void )
    {
      char buffer[BUFSIZ];
    
      printf ( "%s\n", getword ( buffer ) );
    
      return 0;
    }
    I'm sure you've also heard this before, but your function is very dangerous in that it doesn't check boundary conditions. You need to pass the size of the buffer as well and use that as another limit for the loop:
    Code:
    #include <ctype.h>
    #include <stdio.h>
    
    char *getword ( char *buffer, size_t size )
    {
      char *p = buffer;
      int ch;
    
      while ( ( ch = getchar() ) != EOF && !isspace ( ch ) && --size > 0 )
        *p++ = (char)ch;
    
      *p = '\0';
    
      return buffer;
    }
    
    int main ( void )
    {
      char buffer[BUFSIZ];
    
      printf ( "%s\n", getword ( buffer, sizeof buffer ) );
    
      return 0;
    }
    My best code is written with the delete key.

  14. #14
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    Why is very simple. You have a pointer that points to the beginning of a block of memory. If you assign a value to that location and then increment the pointer, you no longer point to the beginning of the block:
    Okay. So you point to the next location right?( Or are you saying i'm changing the actual value at that location?) if i'm incrementing the addy that first character is at that first location right? So thats where my logic was:
    Code:
    *(vault++) = ch;
    that vault would increment to the next address and store the next character there.

    This was my origianal code and obvioulsy it didn't work, however this code seems to be indentical and it works.
    Code:
    char * getword(char * str)
    {
        //int i;
        int ch;
    
        while ((ch = getchar()) != EOF && !isspace(ch))
            *str++ = ch;
        *str = '\0';
        if (ch == EOF)
            return NULL;
        else
        {
            while (ch != '\n')
                ch = getchar();
            return str;
        }
    }
    why though?

    also when you call a object by reference and do something to the pointer to object, that is analagous to doing something to the object as well correct? so
    Code:
    char *getword ( char *buffer, FILE *in )
    {
      char *p = buffer;
      int ch;
    
      /* Stop at whitespace or end-of-file */
      while ( ( ch = fgetc ( in ) ) != EOF && !isspace ( ch ) )
        *p++ = (char)ch;
    when it assignes buffer to *p and then when you increment *p++ isn't that incrementing buffer as well? This is my confusion: why assign buffer another ptr if itself is being incremented. it just seems like a rounabout way. Which the code above seems to agree as well(not yours).

    After your loop, the pointer has been incremented N times and the current memory that it points to contains the null terminator for the string.
    but all the characters before were saved to the line of contiguous memory before right? and the '\0' just terminates it at that certain point in memory
    Therefore you're pointing to the end of the string.
    okay.
    The only way to get back to the beginning is to either save the address of the beginning of the string..
    or just
    Code:
    return string
    as in your example
    Code:
    char *getword ( char *buffer )
    {
      char *p = buffer;
      int ch;
    
      while ( ( ch = getchar() ) != EOF && !isspace ( ch ) )
        *p++ = (char)ch;
    
      *p = '\0';
    
      return buffer;
    }
    when you return a pointer unless you specify the direct address, it always goes to the biginning of that block of memory right? thus printing the first character of the string?

    I'm really sorry if i'm not seeing this, it just doesn't make sense to what i've studied about ptrs, incrementing them and what the code from my book says. Feel free to give up in frustraion.

    Last edited by caroundw5h; 09-04-2004 at 12:28 PM.
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  15. #15
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,796
    You're familiar with how to declare a pointer:
    Code:
    char *p;
    But it looks like initializing a pointer at the definition is confusing you. This is no doubt because declarations are designed to resemble use. The declaration above does not dereference anything, the asterisk is only saying that p is a pointer to char. When you initialize p in the same statement:
    Code:
    char buffer[10] = "testing";
    char *p = buffer;
    There is still no dereferencing going on. The asterisk is only used for the declaration of p, then buffer is assigned to p. The result is that p points to the first element of buffer, you could write it equivalently like this:
    Code:
    char buffer[10] = "testing";
    char *p;
    p = buffer; /* Or p = &buffer[0]; */
    This is a subtle and confusing issue with C's declaration design. Just remember that when you initialize an object, you're initializing the object that was declared. p is declared as a pointer to char, so any initialization will be assigning to a pointer to char, not to a char.

    Also note that p does not point to an array. It points to a char that simply happens to be part of an array. If you want to point to an array then a different declaration is required:
    Code:
    char buffer[10] = "testing";
    char (*p)[10];
    p = &buffer;
    The parentheses guarantee that p is a pointer to whatever is outside of the parentheses, an array of 10 char.

    As long as you point to memory that is contiguous and that is in your address space, you can increment and decrement pointers:
    Code:
    char buffer[10] = "testing";
    char *p;
    p = buffer;
    
    p++; /* p now points to &buffer[1] */
    p--; /* p now points back at &buffer[0] */
    You'll often see somebody dereference and increment or decrement with the same expression:
    Code:
    printf ( "%c\n", *p++ ); /* Prints 't', p points to &buffer[1] */
    printf ( "%c\n", *p-- ); /* Prints 'e', p points to &buffer[0] */
    You can force the increment to be performed first by using prefix notation:
    Code:
    printf ( "%c\n", *++p ); /* Prints 'e', p points to &buffer[1] */
    printf ( "%c\n", *--p ); /* Prints 't', p points to &buffer[0] */
    There, that should be enough setup.

    >So you point to the next location right?
    Yes.

    >Or are you saying i'm changing the actual value at that location?
    No, the pointer and the value being pointed to are different.

    >why though?
    *p++ and *(p++) are equivalent. The parentheses don't do anything meaningful because the postfix increment still works the same way: It copies the current value, increments the pointer, then gives the copy to the rest of the expression to work with. Either way you'll be working with p and incrementing to p + 1. This isn't why your code didn't work.

    >however this code seems to be indentical and it works
    No, it does the same thing. It writes a word into str and returns a null character because a reference to the beginning of the string was not saved or calculated. Run the function like this and you'll see:
    Code:
    char buffer[BUFSIZ];
    printf ( "%s\n", getword ( buffer ) );
    printf ( "%s\n", buffer );
    It will print nothing on the first line, then the first word you typed on the second.

    >when you increment *p++ isn't that incrementing buffer as well?
    No, they are two different pointers that just happen to point to the same address. When you increment p, buffer still points to the same location that it did before you incremented p. p and buffer are different objects even though the address they point to is the same.

    >it always goes to the biginning of that block of memory right?
    How do you define the beginning of a block? It's solely dependent on the logic of your program, so pointers cannot magically move to the beginning of a block unless you explicitly tell them to.
    My best code is written with the delete key.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. DirectShow code - long night of coding
    By VirtualAce in forum Game Programming
    Replies: 2
    Last Post: 03-27-2006, 09:50 AM
  2. Late night part 2
    By caroundw5h in forum C Programming
    Replies: 5
    Last Post: 09-09-2004, 10:07 AM
  3. Good times, late at night
    By prog-bman in forum A Brief History of Cprogramming.com
    Replies: 3
    Last Post: 06-15-2004, 09:02 AM
  4. late night coding
    By caroundw5h in forum C Programming
    Replies: 2
    Last Post: 01-08-2004, 08:23 PM
  5. friday night coding with mind numbing music
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 07-13-2002, 05:17 PM

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