warning: incompatible pointer to integer conversion - c

I am attempting to change the last character in a word to make it the plural version of that word. For example bus to buses or penny to pennies. I get a warning when I try to set the last character equal to the plural ending. Please let me know what I need to change in order to fix this problem. Thank you.
#include <stdio.h>
#include <string.h>
int main(void) {
char word[50];
char *last_char;
printf("Enter a word: ");
scanf("%[^\t\n]", word);
last_char = &word[(strlen(word)-1)];
if(*last_char == 'y')
{
*last_char = "ies";
printf("\nthis does not work %s", word);
}
else if(*last_char == 's')
{
*last_char = "es";
printf("\nthis is working %s", word);
}
else if(*last_char == 'h')
{
*last_char = 'es';
printf("\nPlural: %s", word);
}
else
{
last_char = &word[(strlen(word))];
*last_char = 's';
printf("\nPlural: %s", word);
}
return 0;
}

Just look at what you said yourself:
I get a warning when I try to set the last character equal to the plural ending.
You've got a memory slot for one character at that position and you're trying to squeeze many at that one slot. Isn't going to work.
"ies"; is not a single character, it is a string - an array of characters that decays to a pointer to the first character. A single char is of integer type; you cannot convert a pointer to character (well you can, but it does not make sense).
In this case the simple solution would be to strcpy the ending to the subarray starting from last_character, i.e.:
strcpy(last_char, "ies");
As for
last_char = &word[(strlen(word))];
*last_char = 's';
that is not correct because the string would not be null-terminated!
remember that last_char was already pointing to the last character, and the null terminator after that is at address last_char + 1; you can replace these two lines with
strcpy(last_char + 1, "s");

Related

How to encrypt a String in C

I am kind of new to coding and in this particular situation I am trying to change each character in a string.
My first attempt is to use a pointer to access each character (since I think it is some sort of an array so I won´t need an index for loop) and change it to '%'
Else I want to change the current location of the pointer to be +5 letters in the alphabet.
At the ende the pointer should move one forward.
So this string = "This is confidential information"
should look like this = "Ymnx%nx%htsknijsynfq%nsktwrfynts"
There is an Error at line 22 at the "if" statement where i want change the empty char to %
#include <stdio.h>
#include <ctype.h>
void encryptString(char *sPtr);
int main(void)
{
char string[] = "This is confidential information"; //given string to encrypt
printf("The string before encrypting is: %s", string);
encryptString(string);
printf("\nThe string after encrypting is: %s\n", string);
}
void encryptString(char *sPtr)
{
while(*sPtr != '\0'){ //loop is running until end of string
if(*sPtr == ''){ // should convert space char into a '%')
char *sPtr = '%';
}
else{ //should shift the output of character +5 in the alphabet
char *sPtr =+ 5;
}
++sPtr; //make sPtr point to the next character
}
}
There were some issues in your code, especially the way your have written x =+ 5. Also, I don't understand why you added the char in front of the assignment char *sPtr =+ 5. As it is written C interprets this as a cast to char, but dereferencing a pointer to char already has the char type, so it is useless at least and dangerous at most.. It actually creates a new variable that shadows the outer sPtr, sets it to point to some weird low memory location, then doesn't dereference it
Lastly you can think about what happen when the alphabet is finished, for instance when there is a z character. I have here your code fixed with an idea on how to wrap around with a ASCII table. Please mind that the C standard does not HAVE TO use ASCII, so this implementation won't work everywhere, it's more of an idea for you.
#include <stdio.h>
#include <ctype.h>
#define START_ALPHABET_ASCII 65
#define ALPHABET_LENGTH_ASCII (123-START_ALPHABET_ASCII)
void encryptString(char *sPtr);
int main(void)
{
char string[] = "This is confidential information zzz"; //given string to encrypt
printf("The string before encrypting is: %s", string);
encryptString(string);
printf("\nThe string after encrypting is: %s\n", string);
}
void encryptString(char *sPtr)
{
while(*sPtr != '\0'){ //loop is running until end of string
if(*sPtr == ' '){ // should convert space char into a '%')
*sPtr = '%';
}
else{ //should shift the output of character +5 in the alphabet
*sPtr = ((*sPtr)+5 - START_ALPHABET_ASCII)%(ALPHABET_LENGTH_ASCII) + START_ALPHABET_ASCII ;
}
++sPtr; //make sPtr point to the next character
}
}
Which prints
The string before encrypting is: This is confidential information zzz
The string after encrypting is: Ymnx%nx%htsknijsynfq%nsktwrfynts%EEE

