Character Pointers with Palindrome Checker in C - c

This is code I wrote that checks if a string is a palindrome or not. I need to revise this code so that it uses character pointers in it. Could someone give me some suggestions/tips...or show me how to do that? Thanks
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(){
char string1[20];
int i, length;
int flag = 0;
printf("Enter a string: ");
scanf("%s", string1);
length = strlen(string1);
for(i=0;i < length ;i++){
if(toupper(string1[i]) != toupper(string1[length-i-1])){
flag = 1;
break;
}
}
if (flag)
printf("%s is not a palindrome \n\n", string1);
else
printf("%s is a palindrome \n", string1);
return 0;
}

In your code you use string1[i] to access the current element from the beginning of the string, and string1[length-i-1] to access the current element from the end of the string. You could create two pointers, pb and pe, and then move them toward each other.
To define pointers, use this:
char *pb = &string1[0]; // Or just string1, compiler will convert it to pointer
char *pe = &string1[length-1];
To advance the pointers toward each other, use pb++ and pe--.
To see if the pointers have not crossed each other , check that pb < pe. Currently, your program checks the string twice; there's no need to do that - you can stop as soon as pe becomes less than or equal to the pb.
To access the character pointed to by the current pointer, use
toupper(*pb) != toupper(*pe)
You can combine the check with advancing the pointers, like this:
toupper(*pb++) != toupper(*pe--)
Note: it is not safe to use %s, because when users enter more characters than fits in your string1 buffer overrun results. You should specify the length of the buffer, like this:
scanf("%19s", string1); // Leave one char for null terminator

I'm not sure I completely understand the question, but I think this answers it. You actually are using character pointers. char string1[20] is the same as char *string1. The difference is that you've basically assigned the pointer to a block of memory. You could access the string in this way.
char string[20] = "foo";
printf("%c\n", string[0]); // will print 'f'
printf("%c\n", *string); // will also print 'f'
printf("%c\n", string[1]); // will print the first 'o'
printf("%c\n", *(string + 1)); // will also print the first 'o'

with char * it goes like this
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
char string1[20];
int i, length;
int flag = 0;
printf("Enter a string: ");
scanf("%s", string1);
length = strlen(string1);
char *start=string1;
char *end=&string1[length-1];
//only check upto half
for(i=0;i <= (length-1)/2 ;i++)
{
if(toupper(*(start+i)) != toupper(*(end-i)))
{
flag = 1;
break;
}
}
if (flag)
printf("%s is not a palindrome \n\n", string1);
else
printf("%s is a palindrome \n", string1);
return 0;
}

cant we just copy the original string to another array, and then use strrev() to reverse the copied string and then finally compare the original string with the reversed string?
Like this
1.get new string
2.copy string to new array
3.reverse the copied string using strrev
4.use strcmp to check if both are same or not?
this seemed easier
(i am a beginner so please correct me if i am wrong)

Related

Removing a character from string in C with a dynamic string

