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

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.

Related

Comparing strings and keyboard inputs

When I enter "quit" on my keyboard, the if loop (marked by the comment "here quit is implemented") should return true and the program should end. But strcmp does not return zero. There are no compiler errors. I am not able to identify the problem.
int numInput(){
char str[10];
int num;
char nStr[10];
char q[4] = "quit"; //Quit
LAND:
scanf("%s",&str);
if (strcmp(q,str) == 0){ //Here quit is implemented
exit(0);
}else{
printf(str);
}
num = atoi(str);
itoa(num,nStr,10);
if (strcmp(nStr,str) != 0){
printf("Please enter numbers only!\nEnter number here:");
goto LAND;
}
return num;
}
The char array q doesn't have enough room to store the string "quit".
This string needs 5 characters: 4 for the letters and one for the terminating null byte. And because the array isn't big enough, attempting to use string functions on it causes these functions to read off the end of the array. This triggers undefined behavior.
The array needs to be at least one element larger:
char q[5] = "quit";
Or even better:
char q[] = "quit";
Which sizes the array to fit the initializer.
Also, this isn't correct:
scanf("%s",&str);
As you're passing a pointer to an array while the %s format specifier expects a char *. This should instead be:
scanf("%s",str);

How to show the result of written strings

I'm learning C Programming and I can't resolve this issue.
This is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int first;
printf("Write Down Your First Name!\n\n");
scanf("%s", &first);
int last;
printf("\nNow Write Your Sir Name!\n\n");
scanf("%s", &last);
printf("\nYour Full Name is %s\n\n");
system("pause");
return 0;
}
And I want to show the full name written.
Should I use void?
Thanks in advance
first and last should be of char array type instead of int type if you want to store characters into that.
int first; ---> char first[100]; /* define how many char you want in first*/
similarly
int last; --> char last[100];
And while scanning it you don't have to pass &
scanf("%s", first);
scanf("%s", last);
Want to print/show ?
printf("\nNow Write Your Sir Name! %s n\n", first);/* you missed to pass argument to printf */
printf("\nYour Full Name is %s\n\n",first);
How to join both ? Iterate last upto '\0' char and copy each char of last to end of first
int len = strlen(first);
first[len] = ' ';/* if needed, put space at the end of first */
for( i = 0, j = len + 1 ; last[i]!='\0;i++,j++) {
first[j] = last[i]; /* first should have enough space */
}
first[j] = '\0';
Now print it as
printf("\nYour Full Name is %s\n\n",first);

Passing String to Main from a function

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void get_name();
void display_name(char *fullname);
int main(void)
{
char first[80];
char second[80];
char *fullname[80];
get_name();
display_name(*fullname);
system("pause");
return 0;
}
void get_name()
{
char first[80];
char second[80];
char *fullname[80];
printf("Please enter first name: ");
scanf("%s", &first);
printf("\nPlease enter last name: ");
scanf("%s", &second);
strcpy(*fullname, first);
strcat(*fullname, " ");
strcat(*fullname, second);
printf("\n\nFull name is : %s ", *fullname);
}
void display_name(char *fullname)
{
int index;
char check;
int count=0;
printf("\n\nFull name is : %s ", fullname); //check to see if string is passes correctly
for(index=0; fullname[index] != '\0'; index++)
{
check=fullname[index];
if(check != ' ')
{
count++;
}
}
printf("\n\nNumber of characters in string is: %i\n", count);
}
im trying to send the string from get_name() to display name to count the number of characters. Everytime i pass the string, its comes out as gibberish. Am i passing wrong? I need to use one function to get the first and last name and concatenate the full name, then use another function to count the number of characters.
You're using pointers and scanf quite wrongly.
First of all scanf argument to for %s is supposed to be an array of characters. Remember that the array is in fact the pointer to the array.
Second you declare fullname to be an array of 80 pointers which is probably not what you want to do. Especially when you don't allocate the space for the string.
Instead it should be something like:
void get_name()
{
char first[80];
char second[80];
char fullname[80]; // an array of chars instead of pointers
printf("Please enter first name: ");
scanf("%s", first); // not taking the address of first - is already an address
printf("\nPlease enter last name: ");
scanf("%s", second); // not taking the address of second - is already an address
strcpy(fullname, first); // don't dereference fullname
strcat(fullname, " "); // don't dereference fullname
strcat(fullname, second); // don't dereference fullname
printf("\n\nFull name is : %s ", fullname); // don't dereference fullname
}
The declarations of variables are local to the scope where they are declared.
IOW when you declare first, second and fullname in your function get_name, they are local to that function. In order to pass the value outside of the function you have two, no three ways to do this starting with the worst way:
(1) declare the variable global, i.e. outside of main then share that variable in your function(s).
(2) declare the variable in main but pass it to the function who then fills in the string
int main()
{
char fullname[80];
get_name(fullname,sizeof(fullname)); // good to tell function avail size
...
void get_name(char* fullname, size_t length)
{
...
(3) Allocate memory on the heap, heap memory can be passed around between functions via a pointer
int main()
{
char* fullname = NULL;
get_name(&fullname);
...
void get_name(char** fullname)
{
*fullname = malloc(80);
...
EDIT
In order to read strings from the keyboard it is better to use fgets()
char buffer[128];
if (fgets(buffer,sizeof(buffer),stdin) != NULL) {
// remove the \n
char* p = strchr(buffer,'\n');
if ( p != NULL ) {
*p = '\0';
}
}
Using scanf reading from the keyboard is to be avoided, if you need to extract information use instead sscanf on the string read with fgets

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

Character Pointers with Palindrome Checker in 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)

Resources