Checking for palindrome string in c - c

I am accepting a string as a command line argument. I want to check whether the inputted string is a palindrome or not and print the result. I have written the following code. But its displaying the result 'not palindrome' for all inputs.
#include<stdio.h>
#include<string.h>
int main(int argc, char argv[20]) {
int i;
int l = strlen(argv);
char str[20];
bzero(str, 20);
for(i=0; i<l; i++)
{
str[i] = argv[i+2];
}
int flag;
int len = strlen(str);
for(i=0; i< len/2; i++)
{
if(str[i] == str[len - (i+2)])
{
flag = 0;
}
else
{
flag = 1;
break;
}
}
if(flag == 0)
printf("Palindrome\n");
else
printf("Not a palindrome\n");
}

You could do it in a K&R-style by having two offset iterators in a for-loop:
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main(int argc, char *argv[]) {
assert(argc != 1);
char *text = argv[1];
int len = strlen(text);
int is_palindrome = 1;
int i, j;
for(i = 0, j = len - 1; i < len / 2; i++, j--) {
if(text[i] != text[j]) {
is_palindrome = 0;
break;
}
}
printf("%s a palindrome.\n", is_palindrome ? "is" : "isn't");
return(0);
}
Changes from original:
Changed shift(len >> 1) to division(len / 2) as tenfour suggested.

Updated based on comments:
int is_palindrome(const char *s)
{
const char *t = s + strlen(s);
while (s<t && *s==*--t) s++;
return s>=t;
}
And since the OP wants a version that's not so heavy on pointers:
int is_palindrome(const char *s)
{
size_t i=0, j = strlen(s);
while (i<j && s[i]==s[--j]) i++;
return i>=j;
}
For reference, here's the original buggy version:
int is_palindrome(const char *s)
{
const char *t = s + strlen(s) - 1;
while (s<t && *s++==*t--);
return s>=t;
}

For one thing, your signature for main is off. It should be int main(int argc, char** argv) or int main(int argc, char * argv[]). You're treating a pointer to a string as if it were a string.
When you've changed that, the string you want should be in argv[1] (since argv[0] is some representation of the program name).

There's a good case for using pointers rather than indexes for this:
int is_palindrome(const char *s) {
const char *end = s + strlen(s);
while (end > s) {
--end;
if (*end != *s) return 0;
++s;
}
return 1;
}
If you like short, confusing code, you can re-write that:
int is_palindrome(const char *s) {
const char *end = s + strlen(s);
while (end > s) if (*(--end) != *(s++)) return 0;
return 1;
}
argv isn't a string, it's an array of strings, one for the program name and then one for each argument (usually space-separated in a command line). So to test if the first argument is a palindrome, you're interested in argv[1].
int main(int argc, char **argv) {
if (argc != 2) {
printf("usage: %s <string>\n", argv[0]); // or something
return 1;
}
if (is_palindrome(argv[1])) {
printf("Palindrome\n");
} else {
printf("Not a Palindrome\n");
}
}

The first loop doesn't make sense.
Copying the string to another doesn't make sense.
Just do it and adjust the index:
#include<stdio.h>
#include<string.h>
int main(int argc, char **argv) {
int i;
char * str = argv[1];
int flag;
int len = strlen(str);
for(i=0; i< (len+1)/2; i++)
{
printf("DEBUG: Comparing %c %c\n",str[i], str[len - (i+1)]);
if(str[i] == str[len - (i+1)])
{
flag = 0;
}
else
{
flag = 1;
break;
}
}
if(flag == 0)
printf("Palindrome\n");
else
printf("Not a palindrome\n");
}

No pointers (except the one use for making a copy of the original string).
#include <stdio.h>
#include <string.h>
int main( int argc, char *argv[] )
{
char *s2;
if ( argc != 2 )
return ( 1 ); // not properly invoked
if ( (s2 = strdup( argv[1] )) == NULL )
return ( 2 ); // failed (not likely)
printf( "\"%s\" %s a palindrome.\n", argv[1], strcmp( argv[1], strrev( s2 ) ) ? "is not" : "is" );
free( s2 );
return ( 0 );
}

Related

Displaying the number of occurrences of a letter problem