So, I want to create a function which creates and returns a dynamic string based on a string s without characters c. Now, I want to be able to remove all of the desired characters, no matter the case. Additionally, the original string entered by the user should remain unchanged. Here's my attempt, it keeps telling me about an error at line 12 (noted in the comments).
One more thing: I'm not sure if I wrote the remove function well, I think it should work? All of the pointers confused me a little bit.
#include <stdio.h>
#include <stdlib.h>
char * remove(char *s, char c);
int strlen(char *s);
int main() {
char s[16], c, n[16];
printf("Please enter string: ");
scanf("%s", s);
printf("Which character do you want to remove? ");
scanf("%c", &c);
n = remove(s, c); // Place the new string in n so I wouldn't change s (the error)
printf("The new string is %s", n);
return 0;
}
int strlen(char *s)
{
int d;
for (d = 0; s[d]; d++);
return d;
}
char * remove(char *s, char c) {
char str[16], c1;
int i;
int d = strlen(s);
str = (char)calloc(d*sizeof(char)+1);
// copying s into str so I wouldn't change s, the function returns str
for (i = 0; i < d; i++) {
while(*s++ = str++);
}
// if a char in the user's string is different than c, place it into str
for (i = 0; i < d; i++) {
if (*(s+i) != c) {
c1 = *(s+i);
str[i] = c1;
}
}
return str; // the function returns a new string str without the char c
}
You declared n as 16-element array of char type:
char n[16];
So you cannot do:
n = remove(s, c);
because n is a const pointer.
Also your remove function returns a pointer to its local array, which gets destroyed as soon as your function returns. Better declare remove as
void remove(char *to, char *from, char var);
and pass n as the first parameter.
There ware so many mistakes in your program it was easier to rewrite and show you, with added comments. Note that scanf("%s... will accept only a single word, not a sentence (it stops at the first whitespace). And note that the newline will be left in the input buffer for scanf("%c... to read unless you add a space, as advised.
#include <stdio.h>
void c_remove(char *n, char *s, char c) { // renamed because remove() is predefined
while (*s) { // no need for strlen()
if (*s != c) // test if char is to be removed
*n++ = *s; // copy if not
s++; // advance source pointer
}
*n = '\0'; // terminate new string
}
int main(void) { // correct signature
char s[16], c, n[16];
printf("Please enter string: ");
scanf("%s", s);
printf("Which character do you want to remove? ");
scanf(" %c", &c); // the space before %c cleans off whitespace
c_remove(n, s, c); // pass target string pointer too
printf("The new string is %s", n);
return 0;
}
Program sessions:
Please enter string: onetwothree
Which character do you want to remove? e
The new string is ontwothr
Please enter string: onetwothree
Which character do you want to remove? o
The new string is netwthree

char pointers: invalid conversion from 'char*' to 'char'?

I cut out all the unnecessary code so no one gets too bored with my question... So I cant get the char array to work! on the last few lines of
*whatname = guyname;
*whatlastname = lastname;
I get an error saying invalid conversion from 'char*' to 'char'. Help would be much appreciated!
#include <stdio.h>
#include <ctype.h>
#include <string.h>
void getname(char *whatname, char *whatlastname);
int main()
{
int option = 0;
char guyname = 'x';
char lastname = 'x';
bool name_entered = false;
do{
printf("1. Enter name.\n");
printf("2. Enter exam scores.\n");
printf("3. Display average exam scores. \n");
printf("4. Display summary. \n");
printf("5. Quit. \n");
scanf("%i", &option);
if( option == 1 )
{
name_entered = true;
getname(&guyname, &lastname);
}
else if( option == 4 )
{
{
printf("%s %s based on your exam scores of \n",guyname, lastname);
}
else
{
printf("Please enter your name in option 1 and you exam scores in option 2 before continuing.\n");
}
}
else if( option == 5 )
{
printf(" Come back with a better grade next time.");
break;
}
}while (!(option >5 || option <1));
return 0;
}
void getname (char *whatname, char *whatlastname)
{
char guyname[32];
char lastname[32];
printf("Enter your first and last name : ");
scanf("%s %s", &guyname, &lastname);
guyname[0] = toupper( guyname[0] );
int len = strlen(guyname);
for(int i=1; i<len ; i++)
{
guyname[i] = tolower( guyname[i]);
}
lastname[0] = toupper( lastname[0] );
int len1 = strlen(lastname);
for(int k=1; k<len1; k++)
{
lastname[k]= tolower( lastname[k]);
}
printf("Your name is %s %s\n", guyname, lastname);
*whatname = guyname;
*whatlastname = lastname;
}
Dealing with char, char*, and char [] in C is a little confusing in the beginning.
Take a look at the following statements:
char str1[] = "abcd";
char const* str2 = "xyz";
char* cp = str1;
char c = *cp;
The first statement and the second statement are identical in their behavior. After the first statement is executed, str1 points to a location that contains 4 characters, in consecutive order. If you think of the memory locations for the string, you might see something like:
+---+---+---+---+
| a | b | c | d |
+---+---+---+---+
str1 points to the address where a is stored. There is a similar arrangement for storing the string "xyz" and str2 points to the address where x is stored.
In the third statement, you are creating cp and making it point where str1 is pointing. After that statement, both cp and str1 point to the same string - "abcd".
*cp evaluates to the character that exists at the address that cp points to. In this case, it will be 'a'.
In the fourth statement, you are initializing c with 'a', the character that exists at the address pointed to by cp.
Now, if you try a statement
*cp = str2;
it is a compiler error. *cp simply dereferences the address of cp. You can put a char at that location, not str2, which is a char*.
You can execute
*cp = *str2;
After that, the objects in the memory that str1 and cp point to will look like:
+---+---+---+---+
| x | b | c | d |
+---+---+---+---+
If you want to copy the string from the address pointed to by str1 to the address pointed to by cp, you can use the standard library function strcpy.
strcpy(cp, str2);
You have to be careful about using strcpy because you have to have enough valid memory to copy to. In this particular example, if you tried
char str3[2];
strcpy(str3, cp);
you will get undefined behavior since there isn't enough memory in str3 to be able to copy "abcd".
Hope that made sense.
Here's a modified version of your code that should work:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
void getname(char *whatname, char *whatlastname);
int main()
{
int option = 0;
char guyname[32];
char lastname[32];
bool name_entered = false;
do{
printf("1. Enter name.\n");
printf("2. Enter exam scores.\n");
printf("3. Display average exam scores. \n");
printf("4. Display summary. \n");
printf("5. Quit. \n");
scanf("%i", &option);
if( option == 1 )
{
name_entered = true;
getname(guyname, lastname);
}
else if( option == 5 )
{
printf(" Come back with a better grade next time.");
break;
}
}while (!(option >5 || option <1));
return 0;
}
void getname (char *whatname, char *whatlastname)
{
char guyname[32];
char lastname[32];
printf("Enter your first and last name : ");
scanf("%31s %31s", guyname, lastname);
guyname[0] = toupper( guyname[0] );
int len = strlen(guyname);
for(int i=1; i<len ; i++)
{
guyname[i] = tolower( guyname[i]);
}
lastname[0] = toupper( lastname[0] );
int len1 = strlen(lastname);
for(int k=1; k<len1; k++)
{
lastname[k]= tolower( lastname[k]);
}
printf("Your name is %s %s\n", guyname, lastname);
strcpy(whatname, guyname);
strcpy(whatlastname,lastname);
}
lot of things wrong here. You need to think about where the two string are going to be stored.
You are trying to return variable on the stack of getname - even if you fix the C code that wont work.
a) getname needs to be getname(char**, char**)
b) whatname and whatLastname need to be char *
c) call getname with (&whatname &whatLastName)
d) strdup the strings in getname into the two params (*whatname,...)
You have a pair of values in the main which are single characters.
You're passing in pointers to those characters, then dereferencing them (which gives you single characters again), then trying to assign character pointers to them. That definitely isn't going to work.
Even if you did,
whatname = guyname;
whatlastname = lastname;
which would be type-correct, it wouldn't do what you seem to want, which is to change the values in the calling function. It would only change the values of the argument variables in the subroutine.
If you're trying to return two strings found in the subroutine, change the calling code's variables to:
char *guyname = "x";
char *lastname = "x";
and change the function arguments to
void getname (char **whatname, char **whatlastname)
Then your assignment will be type-correct, and will change the pointers in the calling function.
There shouldn't be & in scanf of string.
first of all, using * on a pointer will dereference it (you did it on the last two lines)
secondly, you are sending to the function a pointer to a single char, not an array of chars so if you will write to its memory you will write on some other variable's memory.
What you should have done is declaring guysname and lastname as char arrays
char guysname[32];
and in your function just read your input directly into the parameters you recieve:
scanf("%s %s", whatname, whatlastname);
replace all instances of guysname and lastname for whatname and whatlastname. get rid of the last lines.
If you want to keep the char arrays inside the function anyway, just use
strcpy(whatname,guysname)
and the same for the last name.
You can't assign a char value to a char pointer, and you can't dereference an Lvalue.
whatname = &guyname;
whatlastname = &guylastname;
This is what you're looking for. However, it appears that you're just starting to play with pointers, and you may need to read up on them a little more before you start experimenting.