Why the program can get right input but print wrong answer according to arrays?

As Above.
#include<stdio.h>
#include<string.h>
char str[10000],s,s1[1000],s2[1000],s3;
char *dict[1000];
int main()
{
memset(dict,0,sizeof(dict));
for(;;)
{
scanf("%s",s1);
if (s1[0] == '*')
{
break;
}
scanf("%s",s2);
dict[s1[0]] = (char*)s2;
}
printf("%s\n",dict['A']);
return 0;
}
I type:
A .-
B --
if right,it should print .-,and it can get s1[0] = 'A' and s2 = ".-" rightly,but I get -- as result.
You store all of the input strings in s2. The following iterations overwrite the input from the previous iteration. All pointers of dict point to s2.
Either the dict should be an array of arrays of char so that it can store the strings themselves, or s2 should be so that the inputs can be stored separately.
Minor notes:
(char*)s2
Avoid C style casts. They often hide bugs that the compiler would see. In this case, the cast is completely redundant and can be removed.
memset(dict,0,sizeof(dict));
This is redundant, since objects with static storage are zero initialised at the start of the program.
This coding would have been more easier in c++ (your's is C). Here's a way to do that in C way. You can also implement a search in the dictionary:
char s1[10], s2[10]; // max word length 10
char dict[1000][2][10]; // 1000 (dict entries) 2 (word + meaning) 10(max word length)
int main()
{
int idx = 0;
for (;;)
{
scanf("%s", s1); // word
if (s1[0] == '*')
{
break;
}
scanf("%s", s2); // describing word
strcpy(dict[idx][0], s1);
strcpy(dict[idx][1], s2);
idx++;
}
printf("%s %s\n", dict[0][0], dict[0][1]); // printing dict first entries
return 0;
}

Stuck in endless loop, not sure what I did wrong

Program compiles, but when I try to use it, I get an endless loop. Where did i do wrong. I put comments into what I am trying to accomplish.
I have tried changing it to a for loop, but I still get issues. I think I am suppose to stick with a while loop to accomplish what I am trying to accomplish.
//Declare the arrays to hold the strings
char str[21], vowels[21], consonants[21];
int i=0;
//Declare the pointers
char *strPointer, *vowelPointer, *consonantPointer;
//Print out the prompt to the user
printf("Enter a string (20 characters maximum): ");
//Scan the user input into str
//Only allow 20 characters
scanf("%s", str);
//Set strPointer to the beginning of the user's string
strPointer = str;
//Set vowelPointer to the beginning of the vowels string
vowelPointer = vowels;
//Set consonantPointer to the beginning of tht consonant string
consonantPointer = consonants;
//Loop through the user's string until the end of the string
while(*strPointer !='\0')
{
//Check if what strPointer is pointing to is a vowel
if(strPointer[i]=='A'||strPointer[i]=='a'||strPointer[i]=='E'||strPointer[i]=='e'||strPointer[i]=='I'||strPointer[i]=='i'||strPointer[i]=='O'||strPointer[i]=='o'||strPointer[i]=='U'||strPointer[i]=='u')
{
//Move the letter from strPointer to vowelPointer
strPointer=vowelPointer
;
//Move the vowelPointer
vowelPointer=vowels
;
}
else
{
//Move the letter from strPointer to consonantPointer
strPointer=consonantPointer
;
//Move the consonantPointer
consonantPointer=consonants
;
}
//Move the strPointer
strPointer=str;
}
//Add null terminators where appropriate
strPointer[21]='\0';
str[21]='\0';
//Set the vowel and consonant pointers back to the beginning of their strings
vowelPointer[0];
consonantPointer[0];
//Print the original string and the resulting vowel and consonant strings
printf("Original string: %s\n", str);
printf("%s\n", vowelPointer);
printf("%s\n", consonantPointer);
The output is explained in my printf statements at the end. Input string, reprinted with the vowels and consonants separated and listed.
I would like to make some suggestions to help you out.
First, when you are scanning from user input, it is wise to use a buffer. Then, strcpy the contents of the buffer into the char array. This will help to prevent overflow. Please see the below code for more details about this topic.
Second, you can use a for loop to iterate through each of the letters. I hope my answer will help you understand what I mean.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void)
{
//Declare the arrays to hold the strings
char c, str[21], vowels[21], consonants[21], buffer[21];
int i = 0, j = 0, h = 0;
//Declare the pointers
char *strPointer, *vowelPointer, *consonantPointer;
//Print out the prompt to the user
printf("Enter a string (20 characters maximum): ");
//Scan the user input into str
scanf("%s", buffer);
// Copy the buffer into the str
strcpy(str, buffer);
// go letter by letter checking if it is a vowel or consonant
for (int i = 0; str[i]; i++)
{
// make the character uppercase
c = toupper(str[i]);
// if the letter is a vowel add the letter to the vowel array,
// then increase the position
if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')
vowels[j++] = str[i];
else
// add the letter to the consonants array, then increase the position
consonants[h++] = str[i];
}
// properly terminate the strings
vowels[j] = '\0';
consonants[h] = '\0';
//Print the original string and the resulting vowel and consonant strings
printf("Original string: %s\n", str);
printf("%s\n", vowels);
printf("%s\n", consonants);
return 0;
}
You invoke an infinite loop by setting:
strPointer=str;
at the end of your while (*strPointer !='\0') loop. This resets the address held by strPointer to the beginning of str. strPointer is never incremented, so your loop loops with strPointer pointing to the first character in str over-and-over-and-over again...
Further, you initialize vowelPointer=vowels; which sets the address of vowelPointer to point to the beginning element of the uninitialized vowels array. The same occurs with consonantPointer=consonants;
Since both vowelPointer and consonantPointer point to arrays declared with automatic storage duration, you invoke Undefined Behavior when you attempt to access the uninitialized values with:
printf("%s\n", vowelPointer);
printf("%s\n", consonantPointer);
(but luckily you never get there because of your endlesss loop over while (*strPointer !='\0'))
Additionally, validate EVERY input and affirmatively protect your array bounds by using the field-width modifier with scanf (or better, use fgets()). For example:
//Only allow 20 characters
if (scanf( "%20s", str) != 1) {
fputs ("error: (user canceled input)\n", stderr);
return 1;
}
(note: when reading with "%s" the trailing '\n' is not consumed and will remain in your input buffer)
To fix your pointer problems, you can do something similar to the following:
//Declare the arrays to hold the strings
char str[21], vowels[21], consonants[21];
size_t vidx = 0, cidx = 0; /* indexes for vowels/consonants */
...
//Loop through the user's string until the end of the string
while (*strPointer)
{
//Check if what strPointer is pointing to is a vowel
if (strPointer[i]=='A'|| strPointer[i]=='a'||
strPointer[i]=='E'|| strPointer[i]=='e'||
strPointer[i]=='I'|| strPointer[i]=='i'||
strPointer[i]=='O'|| strPointer[i]=='o'||
strPointer[i]=='U'|| strPointer[i]=='u')
{
//Copy the letter from strPointer to vowelPointer
if (vidx < 20) {
vowelPointer[vidx] = *strPointer;
vidx++;
}
/* or using pointer arithmetic */
// if (vowelPointer - vowels < 20) {
// *vowelPointer = *strPointer;
// vowelPointer++;
// }
}
else {
//Copy the letter from strPointer to consonantPointer
if (cidx < 20) {
consonantPointer[cidx] = *strPointer;
cidx++;
}
/* same alternative available for consonantPointer */
}
//Move the strPointer
strPointer++;
}
//Add null terminators where appropriate
vowelPointer[vidx] = 0;
consonantPointer[cidx] = 0;
//Reset the ponters
vowelPointer = vowels;
consonantPointer = consonants;
//Print the original string and the resulting vowel and consonant strings
printf("Original string: %s\n", str);
printf("%s\n", vowelPointer);
printf("%s\n", consonantPointer);
If you are still stuck, you can put it altogether in a short, slightly more concise example as:
#include <stdio.h>
#include <ctype.h>
#define MAXC 1024 /* don't skimp on buffer size */
int main (void) {
char str[MAXC], cons[MAXC], vowels[MAXC], /* arrays */
*strptr = str, *consptr = cons, *vowelptr = vowels; /* pointers */
fputs ("Enter a string (1022 characters maximum): ", stdout);
if (!fgets (str, MAXC, stdin)) { /* validate EVERY read */
fputs ("error: (user canceled input)\n", stderr);
return 1;
}
while (*strptr) { /* loop over each character */
char lc = tolower (*strptr); /* convert to lowercase to compare */
if (lc == 'a' || lc == 'e' || lc == 'i' || lc == 'o' || lc == 'u')
*vowelptr++ = *strptr; /* copy vowel to array */
else if (!isspace (*strptr)) /* otherwise if not whitespace */
*consptr++ = *strptr; /* copy to consonant array */
strptr++; /* advance string pointer */
}
*vowelptr = *consptr = 0; /* nul-terminate arrays */
printf ("str : %scons : %s\nvowels: %s\n", str, cons, vowels);
}
(question: do you know why there is no '\n' needed after "str : %s" in the printf above?)
Note above that the character is converted to lowercase before comparison for a vowel to cut in-half the number of conditionals needed to check for a vowel. Don't skimp on buffer size. Generally you have 1M of stack space (4M on Linux). Use a buffer of at least 256-chars, or a simple 1K buffer as used above. Also note if you wanted to print using the pointer, you would simply reset them to point to the original arrays immediately after exiting the loop, e.g.
strptr = str;
consptr = cons;
vowelptr = vowels;
Regardless, you can print using the arrays or the pointers after resetting them as both will both point to the same address. See C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
Example Use/Output
$ ./bin/sepvowels
Enter a string (1022 char max): A quick brown fox jumps over the lazy dog
str : A quick brown fox jumps over the lazy dog
cons : qckbrwnfxjmpsvrthlzydg
vowels: Auioouoeeao