I have a big problem with my function.
My program (C) is supposed to display the number of occurrences of a letter (Upper or lower case).
The program must handle 2 arguments and work as follows:
./rush2 “Just because I don’t care doesn’t mean I don’t understand!” a
4
I tried this :
#include <stdio.h>
int rush2(int argc, char **argv)
{
int i = 0;
int count_letter = 0;
while (argv[0][i] != '\0') {
if (argv[0][i] == argv[1][0]) {
count_letter = count_letter + 1;
}
i = i + 1;
}
printf("%d", count_letter);
return (count_letter);
}
int main (int ac, char **av)
{
rush2(ac, av);
return (0);
}
My function prints 0 or seg faults.
Please help me.
Try this:
#include <stdio.h>
void rush2(char str[], char c_lower)
{
char c_upper = c_lower - 32;
int i = 0;
int count_letter = 0;
while (str[i] != '\0')
{
if (str[i] == c_lower || str[i] == c_upper)
{
count_letter += 1;
}
i += 1;
}
printf("%d\n", count_letter);
}
int main (int argc, char *argv[])
{
rush2(argv[1], argv[2][0]);
return 0;
}

How would I only print out characters that have not appeared before in an argument?

I'm trying to figure out a way to only print out the characters without getting duplicates in C. Any help is appreciated.
For example, if i pass in 'Hello', i would like 'Helo' returned.
My current code that just prints out the passed in argument:
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
i = 0;
while (argv[1][i] != '\0')
{
putchar(argv[1][i]);
i++;
}
return (0);
}
Edit: preferably without the use of any extra functions / #includes’s
You can try this. You need an array with the length of the max possible ascii code, to handle the seen characters. Hope this helps.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int * seen = calloc(256, sizeof(char));
if (argv[1] == NULL) {
printf("No argument.\n");
return 0;
}
for (int i = 0 ; i < strlen(argv[1]) ; i++) {
if (seen[argv[1][i]] != 1) {
seen[argv[1][i]] = 1;
putchar(argv[1][i]);
}
}
free(seen);
}
You can do like this:
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
char f[128];
unsigned char ch;
if (argc != 2) {
printf("use : ./a.out str");
return -1;
}
for (i = 0; i != sizeof(f); ++i)
f[i] = 0;
for (i = 0; argv[1][i] != '\0'; ++i) {
ch = argv[1][i];
if (f[ch] == 0) {
putchar(ch);
f[ch] = 1;
}
}
return 0;
}

Concatenate first characters from a command line argument in c

I have tried this solution, but don't know why it is giving segmentation fault.
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char st[1000]="";
for (int i=1; i<argc; i++)
{
strcat(st,argv[i][0]);
strcat(st,". ");
}
printf("%s", st);
return 0;
}
A solution without using any string-library functions at all might look like:
#include <stdio.h>
#define ARGV_MAX (5) /* Adjust this to match the maximum number of arguments
to be processed. */
#define RESULT_STR_MAX (3*ARGV_MAX +1) /* The chararacters per arg per maximum arguments
to be processed +1 for the 0-terminator. */
int main(int argc, char *argv[])
{
char st[RESULT_STR_MAX] = "";
size_t string_index = 0;
size_t argv_index = 1; /* Skip argv[0] below as it does not carry an
argument, but the program's name. */
while ((size_t) argc > argv_index
&& RESULT_STR_MAX > string_index /* in fact this or
&& ARGV_MAX >= argv_index) this would do. */
{
st[string_index] = argv[argv_index][0];
string_index++;
st[string_index] = '.';
string_index++;
st[string_index] = ' ';
string_index++;
argv_index++;
}
st[string_index] = '\0'; /* Add the '0'-terminator
to make the char array a "string".
(not necessary as st got initialised to all 0s).*/
if (ARGV_MAX < argv_index)
{
printf("Ignored the last %d argument(s).\n", argc - ARGV_MAX - 1);
}
puts(st);
return 0;
}
Below another approach using strcat():
#include <stdio.h>
#define ARGV_MAX (5) /* Adjust this to match the maximum number of arguments
to be processed. */
#define RESULT_STR_MAX (3*ARGV_MAX +1) /* The chararacters per arg per maximum arguments
to be processed +1 for the 0-terminator. */
int main(int argc, char *argv[])
{
char st[RESULT_STR_MAX] = "";
size_t argv_index = 1; /* Skip argv[0] below as it does not carry an
argument, but the program's name. */
while ((size_t) argc > argv_index
&& ARGV_MAX >= argv_index)
{
strcat(st, (char[2]){argv[argv_index][0]});
strcat(st, ". ");
argv_index++;
}
if (ARGV_MAX < argv_index)
{
printf("Ignored the last %d argument(s).\n", argc - ARGV_MAX - 1);
}
puts(st);
return 0;
}
Change this statement
strcat(st,argv[i][0]);
to
strncat(st, &argv[i][0], 1);
or
strncat(st, argv[i], 1);
In the original statement the function considers the character argv[i][0] as a pointer value. So the call has undefined behavior.
Or you can use a straightforward approach without using string functions. For example
#include <stdio.h>
int main( int argc, char * argv[] )
{
char st[1000];
size_t i = 0;
for ( int j = 1; j < argc; j++ )
{
st[i++] = *argv[j];
if ( j + 1 != argc )
{
st[i++] = ',';
st[i++] = ' ';
}
}
st[i] = '\0';
puts( st );
return 0;
}
try this:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char st[1000]="";
--argc, ++argv;//skip first.
char *p = st;
for (int i = 0; i < argc; i++){
if(i){//between ?
strcpy(p, ". ");
p += 2;
}
*p++ = argv[i][0];//copy one character
}
printf("%s\n", st);
return 0;
}

