Thread: strncpy

  1. #1
    Registered User
    Join Date
    Jul 2007
    Posts
    39

    strncpy

    Ok I'm trying to make a strncpy prototype, and it's sort of working but on the first go it eats up the first letter and it has trouble quitting the loop, you have to enter Q twice. I've tried different implementations of the While loop and this is the only one so far to even come close to working, but again it's eating things up so I'm guessing I'm not supposed to be using getchar as my check. But I just can't figure out what else to do. Thanks again for your help guys.

    Code:
    #include <stdio.h>
    #define MAX 80
    char ncpy(char * orig, char * add, int n);
    int main(void)
    {
    	char ins[MAX+1], bee[MAX+1];
    	int n, L=0;
    	
    	printf("Input a line [q to quit]\n");
    	while(getchar() != 'q')
    		{
    		gets(bee);
    		puts("Choose length to be copied");
    		scanf("%d", &n);
    //	printf("%s %d", bee, n);
    		ins[L] = ncpy(ins + L, bee, n);
    		printf("\n%s\n", ins);
    		L += n;
    		printf("Input a line [q to quit]\n");
    		}
    
    	return 0;
    }						
    	
    char ncpy(char * orig, char * add, int n)
    	{
    	int i;
    	
    	for(i=0; i<n; i++)
    		orig[i] = add[i];
    
    	return (*orig);
    	}

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Why not just use gets(bee) [1], and then check if the string is "q"?


    [1] Or better yet, use fgets(bee, sizeof(bee), stdin), which prevents someone who puts his elbow on the keyboard for five minutes from overflowing your buffer.

    --
    Mats

  3. #3
    Registered User
    Join Date
    Jul 2007
    Posts
    39
    if you mean making it

    while (gets(bee) && bee[0] != 'q') I tried that as well as
    while (bee[0] != 'q')

    and that resulted in it printing


    "Input a line [q to quit]
    Choose length to be copied"

    in between new lines anytime you hit enter no matter what was input.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, I suppose that is what you'd get from doing that.

    How about:

    Code:
    ...
    int done = 0;
    ...
    
    while(!done) {
        fgets(bee, sizeof bee, stdin);
        if (strcmp("q", bee) == 0)
            done = 1;
        else if (strlen(bee) != 0) {
            ... // the rest of your code to chose n and such 
       } 
    }
    --
    Mats

  5. #5
    Registered User
    Join Date
    Jul 2007
    Posts
    39
    Code:
    #include <stdio.h>
    #define MAX 80
    char ncpy(char * orig, char * add, int n);
    int main(void)
    {
    	char ins[MAX+1], bee[MAX+1];
    	int n, L=0;
    	int done = 0;
    	
    	printf("Input a line [q to quit]\n");
    	while(!done)
    		{
    		fgets(bee, sizeof bee, stdin);
        if (strcmp("q", bee) == 0)
            done = 1;
        else if (strlen(bee) != 0) 
    			{
    			puts("Choose length to be copied");
    			scanf("&#37;d", &n);
    //	printf("%s %d", bee, n);
    			ins[L] = ncpy(ins + L, bee, n);
    			printf("\n%s\n", ins);
    			L += n;
    			printf("Input a line [q to quit]\n");
    			}
    		}
    
    	return 0;
    }						
    	
    char ncpy(char * orig, char * add, int n)
    	{
    	int i;
    	
    	for(i=0; i<n; i++)
    		orig[i] = add[i];
    
    	return (*orig);
    	}
    resulted in

    [Session started at 2007-07-27 19:46:58 -0400.]
    Input a line [q to quit]
    bam
    Choose length to be copied
    3

    bam$&#203;$\303\377\377\377\377\377\377
    Input a line [q to quit]
    Choose length to be copied

    forgot string.h first run but adding it didn't help
    Last edited by zmaker5; 07-27-2007 at 05:56 PM.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Well, the garbage at the end is that you're not terminating the string in your ncpy function.

    You may also want to strip any carriage return and newlines from the fgets() functions input - that way the check for "empty string" will work.

    --
    Mats

  7. #7
    Registered User
    Join Date
    Jul 2007
    Posts
    39
    Got the termination in but it's still just looping straight to "choose length" after the first run through. I just don't know how I get it to stop reading in an extra new line (since I'm assuming that's what's forcing the looping when it checks for an empty string. Before I made it a looping program I used a
    getchar():
    to remove the newline from the input before it read the input string. I hate to be a bother but I'm refreshing myself on C (never was too in depth in it, the logic is easy but the syntax always gets me.) So you might have to hint at how I can remove returns and newlines before fgets kicks in. Thanks again for your help


    -edit- I'm going to just redo my loop entirely, I've changed some things and it's looping fine but I have to rethink how I'm passing my main array so that each input gets added on to the end. Thanks again mate


    Hah! and just got it working, a little fix and bam, guess I just needed to step back for a bit and think about it. Here's the fixed version if anyone ever needs this (lord only knows why)

    Code:
    #include <stdio.h>
    #include <string.h>
    #define MAX 80
    char ncpy(char * orig, char * add, int n);
    int main(void)
    {
    	char ins[MAX+1], bee[MAX+1];
    	int n, L=0;
    	int done = 0;
    	
    	printf("Input a line [q to quit]\n");
    	while(!done)
    		{
    		gets(bee);
        if (strcmp("q", bee) == 0)
            done = 1;
        else if (strlen(bee) != 0) 
    			{
    			puts("Choose length to be copied");
    			scanf("%d", &n);
    //	printf("%s %d", bee, n);
    			ins[0] = ncpy(ins + L, bee, n);
    			printf("\n%s\n", ins);
    			L += n;
    			printf("Input a line [q to quit]\n");
    			}
    		}
    
    	return 0;
    }						
    	
    char ncpy(char * orig, char * add, int n)
    	{
    	int i;
    	
    	for(i=0; i<n; i++)
    		orig[i] = add[i];
    	orig[i] = '\0';
    
    	return (*orig);
    	}
    Last edited by zmaker5; 07-27-2007 at 07:37 PM.

  8. #8
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    I wouldn't be using gets() due to its limitations (ie. being unsafe). Consider using fgets() as a replacement.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > if (strcmp("q", bee) == 0)
    Would have been OK had you read the FAQ and realised that fgets appends a newline.

    So
    - remove the newline as mentioned in the FAQ
    - append the newline to the compare, as in strcmp("q\n", bee)

    Ideally, the while loop should be
    while ( !done && fgets(bee, sizeof bee, stdin) != NULL )
    So the loop exits when the done flag becomes clear, or the user signals EOF to the input.

    > scanf("%d", &n);
    Having used fgets() to read one thing, you should use it to read everything. Mixing input functions leads only to pain and confusion.
    Eg, replace the scanf with
    fgets(line, sizeof line, stdin)
    scanf( line, "%d", &n);

    where line is a char array similar to bee
    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.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Salem View Post
    > if (strcmp("q", bee) == 0)
    Would have been OK had you read the FAQ and realised that fgets appends a newline.
    Sorry, I should have thought of that! [Also, it seems that MS adds both \n and \r, so if that's the compiler being used, it's probably good to remove BOTH]"
    So
    - remove the newline as mentioned in the FAQ
    - append the newline to the compare, as in strcmp("q\n", bee)
    Yes, me sloppy...

    Ideally, the while loop should be
    while ( !done && fgets(bee, sizeof bee, stdin) != NULL )
    So the loop exits when the done flag becomes clear, or the user signals EOF to the input.

    > scanf("%d", &n);
    Having used fgets() to read one thing, you should use it to read everything. Mixing input functions leads only to pain and confusion.
    Eg, replace the scanf with
    fgets(line, sizeof line, stdin)
    scanf( line, "%d", &n);

    where line is a char array similar to bee
    That's a good solution.

    --
    Mats

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by zmaker5 View Post
    Code:
    char ncpy(char * orig, char * add, int n)
    
    ...
    
    	return (*orig);
    What good is simply returning the first char?
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > it seems that MS adds both \n and \r,
    Unless you're reading from a text file opened in binary mode, this behaviour is broken IMO.

    The C 'f' functions are supposed to convert the OS line termination to just '\n' on input, and convert '\n' to the OS line termination on output.
    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.

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Salem View Post
    > it seems that MS adds both \n and \r,
    Unless you're reading from a text file opened in binary mode, this behaviour is broken IMO.

    The C 'f' functions are supposed to convert the OS line termination to just '\n' on input, and convert '\n' to the OS line termination on output.
    Sorry, yes you are right - I confused myself by what I remember from last night - I removed the last char (by replacing it with a zero) in my test-case, not the last two!

    --
    Mats

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. why is strncpy segfaulting here?
    By Calef13 in forum C Programming
    Replies: 3
    Last Post: 12-29-2008, 03:27 PM
  2. Replace strncpy with snprintf, how?
    By garton in forum C Programming
    Replies: 19
    Last Post: 09-11-2008, 03:21 AM
  3. strncpy adavnced :P
    By Joke in forum C Programming
    Replies: 3
    Last Post: 07-14-2008, 11:14 AM
  4. strncpy question, size -1??
    By fayte in forum C Programming
    Replies: 16
    Last Post: 03-16-2006, 11:32 PM
  5. strncpy doesn't seem to work
    By linucksrox in forum C++ Programming
    Replies: 3
    Last Post: 09-08-2005, 01:34 PM