Why following code snippets assignment gives confusing output?

I'm studying C. I came across with string arrays. I'm bit confused about the following codes. I was anticipating one kind of output; however, getting completely different kind of output or program crush due to read access violation.
I've run this code on visual studio 2017, with _CRT_SECURE_NO_WARNINGS
// case 1
char* name[2];
//name[0] = (char*)malloc(sizeof(char*) * 10);
//name[1] = (char*)malloc(sizeof(char*) * 10);
name[0] = "john";
name[1] = 'doe';
printf("%s\n", name[0]); // prints john
//printf("%s\n", name[1]); // gives read access violation exception, why??? even with dynamically allocated memory
// case 2
char* name2[2] = { "emma", "olsson" };
printf("%s\n", name2[0]); // prints emma
printf("%s\n", name2[1]); // prints olsson, why no error???
// case 3
for (int i = 0; i < 2; i++)
{
name[i] = name2[i];
}
printf("%s\n", name[0]); // prints emma
printf("%s\n", name[1]); // prints olsson, why no error???
// case 4
char inputName[10];
int i = 0;
while (i < 2)
{
fgets(inputName, sizeof(inputName), stdin); // first input: Max second input: Payne
char* pos = strchr(inputName, '\n');
if (pos != NULL)
*pos = '\0';
name[i++] = inputName;
}
printf("%s\n", name[0]); // prints Payne, why not Max???
printf("%s\n", name[1]); // prints Payne
For case 1, 'doe' is not a string.
Case 2 works because you are initializing you pointers with string literals.
Case 3 works too because you assign the same initialized pointer in case 2 to case 1 pointers. Your name array pointers are basically set to point to where name2 ones are pointing.
In case 4, you declared inputName which points to a set of 10 chars. Then each time you get a new input you are writing it to the same memory section. And by doing this:name[i++] = inputName;
you are not copying a new char array to name[i] as you might think. Instead, you are telling name[i] char pointer to point to inputName. So it is normal that name prints last input twice, because that's what inputName points to, as well as both name char pointers.
It is unclear whether OP's code runs within main() or a user-defined function and what kind of value returns. That said, after removing superfluous variable redeclarations, here's how I achieved working code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char * name[2];
char * name2[2]={ "emma", "olsson" };
char inputName[10];
char names[BUFSIZ];
int i = 0;
// case 1
name[0] = "john";
name[1] = "doe";
printf("%s %s\n", name[0],name[1]); //john doe
// case 2
printf("%s %s\n", name2[0],name2[1]);//emma olsson
// case 3
for (i = 0; i < 2; i++){
name[i] = name2[i];
}
printf("%s %s\n", name[0],name[1]);//emma olsson
// case 4
i=0;
while (fgets(inputName, sizeof(inputName), stdin) != NULL && (i < 2) ){
strcat(names,inputName);
i++;
}
printf("\n%s\n",names);
return 0;
}
See live code here
OP should replace the single quotes around doe with double quotes which denote a null-terminated string. Single quotes are meant for a single character, i.e. 'a' refers to a byte value while "a" signifies a string containing two characters, an 'a' and a '\0'.
Also, OP should include two other libraries to facilitate execution. In particular, string.h is needed for the built-in string functions to execute properly.
Case 2 and Case 3 work because strings are encompassed by double quotes instead of single quotes. Note that in each case the "%s" format specifier for the printf() indicates that a string needs to be displayed.
In last case, fgets() with respect to stdin, upon success returns user input as a string. But that input will be overridden in the while loop, unless in each iteration you concatenate the old input with the new. Otherwise, when the inputName element values change because its address remains constant, only the latest input string displays. Here's some code that illustrates this point:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char * name[2];
char inputName[10];
int i = 0;
while (fgets(inputName, sizeof(inputName), stdin) != NULL && (i < 2) ){
printf("inputName: %p points to: %s",inputName,inputName);
name[i++] = inputName;
}
printf("\n name[0]: %p points to: %s\n name[1]: %p points to: %s",name[0],name[0],name[1],name[1]);
return 0;
}
Output:
inputName: 0x7fff8a511a50 points to: Maxine
inputName: 0x7fff8a511a50 points to: Pauline
name[0]: 0x7fff8a511a50 points to: Pauline
name[1]: 0x7fff8a511a50 points to: Pauline
See live code.
Incidentally, you don't need an array to display the names and indeed one may display the names outside of the loop as long as within the loop the code concatenates user input.