Efficiently replace a substring in a string

I have made two functions that find a substring index and substitute that substring in the string. I'm glad I jury rigged this at all, given that similar questions previously asked were never answered/marked as closed without any help. Is there a cleaner method?
void destroy_substr(int index, int len)
{
int i;
for (i = index; i < len; i++)
{
string[i] = '~';
}
}
void find_substr_index(char* substr)
{
int i;
int j;
int k;
int count;
int len = strlen(substr);
for (i = 0; i < strlen(string); i++)
{
if (string[i] == substr[0])
{
for(j = i, k = 0; k < len; j++, k++)
{
if (string[j] == substr[k])
{
count++;
}
if (count == len)
destroy_substr((j - len + 1), len);
}
j = 0;
k = 0;
count = 0;
}
}
}
Your code seems like you're trying to re-inventing your own wheel.
By using standard C functions, which is strstr() and memset(), you can achieve the same result as you expected.
#include <stdio.h>
#include <string.h>
char string[] = "foobar foobar foobar";
char substr[] = "foo";
char replace = '~';
int main() {
int substr_size = strlen(substr);
// Make a copy of your `string` pointer.
// This is to ensure we can safely modify this pointer value, without 'touching' the original one.
char *ptr = string;
// while true (infinite loop)
while(1) {
// Find pointer to next substring
ptr = strstr(ptr, substr);
// If no substring found, then break from the loop
if(ptr == NULL) { break; }
// If found, then replace it with your character
memset(ptr, replace, substr_size);
// iIncrement our string pointer, pass replaced substring
ptr += substr_size;
}
printf("%s\n", string);
return 0;
}
How about this:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char string[] = "HELLO hello WORLD world HELLO hello ell";
char substring[] = "ell";
int stringLength = strlen(string);
int substringLength = strlen(substring);
printf("Before: %s\n", string);
if(substringLength <= stringLength)
{
int i;
int j;
for(i = 0, j = stringLength - substringLength + 1; i < j; )
{
if(memcmp(&string[i], substring, substringLength) == 0)
{
memset(&string[i], '~', substringLength);
i += substringLength;
}
else
{
i++;
}
}
}
printf("After: %s\n", string);
return 0;
}
Key ideas are:
You only need to scan the string (stringLength - substringLength) times
You can use functions from string.h to do the comparison and to replace the substring
You can copy the new string in place. If you want to support insertion of longer strings you will need to manage memory with malloc()/realloc(). If you want to support insertion of smaller strings you'll need to advance the pointer to the beginning by the length of the replacement string, copy the rest of the string to that new location, then zero the new end of the string.
#include <stdio.h>
#include <string.h>
#include <err.h>
int main(int argc, char **argv)
{
char *str = strdup("The fox jumps the dog\n");
char *search = "fox";
char *replace = "cat";
size_t replace_len = strlen(replace);
char *begin = strstr(str, search);
if (begin == NULL)
errx(1, "substring not found");
if (strlen(begin) < replace_len)
errx(1, "replacement too long");
printf("%s", str);
memcpy(begin, replace, replace_len);
printf("%s", str);
return 0;
}