Passing pointers to string arrays to toupper() in C

I'm trying to pass a pointer array of strings to function toupper() in C.
main() {
char *choice[1];
scanf("%s", choice);
printf("%s", toupper(&choice[0]));
}
I always type in a lowercase word such as "modify" to test it. Different variations of this, such as toupper(*choice[0]) or toupper(*choice) or mixtures of them all, including &, have either thrown an error or returned the same lowercase "modify". Any suggestions?
To start with array of char pointers having one element doesn't make much sense to me since it will only point to one string.Why not declare a char array if you just want a single string?
Prototype of toupper is this:
int toupper( int ch );
It doesn't take an array.
You can try like this :
#include <stdio.h>
#include <ctype.h>
int main()
{
char str[25];
int i = 0;
setbuf(stdout,NULL);
printf ("enter the name \n");
fgets (str,sizeof str-1, stdin);
printf ("the name entered in upper case is :\n");
while (str[i])
{
int c = str[i];
printf ("%c",toupper(c));
i++;
}
return 0;
}
NOTE- Do not use scanf for taking strings try fgets , its better.
Before you call scanf, you need to allocate some space for the characters to be stored in. You only allocate a single pointer and then you don't even set it to point to anything. Similarly, toupper returns the converted character, which is not a string, so passing it to printf through %s is also wrong.
Something like this should serve the purpose.
#include<stdio.h>
#include<ctype.h>
void StrToUpper(char *str)
{
while(*str != '\0')
{
*str = toupper(*str);
str++;
}
}
int main()
{
char *choice[1];
choice[1] = new char[10];
scanf("%s", choice[1]);
StrToUpper(choice[1]);
printf("%s", choice[1]);
return 0;
}
In the program, you have array of pointers.
So:
Allocate memory for your string
call toupper(choice[0][0]);
toupper takes only a character value (between 0 and 255), not a pointer or array.