ANSI C strcmp() function never returning 0, where am I going wrong?

C isn't the language I know so I'm out of my comfort zone (learning C) and I have ran into an issue that I can't currently figure out.
I am trying to read from a text file one word at a time and compare it to a word that I have passed into the function as a pointer.
I am currently reading it from the file one character at a time and storing those characters in a new char array until it hits a space, then comparing that char array to the original word stored in the pointer (stored where it's pointing to, anyway).
When I do a printf to check if both arrays are the same they are, they both equal "Hello". At first I thought maybe it's because my char array doesn't have an end terminator but I tried adding one but still nothing is seeming to work.
My code is below and I would appreciate any help. Again C isn't my strong area.
If I do "Hello" it will be > 0 by the way, so I think it's because the gets() stdin function is also including the enter key or something of that sort. I am not sure of a better way to grab the string though.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int partA(char*);
main()
{
// Array to store my string
char myWord[81];
// myword = pointer to my char array to store. 80 = the size (maximum). stdin = standard input from my keyboard.
fgets(myWord, 80, stdin);
partA(myWord);
}
int partA(char *word)
{
// points to file.
FILE *readFile;
fopen_s(&readFile, "readThisFile.txt", "r");
char character;
char newWord[50];
int i = 0;
while ((character = fgetc(readFile)) != EOF)
{
if (character == ' ')
{
newWord[i] = '\0';
int sameWord = strcmp(word, newWord);
printf("Word: %s", word);
printf("newWord: %s", newWord);
if (sameWord == 0)
printf(" These words are the same.");
if (sameWord > 0)
printf(" sameWord > 0.");
if (sameWord < 0)
printf(" sameWord < 0.");
printf("\n");
i = 0;
}
if (character != ' ')
{
newWord[i] = character;
i++;
}
printf("%c", character);
}
fclose(readFile);
return 1;
}

Resources