replaceString() function in C

I am currently learning C with the book "Programming in C 3rd edition" by Stephen G. Kochan.
The exercise require that I make a function that replaces a character string inside a character string with another character string. So the function call
replaceString(text, "1", "one");
Will replace, if exist, "1" in the character string text with "one".
To fullfill this exercise, you need the functions findString(), insertString() and removeString().
This is the findString() function
int findString (const char source[], const char s[])
{
int i, j;
bool foundit = false;
for ( i = 0; source[i] != '\0' && !foundit; ++i )
{
foundit = true;
for ( j = 0; s[j] != '\0' && foundit; ++j )
if ( source[j + i] != s[j] || source[j + i] == '\0' )
foundit = false;
if (foundit)
return i;
}
return -1;
}
If s[] is inside the string source[], it returns an integer equal to the starting point for s[] inside the string. If it do not find s[] it will return -1.
The insertString() function is as follows
void insertString (char source[], char s[], int index)
{
int stringLength (char string[]);
int j, lenS, lenSource;
lenSource = stringLength (source);
lenS = stringLength (s);
if ( index > lenSource )
return;
for ( j = lenSource; j >= index; --j )
source[lenS + j] = source[j];
for ( j = 0; j < lenS; ++j )
source[j + index] = s[j];
}
This function take three arguments i.e. source[], s[] and index[]. s[] is the string that I would like to put into source[] and index[] is where it should start (e.g. insertString("The son", "per", 4) makes the source string to "The person").
The function includes another function called stringLength(), which purpose is the same at its name. This is stringLength()
int stringLength (char string[])
{
int count = 0;
while ( string[count] != '\0' )
++count;
return count;
}
The removeString() takes three arguments i.e. word, i and count. The function removes a number of characters inside another character string. This function I have not yet been able to make.
Just to sum it up, my question is:
How do i make the function replaceString(), which looks for a word in a character string, and if it is there, then it replaces it with another?
This has really bugged me for some time, and I would really appreciate your help on this.
UPDATE
This is the code I have made so far
// replaceString() program
#include <stdio.h>
#include <stdbool.h>
int findString (char source[], char s[])
{
int i, j;
bool foundit = false;
for ( i = 0; source[i] != '\0' && !foundit; ++i )
{
foundit = true;
for ( j = 0; s[j] != '\0' && foundit; ++j )
if ( source[j + i] != s[j] || source[j + i] == '\0' )
foundit = false;
if (foundit)
return i;
}
return -1;
}
int stringLength (char string[])
{
int count = 0;
while ( string[count] != '\0' )
++count;
return count;
}
void replaceString(char source[], char str1[], char str2[])
{
int findString(char source[], char s[]);
int stringLength(char string[]);
int start;
if ( findString(source, str1) == -1 )
return;
else
{
start = findString(source, str1);
int lenSource = stringLength(source);
int lenStr2 = stringLength(str2);
int counter = lenStr2;
for ( lenSource; lenSource > start + lenStr2; --lenSource )
{
source[lenSource + lenStr2] = source[lenSource];
}
int i = 0;
while ( i != counter )
{
source[start + i] = str2[i];
++i;
}
}
}
int main (void)
{
void replaceString(char source[], char str1[], char str2[]);
char string[] = "This is not a string";
char s1[] = "not";
char s2[] = "absolutely";
printf ("Before: \n %s \n\n", string);
replaceString(string, s1, s2);
printf ("After: \n %s \n\n", string);
return 0;
}
This code gives the following output:
Before:
This is not a string
After:
This is absolutelyng
As you can see, I have not included the removeString function(), as I could not get that function working properly. Where is the error in my program?
for starters, your string's length is fixed. so if the "destination" is longer than "source", then it won't work. insert string needs to pass in a pointer, then you can allocate a string on the heap that is long enough to contain length(source)-length(remove) +length(add), and return that pointer
Say your replaceString() args are (char source[], char s1[], char replacement[])
You need to use findString() to find s1 in source. If it finds it, given the position of s1, use removeString() to remove that string and then insertString() to insert replacement into that position.
I am also a newbie in programming. I came across this same exercise some days ago and just solved it today.
This is my code.
/* Programme to replace a string by using find, remove and insert
functions ex9.8.c */
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MAX 501
// Function prototypes
void read_Line (char buffer[]);
int string_Length (char string[]);
int find_String (char string1[], char string2[]);
void remove_String (char source[], int start, int number);
void insert_String (char source[], int start, char input[]);
void replace_String (char origString[], char targetString[], char substString[]);
bool foundFirstCharacter = false;
int main(void)
{
printf("This is a programme to replace part of a string.\n");
printf("It can only handle up to 500 characters in total!\n");
char text[MAX];
bool end_Of_Text = false;
int textCount = 0;
printf("\nType in your source text.\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(text);
if (text[0] == '\0')
{
end_Of_Text = true;
}
else
{
textCount += string_Length(text);
}
break;
}
// Declare variables to store seek string parameters
int seekCount = 0;
char seekString[MAX];
printf("\nType in the string you seek.\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(seekString);
if (seekString[0] == '\0')
{
end_Of_Text = true;
}
else
{
seekCount += string_Length(seekString);
}
break;
}
// Declare variables to store replacement string parameters
int replCount = 0;
char replString[MAX];
printf("\nType in the replacement string.\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(replString);
if (replString[0] == '\0')
{
end_Of_Text = true;
}
else
{
replCount += string_Length(replString);
}
break;
}
// Call the function
replace_String (text, seekString, replString);
return 0;
}
// Function to get text input
void read_Line (char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
++i;
}
while (character != '\n');
buffer[i - 1] = '\0';
}
// Function to determine the length of a string
int string_Length (char string[])
{
int len = 0;
while (string[len] != '\0')
{
++len;
}
return len;
}
// Function to find index of sub-string
int find_String (char string1[], char string2[])
{
int i, j, l;
int start;
int string_Length (char string[]);
l = string_Length(string2);
for (i = 0, j = 0; string1[i] != '\0' && string2[j] != '\0'; ++i)
{
if (string1[i] == string2[j])
{
foundFirstCharacter = true;
++j;
}
else
{
j = 0;
}
}
if (j == l)
{
start = i - j + 1;
return start;
}
else
{
return j - 1;
}
}
// Function to remove characters in string
void remove_String (char source[], int start, int number)
{
int string_Length (char string[]);
int i, j, l;
char ch = 127;
l = string_Length(source);
j = start + number;
for (i = start; i < j; ++i)
{
if (i >= l)
{
break;
}
source[i] = ch;
}
//printf("\nOutput: %s\n", source);
}
// Function to insert characters in string
void insert_String (char source[], int start, char input[])
{
int string_Length (char string[]);
int i, j, k, l, m;
int srcLen;
int inpLen;
int totalLen;
int endInsert;
srcLen = string_Length(source);
inpLen = string_Length(input);
// Declare buffer array to hold combined strings
totalLen = srcLen + inpLen + 3;
char buffer[totalLen];
// Copy from source to buffer up to insert position
for (i = 0; i < start; ++i)
buffer[i] = source[i];
// Copy from input to buffer from insert position to end of input
for (j = start, k = 0; k < inpLen; ++j, ++k)
buffer[j] = input[k];
endInsert = start + inpLen;
for (m = start, l = endInsert; m <= srcLen, l < totalLen; ++m, ++l)
buffer[l] = source[m];
buffer[l] = '\0';
printf("\nOutput: %s\n", buffer);
}
// Function to replace string
void replace_String (char origString[], char targetString[], char substString[])
{
// Function prototypes to call
void read_Line (char buffer[]);
int string_Length (char string[]);
int find_String (char string1[], char string2[]);
void remove_String (char source[], int start, int number);
void insert_String (char source[], int start, char input[]);
// Search for target string in source text first
int index;
index = find_String (origString, targetString);
if (index == -1)
{
printf("\nTarget string not in text. Replacement not possible!\n");
exit(999);
}
// Remove found target string
int lengthTarget;
lengthTarget = string_Length(targetString);
remove_String(origString, index - 1, lengthTarget);
// Insert replacement string
insert_String(origString, index, substString);
}

Resources