array of character in C

I have a question simple like that: Let user enter some words from keyboard,one word per line until a '.' (period) entered then print out result, for example:
Enter a word: word1
Enter a word: word2
Enter a word: .
You have entered 2 word(s):
word1
word2
OK here my try but when I run it said file has stopped working after let me enter first word
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char *word[50]; //each word has maximum 49 character
int i=0, number_of_word;
do
{
printf ("Enter a word: ");
scanf("%s", &word[i]);
i++;
}
while (word[i][0]!='.');
number_of_word =i;
printf ("You entered %d word(s):\n", number_of_word);
for (i=0; i<number_of_word; i++)
{
printf("%s\n", &word[i]);
}
return 0;
}
-----------------------------------------------------------------------
EDIT 1:
OK I try this, it worked but I am still looking for best way to declare an unknown size array of character string since I don't know neither how many word user may enter nor how many letter of each word, in C++ it may called dynamic allocation array, I have no idea how to do it in C
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
char word[20][50]; //array has maximum 20 words, each word maximum 50 character
int i=0, number_of_word;
do
{
printf ("Enter a word: ");
scanf("%s", word[i]);
i++;
}
while (word[i-1][0]!='.');
number_of_word =i-1;
printf ("You entered %d word(s):\n", number_of_word);
for (i=0; i<number_of_word; i++)
{
printf("Word %d is %s\n", i, word[i]);
}
return 0;
}
You are not assigning any memory to store the individual strings, so your program invokes undefined behaviour.
This:
char *word[50];
defines an array of 50 pointers, but no further storage.
And when you do this:
scanf("%s", &word[i]);
you're writing into the pointer array.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
int main () {
char *word[50]; //each word has maximum 50 word
char enter_word[50];//maximum 49 character
int i=0, number_of_word;
while(1){
printf("Enter a word: ");
scanf("%49s", enter_word);
if(*enter_word == '.')break;
word[i++]=strdup(enter_word);
}
number_of_word = i;
printf ("You entered %d word(s):\n", number_of_word);
for (i=0; i<number_of_word; i++){
printf("%s\n", word[i]);
}
for(i=0;i<number_of_word; ++i)
free(word[i]);
return 0;
}
When you declare
char *word[50];
You have 50 char pointers pointing to random memory. What you want is something like this:
char word[50][50];
Note that you can have only 49 words (and the '.'), and each can have less than 50 characters (don't forget the \0, so a word with 50 chars will overflow).
And you will want to change your scanf call to something like:
scanf("%s", word[i]);
Note that you do not need the &, since word[i] is already a pointer.
char *word[50];
You have an array of 50 pointers. You want an array of 50 byte chunks. How many words do you want to read? If you know the maximum, you can allocate the space in advance. If you don't, you need something like a linked list of strings, to which you can append a new item when you read it.
Its your printf Call. Remember to add the end character \0 to the end of the word. Printf when printing strings prints everything in the char array till it reads an end character \0
BasicAlly... Hos should printf know how long the word is and when it should stop printing?(Right now it continues forever)
You've done nothing to allocate memory for the individual strings.
Char *word[50] just declares a pointer to one array of char pointers.
EDIT
I'll try to illustrate this here with some pseudo code...formatted code on a phone is nearly impossible :) Given a prior char * input[50]:
char * nextString;
bool entering=true;
do{
nextString =calloc(50);
// enter the string to nextString
if (nextString[0] != '.'){
input[i] = nextString;
i++;
} else{
entering=false;
}
}
}while(entering)
"char *word[50]" have done nothing to allocate the memory for the individual string.
you should allocate it by using the function of alloc
you just try to use "%[^\n]" place of "%s" in scanf().
because "%s" stores characters until it found first space in the string.
try this with your very first asked Program
May its help to you.

