Thread: strnlen, implicit declaration?

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    11

    strnlen, implicit declaration?

    Hi,

    I am in my second year of Computer Science and have just been introduced to C this term. Coming from a JAVA background I must say it is slightly daunting, but I'm sure I'll pick it up...

    I'm just having a bit of trouble with a small function I'm writing:

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    /*
     * Print a given description to the standard output stream
     * formatting the output to conform to the maxLineWidth.
     */
    void printDescription(const char *description, const int maxLineWidth) {
    	char buff[maxLineWidth + 1], *b;
    	char word[maxLineWidth + 1], *w;
    	b = buff;
    	w = word;
    	
    	for(; *description !='\0'; description++) {
    		*w = *description;
    
    		if (*description == ' ' &&  strnlen(w, maxLineWidth) + strnlen(b, maxLineWidth) <= maxLineWidth) {
    			b = strncat(*b, *w, strnlen(w, maxLineWidth));
    			w = "";
    		}
    
    		if (strnlen(w, maxLineWidth) + strnlen(b, maxLineWidth) > maxLineWidth) {
    			printf("%s\n", buff);
    			b = "";
    			b = strncat(*b, *w, strnlen(w, maxLineWidth));
    			w = "";
    		}
    		
    		w++;
    	}
    
    	printf("%s\n", buff);
    }
    Basically the function 'printDescription' takes a paragraph of writing and outputs it depending on the 'maxLineWidth' parameter.

    The way I am trying to implement it is by copying each character to a 'word', then when the word is complete placing it in the buffer for the line. Once the line has reached its maximum allowed length, the line is printed and then the next line and so on...

    I keep getting an error for 'implicit declaration of strnlen' when I try to compile it, so I can't even see if it works yet. Any other tips on where my program is incorrect would also be welcome...

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It means you haven't included the header file where strnlen resides. Without it, the compiler is not guaranteed to generate correct code to call the function (undefined behaviour).
    However, I'm unsure at the time of writing, where it does reside. Suggest you google a little or wait until someone else shows up.
    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.

  3. #3
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Didn't even think strnlen existed.
    =========================================
    Everytime you segfault, you murder some part of the world

  4. #4
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    =========================================
    Everytime you segfault, you murder some part of the world

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    11
    I am pretty sure strnlen resides within the string.h header, and I have included it there...

  6. #6
    Cogito Ergo Sum
    Join Date
    Mar 2007
    Location
    Sydney, Australia
    Posts
    463
    Locate your string.h file and see if it is there. I don't think it's in there if it gives you an implicit declaration.
    =========================================
    Everytime you segfault, you murder some part of the world

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It can't give you an implicit declaration if the compiler sees the actual decaration. Sometimes, depending on compiler, you may have to define macros or similar. The best bet is to take a peek inside the header file and see if you locate the function.
    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.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    strnlen is a non-standard function, so I expect it to only "work" on certain implementations.

    You can write your own:
    Code:
    size_t strnlen(const char *str, size_t maxlen)
    {
         size_t i;
         for(i = 0; i < maxlen && str[i]; i++);
         return i;
    }
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Apr 2008
    Posts
    11
    OK thanks guys, yeah i couldn't find strnlen, but there is strlen there. I was told this may be bad to use because of potential buffer overflows, but I guess I'll just use this instead.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Not if your string is NULL terminated. But you are right in that it may be unsafe.
    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
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    It is "bad" in the sense that if there isn't a zero at the end of the string, it will continue until it finds a zero - which can lead to a segfault/access violation if there is no zero before the "end of current memory block".

    By the way, your code is broken in several ways when it comes to the handling of strings:

    Code:
    ....
    			b = strncat(*b, *w, strnlen(w, maxLineWidth));
    			w = "";
    ....
    	   	        b = "";
    			b = strncat(*b, *w, strnlen(w, maxLineWidth));
    			w = "";
    These bits will DEFINITELY crash your system (unless you are using 16-bit code in DOS where there isn't have any memory protection), as in the second case, *b definitely is 0 - definitely bad destination for a strncpy, and in the other cases *b and *w is a the single character that w points to, which isn't a good memory address for strncat to copy to or from. Also, assuming you removed the *, you are trying to copy to an empty string constant (again, in the second case), which will also fail in most system since it's a "read only" piece of memory that holds the empty string.

    You need to study string handling a bit further (and turn up your warning levels so that you get warnings for passing incorrect parameters to strncpy().


    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by AngryStyro View Post
    OK thanks guys, yeah i couldn't find strnlen, but there is strlen there. I was told this may be bad to use because of potential buffer overflows, but I guess I'll just use this instead.
    How can a function which only READS data possibly overflow a buffer? It could step out of bounds and crash, but the traditional definition of a "buffer overflow" is writing data where you're not supposed to. Whoever told you that is not thinking.

    strnlen() is a paranoid GNU extension written by somebody who was afraid of the black helicopters.

  13. #13
    Registered User
    Join Date
    Apr 2008
    Posts
    11
    Yes, I didn't exactly follow there either but took their word for it since they have more experience in C than me.

  14. #14
    Registered User
    Join Date
    Apr 2008
    Posts
    11
    OK, I have managed to get rid of all the errors whilst compiling, but I am not getting the output I want from the function.

    Code:
    void printDescription(const char *description, const int maxLineWidth) {
    	char buff[maxLineWidth + 1], *b;
    	char word[maxLineWidth + 1], *w;
    	b = buff;
    	w = word;
    	
    	for(; *description !='\0'; description++) {
    		*w = *description;
    
    		if (*description == ' ' &&  strlen(w) + strlen(b) <= maxLineWidth) {
    			b = strncat(b, w, strlen(w + 1));
    			*w = 0;
    		}
    
    		else if (*description == ' ' && strlen(w) + strlen(b) > maxLineWidth) {
    			printf("%s\n", b);
    			*b = 0;
    			b = w;
    			*w = 0;
    		}
    		
    		else {
    			w++;
    		}
    	}
    
    	printf("%s\n", b);
    }
    From my analysis I think the problem is where I have *w=0. What I want to do here is effectively 'reset' the string so it is effectively empty, and the pointer is back at the starting position. I suspect what it is actually doing is just putting a 0 value at the current position and continuing on. Does anybody know what I would have to change it to to get the desired result?

    The only other thing I thought it could be was if strlen included the null characters in the length of the string, but surely it doesn't...

    Many thanks

  15. #15
    Registered User
    Join Date
    Apr 2008
    Posts
    11
    Thought I'd just add what the function is meant to do again...

    Basically the function 'printDescription' takes a paragraph of writing and outputs it depending on the 'maxLineWidth' parameter.

    The way I am trying to implement it is by copying each character to a 'word', then when the word is complete placing it in the buffer for the line. Once the line has reached its maximum allowed length, the line is printed and then the next line and so on...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Quantum Random Bit Generator
    By shawnt in forum C++ Programming
    Replies: 62
    Last Post: 06-18-2008, 10:17 AM
  2. failure to import external C libraries in C++ project
    By nocturna_gr in forum C++ Programming
    Replies: 3
    Last Post: 12-02-2007, 03:49 PM
  3. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  4. Errors with including winsock 2 lib
    By gamingdl'er in forum C++ Programming
    Replies: 3
    Last Post: 12-05-2005, 08:13 PM
  5. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM