When I run this function I don't get a return value of 1 or 0. Im not sure why, I'm new to pointers and any type of help/tips would be greatly appreciated.
int isPalindrome (char * str)
{
char def[SIZE];
int length = strlen(str);
for(int count; count <= length; count++ ){
def[count] = str[count];
}
int c;
char *begin, *end, temp;
begin = str;
end = str;
for (c = 0; c < length - 1; c++)
end++;
for (c = 0; c < length/2; c++)
{
temp = *end;
*end = *begin;
*begin = temp;
begin++;
end--;
}
for(int count2; count2 <= length; count2++){
if(str[count2] != def[count2]){
return 0;
}
return 1;
}
}
The function is called with..
if(isPalindrome(arr) == 1)
printf ("\nIs a palindrome.\n\n");
To check if a string is a palindrome you create a reversed string, after first allocating enough room for all chars, by looping through the original one and changing the order. you can then use a strcmp to check if the reversed and original string are the same.
int isPalindrome (char * str)
{
int length = strlen(str);
char* reversed = malloc(sizeof(char)*length); //we allocate enough space for length chars
for(int i = 0; i < length; i++) {
reversed[i] = str[length-1-i]; //populate reversed with the chars in str but in the reversed order
}
if(strcmp(str,reversed) == 0) //strcmo(a,b) return 0 if they are equal
{
free(reversed); //deallocate the space for reversed
return 1;
}
free(reversed); //deallocate the space for reversed
return 0;
}
In these loops
for(int count; count <= length; count++ ){
def[count] = str[count];
}
and
for(int count2; count2 <= length; count2++){
if(str[count2] != def[count2]){
return 0;
}
return 1;
}
there are used uninitialized variables count and count2. So the function has undefined behavior.
Pay attention the the function is declared and defined incorrectly. It is too complicated and uses a magic number SIZE.
Also you should use the type size_t instead of the type int because the return type of the function strlen is size_t and in general an object of the type int can not accommodate an object of the type size_t.
There is no need to create an auxiliary array and change the original string to check whether the given string is a palindrome. Moreover the parameter shall be defined with the qualifier const. Otherwise you will be unable to check whether a string literal is a palindrome because modifying a string literal invokes undefined behavior.
Also if you are trying to use pointers then there is no need to use also indices in loops.
The function can be defined much simpler.
Here you are.
#include <stdio.h>
#include <string.h>
_Bool isPalindrome( const char *s )
{
const char *first = s, *last = s + strlen( s );
if ( first != last )
{
while ( first < --last && *first == *last ) ++first;
}
return !( first < last );
}
int main(void)
{
char *s1 = "121";
printf ( "\"%s\" is %s%s\n", s1, isPalindrome( s1 ) ? "a " : "not ", "palindrome." );
char *s2 = "1221";
printf ( "\"%s\" is %s%s\n", s2, isPalindrome( s2 ) ? "a " : "not ", "palindrome." );
return 0;
}
The program output is
"121" is a palindrome.
"1221" is a palindrome.
As you can see the function uses only pointers and neither index.
Your program has multiple problems. Lets see them one by one:
for(int count; count <= length; count++ ){
^^^^
def[count] = str[count];
}
You are not initialising count, you are just declaring it. Without any initial value count will just be some garbage. To fix this:
for(int count = 0; count <= length; count++ ){
def[count] = str[count];
}
Please note that older C versions require you to declare all variables in the beginning of a function block as far as I remember. So this is anyways wrong.
Next, your palindrome logic is incorrect. You are just swapping characters between begin and end.
All you have to do is check while iterating HALF THE STRING is whether the characters from the beginning equal to the end.
for (c = 0; c < length/2; c++)
{
// Check if "begin" equals to the current "end"
if (*begin != *end)
{
return 0;
}
// Move "begin" forward and "end" backwards
begin++;
end--;
}
Here is your complete function in working condition:
int isPalindrome(char* str)
{
int length = strlen(str);
int c;
char *begin, *end;
begin = str;
// Why use the below for loop when you can directly move end to the end?
end = str + length - 1;
// for (c = 0; c < length - 1; c++)
// end++;
for (c = 0; c < length / 2; c++) {
if (*begin != *end) {
return 0;
}
begin++;
end--;
}
return 1;
}
Related
I am trying to reverse this C-string and I thought I did it correct but the string remains the same when it passes through the function.
#include <stdio.h>
char* reverse(char* string);
int main(int arc, char* argv[]) {
char word[] = "Hello World!";
printf("%s\n", word);
printf("%s\n", reverse(word));
return 0;
}
char* reverse(char* string) {
int i, j, n = 0;int len = 0;char temp;
//Gets string length
for (i = 0; *(string + i) != '0'; i++) {
len++;
}
//Reverses string
for (j = len - 1; j >= 0; j--) {
temp = string[n];
string[n] = string[j];
string[j] = temp;
n++;
}
return &string[0];
}
Expected output:
Hello World!
!dlroW olleH
For starters there is a typo
for (i = 0; *(string + i) != '0'; i++) {
You have to write
for (i = 0; *(string + i) != '\0'; i++) {
That is instead of the character '0' you have to use '\0' or 0.
In this for loop
for (j = len - 1; j >= 0; j--) {
temp = string[n];
string[n] = string[j];
string[j] = temp;
n++;
}
the string is reversed twice.:) As a result you get the same string.
The function can look for example the following way
char * reverse(char *string)
{
//Gets string length
size_t n = 0;
while ( string[n] != '\0' ) ++n;
//Reverses string
for ( size_t i = 0, m = n / 2; i < m; i++ )
{
char temp = string[i];
string[i] = string[n - i - 1];
string[n - i - 1] = temp;
}
return string;
}
Or the function can be defined the following way using pointers
char * reverse(char *string)
{
//Gets string length
char *right = string;
while ( *right ) ++right;
//Reverses string
if ( right != string )
{
for ( char *left = string; left < --right; ++left )
{
char temp = *left;
*left = *right;
*right = temp;
}
}
return string;
}
The same approach of the function implementation without using pointers can look the following way
char * reverse(char *string)
{
//Gets string length
size_t n = 0;
while ( string[n] != '\0' ) ++n;
//Reverses string
if ( n != 0 )
{
for ( size_t i = 0; i < --n; ++i )
{
char temp = string[i];
string[i] = string[n];
string[n] = temp;
}
}
return string;
}
Here is one more solution. I like it most of all. Tough it is inefficient but it is not trivial as the early presented solutions. It is based on an attempt of one beginner to write a function that reverses a string.:)
#include <stdio.h>
#include <string.h>
char *reverse( char *string )
{
size_t n = 0;
while (string[n]) ++n;
while (!( n < 2 ))
{
char c = string[0];
memmove( string, string + 1, --n );
string[n] = c;
}
return string;
}
int main( void )
{
char string[] = "Hello World!";
puts( string );
puts( reverse( string ) );
}
The program output is
Hello World!
!dlroW olleH
Of course instead of manually calculating the length of a string in all the presented solutions there could be used standard string function strlen declared in the header <string.h>.
The problem is that the input word[] is an array, which decays to a pointer when passed to the reverse function.
In the for loop, instead of using n to keep track of the position, I suggest you to use i and j to keep track of the start and end of the string, and increment and decrement them respectively and use strlen to get the length of string.
Also, as it is mentionned above by #Vlad from Moscow, in your for loop you are checking for 0 but it should be \0 which is the null character.
Please find down below an update of your posted code that is generating the expected result :
#include <stdio.h>
char* reverse(char* string);
int main(int arc, char* argv[]) {
char word[] = "Hello World!";
printf("%s ", word);
printf("%s\n", reverse(word));
return 0;
}
char* reverse(char* string) {
int i, j;
char temp;
int len = strlen(string);
//Reverses string
for (i = 0, j = len - 1; i < j; i++, j--) {
temp = string[i];
string[i] = string[j];
string[j] = temp;
}
return &string[0];
}
The output is as expected: Hello World! !dlroW olleH
Aditionnally, you can include the header <string.h> or explicitly
provide a declaration for 'strlen' to avoid the warning that indicate to implicitly declaring library function 'strlen' with type 'unsigned long (const char *)' [-Wimplicit-function-declaration]
I was trying to write a program that reverses its input a line at a time. I thought I had done it successfully, however it sometimes doesn't give the desirable output (this happens when I put an input with a smaller length than the one I put previously). I am new to this and I was wondering what can I do to solve this issue.
Program:
#include <stdio.h>
#define MAXLINE 1000
void reverse(char o[], char l[]);
int mgetline(char line[]);
int main(void){
int len;
char line[MAXLINE];
char rev[MAXLINE];
while((len = mgetline(line)) > 0){
reverse(rev, line);
printf("%s\n",rev);
}
return 0;
}
int mgetline(char s[])
{
int c,i;
for(i = 0; ((c=getchar())!=EOF) && (c!='\n'); ++i)
s[i] = c;
if (c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
void reverse(char revi[], char liner[])
{
int i, c, j;
for(i=0;liner[i]!='\0';++i)
;
--i;
if(liner[i]=='\n')
--i;
for(j=0; j<=i ; ++j){
c = i - j;
revi[j] = liner[c];
}
--j;
}
Since you not terminating the revi string at the end, therefore it will print the leftout characters from the previous result if the new input is smaller. Fix it by adding this
revi[j] = '\0';
at the end of the reverse function and delete that last --j;.
The function reverse does not build a string that is it does not append the terminating zero '\0' to the result string.
The second parameter of the function should have the qualifier const because it is not changed in the function.
As all standard C string functions this function should return pointer to the result string.
And it is better to name the function like reverse_copy instead of reverse because the name reverse is usually used when a container is reversed "in place".
It can look the following way
char * reverse_copy( char revi[], const char liner[] )
{
size_t n = 0;
while ( liner[n] ) ++n;
if ( n != 0 && liner[n-1] == '\n' ) --n;
size_t i = 0;
while ( n != 0 ) revi[i++] = liner[--n];
revi[i] = '\0';
return revi;
}
I have created a function that should find the numerical position of the first character of a substring in a larger string. I am having some problems with the output and I am not too sure why. These problems include -1 being returned every single time instead of the integer position of the substring. I have debugged and cannot trace where the function goes wrong.
This is how the function should perform: If my string is "The dog was fast" and I am searching for the substring "dog", the function should return 4. Thanks to chqrlie for help with the loop.
Here is the function:
int findSubString(char original[], char toFind[]) {
size_t i, j;
int originalLength = 0;
int toFindLength = 0;
originalLength = strlen(original) + 1;
toFindLength = strlen(toFind) + 1;
for (i = 0; i < toFindLength + 1; i++) {
for (j = 0; j < originalLength + 1; j++) {
if (toFind[j] == '\0') {
return i;
}
if (original[i + j] != toFind[j]) {
break;
}
}
if (original[i] == '\0') {
return -1;
}
}
}
The function parameters cannot be modified, this is a requirement. Any help appreciated!
These statements inside the loops
if (toFind[j] == '\0') {
return i;
}
results in undefined behavior because the string toFind can be shorter than the string original.
The same is valid for this loop
if (original[i + j] != toFind[j]) {
break;
}
because i + j can be greater than the length of the string original.
And there is no need to scan all characters of the string original if you are going to find a substring inside it.
Also you should check whether the length of the string original is not less than the length of the string toFind.
If you want to find only the first character of the string toFind in the string original it is enough to use standard C function strchr. If you want to find the whole string toFind in the string original then you could use another C standard function strstr.
If you want to write the function yourself to find a string in other string then it can look for example the following way
I declared the function like
long long int findSubString( const char original[], const char toFind[] );
however you can write its declaration as you like for example like
int findSubString( char original[], char toFind[] );
But in this case you should declare function local variable success like
int success = -1;
and output the result using format specifier "%d" instead of "%lld".
Here you are.
#include <stdio.h>
#include <string.h>
#include <stddef.h>
long long int findSubString( const char original[], const char toFind[] )
{
size_t n = strlen( original );
size_t m = strlen( toFind );
long long int success = -1;
if ( !( n < m ) )
{
n = n - m + 1;
for ( size_t i = 0; success == -1 && i < n; i++ )
{
size_t j = 0;
while ( j < m && original[i+j] == toFind[j] ) j++;
if ( j == m ) success = i;
}
}
return success;
}
int main(void)
{
printf( "%lld\n", findSubString( "The dog was fast", "dog" ) );
return 0;
}
Its output is
4
Your loops are reversed. The outer loop should walk positions from zero to originalLength, inclusive; the nested loop should walk positions from zero to toFindLength, inclusive.
Both originalLength and toFindLength should be set to values returned by strlen, not strlen plus one, because null terminator position is not a good start.
Finally, you are returning -1 from inside the outer loop. This is too early - you should be returning -1 only after you are done with the outer loop as well.
Your loop counter tests are incorrect: wrong upper limit and the limits are off by one. Note that the tests are actually not necessary as you exit both loops when hitting the '\0' terminators.
Here is a simpler version:
int findSubString(const char *original, const char *toFind) {
for (size_t i = 0;; i++) {
for (size_t j = 0;; j++) {
if (toFind[j] == '\0') {
return i;
}
if (original[i + j] != toFind[j]) {
break;
}
}
if (original[i] == '\0') {
return -1;
}
}
}
There is a small advantage at computing the string lengths to reduce the number of comparisons in pathological cases such as findSubString("aaaaaaaaaaa", "aaaaaaaaaaaa");
int findSubString(const char *original, const char *toFind) {
size_t originalLength = strlen(original);
size_t toFindLength = strlen(toFind);
if (toFindLength <= originalLength) {
for (size_t i = 0; i <= originalLength - toFindLength; i++) {
for (size_t j = 0;; j++) {
if (toFind[j] == '\0') {
return i;
}
if (original[i + j] != toFind[j]) {
break;
}
}
}
}
return -1;
}
I have created a function that should find the numerical position of the first character of a substring in a larger string. I am having some problems with the output and I am not too sure why. These problems include -1 being returned every single time instead of the integer position of the substring. I have debugged and cannot trace where the function goes wrong.
This is how the function should perform: If my string is "The dog was fast" and I am searching for the substring "dog", the function should return 4. Thanks to chqrlie for help with the loop.
Here is the function:
int findSubString(char original[], char toFind[]) {
size_t i, j;
int originalLength = 0;
int toFindLength = 0;
originalLength = strlen(original) + 1;
toFindLength = strlen(toFind) + 1;
for (i = 0; i < toFindLength + 1; i++) {
for (j = 0; j < originalLength + 1; j++) {
if (toFind[j] == '\0') {
return i;
}
if (original[i + j] != toFind[j]) {
break;
}
}
if (original[i] == '\0') {
return -1;
}
}
}
The function parameters cannot be modified, this is a requirement. Any help appreciated!
These statements inside the loops
if (toFind[j] == '\0') {
return i;
}
results in undefined behavior because the string toFind can be shorter than the string original.
The same is valid for this loop
if (original[i + j] != toFind[j]) {
break;
}
because i + j can be greater than the length of the string original.
And there is no need to scan all characters of the string original if you are going to find a substring inside it.
Also you should check whether the length of the string original is not less than the length of the string toFind.
If you want to find only the first character of the string toFind in the string original it is enough to use standard C function strchr. If you want to find the whole string toFind in the string original then you could use another C standard function strstr.
If you want to write the function yourself to find a string in other string then it can look for example the following way
I declared the function like
long long int findSubString( const char original[], const char toFind[] );
however you can write its declaration as you like for example like
int findSubString( char original[], char toFind[] );
But in this case you should declare function local variable success like
int success = -1;
and output the result using format specifier "%d" instead of "%lld".
Here you are.
#include <stdio.h>
#include <string.h>
#include <stddef.h>
long long int findSubString( const char original[], const char toFind[] )
{
size_t n = strlen( original );
size_t m = strlen( toFind );
long long int success = -1;
if ( !( n < m ) )
{
n = n - m + 1;
for ( size_t i = 0; success == -1 && i < n; i++ )
{
size_t j = 0;
while ( j < m && original[i+j] == toFind[j] ) j++;
if ( j == m ) success = i;
}
}
return success;
}
int main(void)
{
printf( "%lld\n", findSubString( "The dog was fast", "dog" ) );
return 0;
}
Its output is
4
Your loops are reversed. The outer loop should walk positions from zero to originalLength, inclusive; the nested loop should walk positions from zero to toFindLength, inclusive.
Both originalLength and toFindLength should be set to values returned by strlen, not strlen plus one, because null terminator position is not a good start.
Finally, you are returning -1 from inside the outer loop. This is too early - you should be returning -1 only after you are done with the outer loop as well.
Your loop counter tests are incorrect: wrong upper limit and the limits are off by one. Note that the tests are actually not necessary as you exit both loops when hitting the '\0' terminators.
Here is a simpler version:
int findSubString(const char *original, const char *toFind) {
for (size_t i = 0;; i++) {
for (size_t j = 0;; j++) {
if (toFind[j] == '\0') {
return i;
}
if (original[i + j] != toFind[j]) {
break;
}
}
if (original[i] == '\0') {
return -1;
}
}
}
There is a small advantage at computing the string lengths to reduce the number of comparisons in pathological cases such as findSubString("aaaaaaaaaaa", "aaaaaaaaaaaa");
int findSubString(const char *original, const char *toFind) {
size_t originalLength = strlen(original);
size_t toFindLength = strlen(toFind);
if (toFindLength <= originalLength) {
for (size_t i = 0; i <= originalLength - toFindLength; i++) {
for (size_t j = 0;; j++) {
if (toFind[j] == '\0') {
return i;
}
if (original[i + j] != toFind[j]) {
break;
}
}
}
}
return -1;
}
I feel like I've got it almost down, but for some reason my second test is coming up with a shorter palindrome instead of the longest one. I've marked where I feel the error may be coming from, but at this point I'm kind of at a loss. Any direction would be appreciated!
#include <stdio.h>
#include <string.h>
/*
* Checks whether the characters from position first to position last of the string str form a palindrome.
* If it is palindrome it returns 1. Otherwise it returns 0.
*/
int isPalindrome(int first, int last, char *str)
{
int i;
for(i = first; i <= last; i++){
if(str[i] != str[last-i]){
return 0;
}
}
return 1;
}
/*
* Find and print the largest palindrome found in the string str. Uses isPalindrome as a helper function.
*/
void largestPalindrome(char *str)
{
int i, last, pStart, pEnd;
pStart = 0;
pEnd = 0;
int result;
for(i = 0; i < strlen(str); i++){
for(last = strlen(str); last >= i; last--){
result = isPalindrome(i, last, str);
//Possible error area
if(result == 1 && ((last-i)>(pEnd-pStart))){
pStart = i;
pEnd = last;
}
}
}
printf("Largest palindrome: ");
for(i = pStart; i <= pEnd; i++)
printf("%c", str[i]);
return;
}
/*
* Do not modify this code.
*/
int main(void)
{
int i = 0;
/* you can change these strings to other test cases but please change them back before submitting your code */
//str1 working correctly
char *str1 = "ABCBACDCBAAB";
char *str2 = "ABCBAHELLOHOWRACECARAREYOUIAMAIDOINEVERODDOREVENNGGOOD";
/* test easy example */
printf("Test String 1: %s\n",str1);
largestPalindrome(str1);
/* test hard example */
printf("\nTest String 2: %s\n",str2);
largestPalindrome(str2);
return 0;
}
Your code in isPalindrome doesn't work properly unless first is 0.
Consider isPalindrome(6, 10, "abcdefghhgX"):
i = 6;
last - i = 4;
comparing str[i] (aka str[6] aka 'g') with str[last-i] (aka str[4] aka 'e') is comparing data outside the range that is supposed to be under consideration.
It should be comparing with str[10] (or perhaps str[9] — depending on whether last is the index of the final character or one beyond the final character).
You need to revisit that code. Note, too, that your code will test each pair of characters twice where once is sufficient. I'd probably use two index variables, i and j, set to first and last. The loop would increment i and decrement j, and only continue while i is less than j.
for (int i = first, j = last; i < j; i++, j--)
{
if (str[i] != str[j])
return 0;
}
return 1;
In isPalindrome, replace the line if(str[i] != str[last-i]){ with if(str[i] != str[first+last-i]){.
Here's your problem:
for(i = first; i <= last; i++){
if(str[i] != str[last-i]){
return 0;
}
}
Should be:
for(i = first; i <= last; i++, last--){
if(str[i] != str[last]){
return 0;
}
}
Also, this:
for(last = strlen(str); last >= i; last--){
Should be:
for(last = strlen(str) - 1; last >= i; last--){