string rotations

#include <stdio.h>
#include <string.h>
int main()
{
char s[15];
int i,j,n,*str;
printf("Enter a string");
scanf("%s",str);
n=strlen(str);
for(i=0;i<n;i++)
{
str[n]=str[0];
for(j=0;j<n;j++)
{
str[j]=str[j+1];
}
str[n]='\0';
printf("\n %s",str);
}
return 0;
}
this program gives me all possible rotations of string
can anyone explain str[n]=str[0] and str[j]=str[j+1] meaning
instead of taking n=strlen(s) can we use n=strlen(str)
plz explain
This rotates the string. The way it does so is by moving the first character to the last place by doing str[n] = str[0] (str[n] is the string-terminating null character '\0', then shifting the whole string down one (str[j] = str[j+1]), then replacing the null at the end (str[n]='\0').
This code would, if it were using s, cause a buffer overrun if the string is longer than 14 characters. However, there's also a logic error in the code: it should be either initializing str (as a char* not int*) or scanning into s with a length bound. For instance:
scanf("%14s", s);
or
str = (char*)malloc(500);
scanf("%500s", str);
instead of taking n=strlen(s) can we use n=strlen(str)
Actually, since str is an int-pointer that is not initialized anywhere, all uses of str should be replaced by s (it's probably just a typo).
#include <stdio.h>
#include <string.h>
int main()
{
char s[15];
char tmp_var;
int i,j,n,*str;
printf("Enter a string");
scanf("%s",str);
n=strlen(str);
for(i=0;i<n/2;i++)
{
tmp_var = str[i];
str[i] = str[n-i];
str[n-i] = tmp_var;
}
printf("\n Rotated String is %s \n",str);
return 0;
}

Resources