Clay James
Clay James

Reputation: 23

C string behaving strangely when longer than 7 characters

I am trying to create a program in C which takes a user's input and 'evolves' a random string until it matches the input. So far it works fine on input which is 7 characters or less, but as soon as a user enters 8 characters the program doesn't work. I can't figure out where I am going wrong. Here's the code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

void mutate(char ancestor[], char descendent[]);
void evolve(char descendent[]);

int main(void)
{
    srand(time(NULL));
    char input[50];

    printf("Please Enter a String:\n");
    scanf("%s", input);

    evolve(input);
    return 0;


void evolve(char descendent[])
{
    size_t length = strlen(descendent);
    char ancestor[50];
    int i;
    for(i = 0; i < length; i++)
        ancestor[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % 52];
    while(strcmp(ancestor, descendent)){
        mutate(ancestor, descendent);
        printf("%s\n", ancestor);
    }
}

void mutate(char ancestor[], char descendent[])
{
    int i;
    size_t length = strlen(descendent);
    for(i = 0; i < length; i++){
        if(ancestor[i] != descendent[i]){
            ancestor[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % 52];
        }
    }
}

Upvotes: 0

Views: 157

Answers (2)

user6169399
user6169399

Reputation:

First you must check for errors:

char input[50];
scanf("%s", input);
  1. Did scanf succeed?
  2. The user could enter more than 50 characters for input:

    if (scanf("%49s", input) != 1){
        printf("incorrect input\n");
        return 1; // error
    }
    
  3. You need to check input string for valid input too using e.g. isalpha():

    n = strlen(input);
    for (i = 0; i < n; i++){
        if (!isalpha(input[i])) {
            printf("incorrect input\n");
            return 1; // error
        }
    }
    

    It is good to use C preprocessor Stringification:

    #define MAX_LEN 4  
    #define STR2(n) #n
    #define STR(n) STR2(n)
    printf("Please Enter a String[A-Z,a-z] with max length:"STR(MAX_LEN)"\n");
    if (scanf("%"STR(MAX_LEN)"s", input) != 1){
        printf("incorrect input\n");
        return 1; // error
    }
    

    This will ask, Please Enter a String[A-Z,a-z] with max length:4.

    With a limit of 49 letters, I think it could take more than a lifetime to finish!

  4. Inside evolve(), you need to ensure that the ancestor string is NUL-terminated:

    ancestor[i] = 0;
    

Here's a working sample with my improvements:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

void mutate(char ancestor[], char descendent[]);
void evolve(char descendent[]);

#define MAX_LEN 4  
#define STR2(n) #n
#define STR(n) STR2(n)

int main(void)
{
    int i;
    int n;
    srand(time(NULL));
    char input[MAX_LEN + 1];

    printf("Please Enter a String[A-Z,a-z] with max length:"STR(MAX_LEN)"\n");
    if (scanf("%"STR(MAX_LEN)"s", input) != 1){
        printf("incorrect input\n");
        return 1; // error
    }
    n = strlen(input);
    for (i = 0; i < n; i++){
        if (!isalpha(input[i])) {
            printf("incorrect input\n");
            return 1; // error
        }
    }

    evolve(input);
    return 0;
}

void evolve(char descendent[])
{
    size_t length = strlen(descendent);
    char ancestor[MAX_LEN + 1];
    int i;
    for (i = 0; i < length; i++)
        ancestor[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % 52];
    ancestor[i] = 0;
    while (strcmp(ancestor, descendent)){
        mutate(ancestor, descendent);
        printf("%s\n", ancestor);
    }
}

void mutate(char ancestor[], char descendent[])
{
    int i;
    size_t length = strlen(descendent);
    for (i = 0; i < length; i++){
        if (ancestor[i] != descendent[i]){
            ancestor[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[rand() % 52];
        }
    }
}

Upvotes: 2

BlackMamba
BlackMamba

Reputation: 10254

The issue is in strcmp. please read: http://www.cplusplus.com/reference/cstring/strcmp/

This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.

But for char ancestor[50];, you don't give it a null-character. so there will be undefinded behavior for strcmp.

Upvotes: 0

Related Questions