Thread: strcpy() Not Responding to Input

  1. #1
    Registered User
    Join Date
    Dec 2005
    Posts
    1

    strcpy() Not Responding to Input

    When starting the shell function, the strcpy() call doesn't properly copy argdin to arg:
    main.c:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include "data.h"
    
    void randinit(void);
    int randint(int max);
    void create(struct ch * ma);
    void shell(struct ch * ma);
    
    int main(int argc, char * argv[]) {
    	struct ch mai;
    	int c;
    	randinit();
    	if(!strcmp("--new", argv[1])) {
    		create(&mai);
    	}
    	printf("Welcome, %s.",(&mai)->name);
    	shell(&mai);
    	printf("Bye!\n");
    	return 0;
    }
    
    void create(struct ch * ma) {
    	char * name = malloc(64);
    	printf("Name (64): ");
    	fgets(name, 64, stdin);
    	ma->name = malloc(strlen(name));
    	strncpy(ma->name, name, strlen(name) - 1);
    	free(name);
    	ma->total = 10;
    	ma->life = ma->total;
    	ma->pos[0] = 0;
    	ma->pos[1] = 0;
    	printf(STATS, ma->name, ma->life, ma->total, ma->pos[0], ma->pos[1]);
    }
    shell.c:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "data.h"
    
    void shell(struct ch * ma) {
    	char * argdin, * arg;
    	int exit = 0, ret, time = 0;
    	while(exit == 0) {
    		argdin = malloc(256);
    		printf("\nD: ");
    	//	printf("%s\n", stin);
    		fgets(argdin, 255, stdin);
    		printf("%s\n", argdin);
    		arg = malloc(strlen(argdin) + 1);
    		strncpy(arg, argdin, strlen(argdin) - 1);
    		printf("%s\n", arg);
    	//	printf("arg = %s\n", arg);
    		if(!strcmp("exit", arg) || !strcmp("quit", arg)) {
    			exit = 1;
    		}
    		else if(!strncmp("move", arg, 4)) {
    			ret = move(ma, arg);
    			if(ret == 0) {
    				printf("Move %c is out of bounds.", arg[5]);
    			}
    			else if(ret == 1) {
    				printf("Moved %c.", arg[5]);
    			}
    			else if(ret == 2) {
    				printf("Where is %c?", arg[5]);
    			}
    		}
    		else if(!strcmp("stat", arg)) {
    			printf(STATS, ma->name, ma->life, ma->total, ma->pos[0], ma->pos[1]);
    		}
    		else {
    			if(time == 0) {
    				time = 1;
    			}
    			else if(time == 1) {
    				printf("Command not understood!");
    			}
    		}
    		free(argdin);
    	}
    }
    comm.c:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "data.h"
    
    int move(struct ch * ma, char * com) {
    	if(com[5] == 'u') {
    		if(ma->pos[1] == 0) {
    			return 0;
    		}
    		else {
    			ma->pos[1] = ma->pos[1] - 1;
    			return 1;
    		}
    	}
    	else if(com[5] == 'd') {
    		if(ma->pos[1] == YMAX) {
    			return 0;
    		}
    		else {
    			ma->pos[1] = ma->pos[1] + 1;
    			return 1;
    		}
    	}
    	else if(com[5] == 'l') {
    		if(ma->pos[0] == 0) {
    			return 0;
    		}
    		else {
    			ma->pos[0] = ma->pos[0] - 1;
    			return 1;
    		}
    	}
    	else if(com[5] == 'r') {
    		if(ma->pos[0] == XMAX) {
    			return 0;
    		}
    		else {
    			ma->pos[0] = ma->pos[0] + 1;
    			return 1;
    		}
    	}
    	else {
    		return 2;
    	}
    }
    randgen.c:
    Code:
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    void randinit(void) {
    	srand(time(NULL));
    }
    
    int randint(int max) {
    	return rand() % (max + 1);
    }
    data.h:
    Code:
    struct ch {
    	char * name;
    	int total, life, pos[2];
    };
    #define STATS "%s\n%d/%d\nPOS[%d,%d]\n" // NAME, CURRENT LIFE, TOTAL LIFE, X POSITION, Y POSITION
    #define YMAX 256
    #define XMAX 256
    Example Output:
    Code:
    Name (64): Neil  
    Neil             
    10/10            
    POS[0,0]         
    Welcome, Neil.   
    D: exit          
    exit             
                     
    exitüƒ‼a         
                     
    D: exit          
    exit             
                     
    exit             
    Bye!
    Why does the first strcpy() not work correctly?

  2. #2
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    Code:
    strncpy(arg, argdin, strlen(argdin) - 1);
    You are telling it to copy only strlen(argdin) - 1, presumably to remove the linefeed that fgets may have appended. But if you tell strncpy to copy a shorter count than the string + null, it won't copy the null terminator of the string across.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > argdin = malloc(256);
    Why do you malloc and free every time?

    char argdin[256];
    right at the beginning will suffice.

    > fgets(argdin, 255, stdin);
    You don't need to compensate for the \0, fgets() will do it for you.
    With an array, you would simply do fgets( argdin, sizeof argdin, stdin );

    > strncpy(arg, argdin, strlen(argdin) - 1);
    As noted, strncpy() doesn't always append a \0 for you - hence the garbage you see between the string you copied and the first \0 which just happened to be in some random memory location past the end of your data.
    If this is an attempt to avoid the \n, then read the FAQ on using fgets, which shows other ways of removing the \n

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Checking array for string
    By Ayreon in forum C Programming
    Replies: 87
    Last Post: 03-09-2009, 03:25 PM
  2. I would love some input on my BST tree.
    By StevenGarcia in forum C++ Programming
    Replies: 4
    Last Post: 01-15-2007, 01:22 AM
  3. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM
  4. Structure and Linked List User Input Question
    By kevndale79 in forum C Programming
    Replies: 16
    Last Post: 10-05-2006, 11:09 AM