Search code examples
c++runtime-errorc-stringspalindrome

concatenating tokens of an old cstring into a new c-string


Our professor gave us a palindrome assignment, and in this assignment we need to write a function that removes all punctation marks, spaces, and converts uppercase letter to lowecase letters in a c-string. The problem I am getting is when I debug/run it, after I enter the cstring for the function, it gives an "Debug Assertion failed" error, and gives the output of only lower case letter version of the c-string input. Does anyone have suggestions how I can fix or improve this piece of code?

Update: I fixed my error by tokenizing the string as geeksforgeeks did. But now the problem I am getting is, when concatenating tokens of s cstring into new_s c-string, it only concatenates the first token of s to new_s. This is my code:

#define _CRT_SECURE_NO_WARNINGS //I added this because my IDE kept giving me error saying strtok is unsafe and I should use strtok_s. 
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace  std;

/*This method removes all spaces and punctuation marks from its c-string as well as change any uppercase letters to lowercase. **/
void removePuncNspace(char s[])
{
    char new_s[50], *tokenptr;

    //convert from uppercase to lowercase
    for (int i = 0; i < strlen(s); i++) (char)tolower(s[i]);

    //use a cstring function and tokenize s into token pointer and eliminate spaces and punctuation marks
    tokenptr = strtok(s, " ,.?!:;");

    //concatenate the first token into a c-string.
    strcpy_s(new_s,tokenptr);

    while (tokenptr != NULL)
    {
        tokenptr = strtok('\0', " ,.?!:;"); //tokenize rest of the string
    }

    while (tokenptr != NULL)
    {
        // concat rest of the tokens to a new cstring. include the \0 NULL as you use a cstrig function to concatenate the tokens into a c-string.
        strcat_s(new_s, tokenptr);
    }

    //copy back into the original c - string for the pass by reference.
    strcpy(s, new_s);
}

My output is:

Enter a line:
Did Hannah see bees? Hannah did!
Did is palindrome


Solution

  • Firstly, as @M.M said, when you want to continue tokenizing the same string, you should call strk(NULL, ".."), not with '\0'.

    Secondly, your program logic doesn't make much sense. You split the string s into substrings, but never actually concatenate them to new_s. By the time you get to the second while, tokenptr is surely NULL, so you never enter the loop.

    To fix your code I merged the two whiles into a single one and added an if to not call strcat(new_s, tokenptr) if tokenptr is NULL.

    void removePuncNspace(char s[])
    {
        char new_s[50], *tokenptr;
    
        //convert from uppercase to lowercase
        for (int i = 0; i < strlen(s); i++) (char)tolower(s[i]);
    
        //use a cstring function and tokenize s into token pointer and eliminate spaces and punctuation marks
        tokenptr = strtok(s, " ,.?!:;");
    
        //concatenate the first token into a c-string.
        strcpy(new_s,tokenptr);
    
        while (tokenptr != NULL)
        {
            tokenptr = strtok(nullptr, " ,.?!:;"); //tokenize rest of the string
            if (tokenptr != NULL)
                strcat(new_s, tokenptr);
        }
    
        //copy back into the original c - string for the pass by reference.
        strcpy(s, new_s);
    }
    

    P.S: I used the non-secure versions of cstring functions because, for some reason, my compiler doesn't like the secure ones.