How do I concat a character into a string? - c

I'm trying to take a char and add it to a string. OR if that's not possible, add it to an array of characters?
I tried changed 'string updated = ""' to 'char updated[text_length]' but I was getting the same error - incompatible integer to pointer conversion error
if(argc == 2 && IsDigitsOnly(argv[argc-1])) {
// convert to integer
int x = atoi(argv[argc-1]);
// prompt user for plaintext
string plaintext = get_string("plaintext: ");
int text_length = strlen(plaintext);
int ascii = 'a';
string updated= "";
for (int i = 0; i < text_length; i++)
{
if (isalpha(plaintext[i]))
{
if (isupper(plaintext[i]))
{
// GETTING ERROR HERE -- trying to pass 'letter' in strcat
// This gives me an error: incompatible integer to pointer conversion error
int n = (plaintext[i] + x) % 90;
char letter = n;
strcat(updated, letter);
}
else
{
ascii = (ascii + x) % 122;
}
}
}
printf("%s\n", updated);
}

Based on the string and get_string() call, I assume that you are using cs50. In this case:
You can not write to a string literal (updated).
srtcat wants a pointer to char (not a char) as second parameter.
Switch to:
char updated[SOME_SIZE] = "";
...
char letter = n;
strcat(updated, (char[]){letter, 0});
Notice that strcat is prone to buffer overflows, consider replacing it with snprintf, something like:
char updated[SOME_SIZE] = "";
...
char letter = n;
size_t len = strlen(updated);
snprintf(updated + len, sizeof updated - len, "%c", letter);

How do I concat a character into a string?
// Since C99, append by forming a compound literal.
strcat(some_string, (char []){some_chracter, '\0'});
Yet in OP's case, concatenating a character to a string is a weak approach.
For this task, strcat(updated, ...) is slow as each time a letter needs to be appended, updated is longer and longer. See Schlemiel the Painter's Algorithm.
A more idiomatic approach would keep track of the length of updated and use that as an index in appending letter.
int text_length = strlen(plaintext);
int ascii = 'a';
// string updated= "";
char updated[text_length + 1]; // `text_length + 1` is the maximum size needed.
// Add
int updated_used = 0;
for (int i = 0; i < text_length; i++)
{
if (isalpha(plaintext[i]))
{
if (isupper(plaintext[i]))
{
int n = (plaintext[i] + x) % 90;
char letter = n;
// strcat(updated, letter);
updated[updated_used++] = letter;
}
else
{
ascii = (ascii + x) % 122;
}
}
}
// Add
updated[updated_used] = '\0';
Both int n = (plaintext[i] + x) % 90; and ascii = (ascii + x) % 122; look wrong.
I suspect OP wants to shift within uppercase letters with
int n = (plaintext[i] - 'A' + x) % 26 + 'A';
and for lower case:
int n = (plaintext[i] - 'a' + x) % 26 + 'a';

Related

How do you copy an int or a char into a string element? I'm having trouble with pointers and casting

Instead of having the following function print out an encrypted version of each element in the string, I would like to pass each encrypted digit into a new string and then return a pointer to that new array.
void encrypt(int key, char *plaintext)
{
int length = strlen(plaintext);
for (int i = 0; i < length; i++)
{
if isupper(plaintext[i])
printf("%c", (((plaintext[i] + key) - 'A') % 26) + 'A');
else if islower(plaintext[i])
printf("%c", (((plaintext[i] + key) - 'a') % 26) + 'a');
else
printf("%c", plaintext[i]);
}
}
I wrote the following function, but I get the following errors in clang:
Lines 12 & 14:
incompatible integer to pointer conversion assigning to 'char *' from 'int'
Line 16:
incompatible integer to pointer conversion assigning to 'char *' from 'char'; take the address with &
I'm new to pointers and can't figure out why my approach doesn't work. On lines 12 & 14, I've tried casting the result of the formula to a char to no avail.
char * encrypt(int key, char *plaintext)
{
int length = strlen(plaintext);
char *cipher[length];
char element;
for (int i = 0; i < length; i++)
{
element = (char) &plaintext[i];
if isupper(element)
cipher[i] = (((element + key) - 'A') % 26) + 'A'; // Line 12 error
else if islower(element)
cipher[i] = (((element + key) - 'a') % 26) + 'a'; // Line 14 error
else
cipher[i] = element; // Line 16 error
}
return cipher[0];
}
how do you copy an int or a char into a string element?
Where to form the result?
char *cipher[length]; is an array of pointers, not the expected array of char. Code like cipher[i] = (((element + key) - 'A') % 26) + 'A'; is attempting to assigned an integer to a pointer.
This array ceases to exist at the end of the function and is not something to return.
Instead, consider passing in the destination:
// char * encrypt(int key, char *plaintext)
void encrypt(int key, const char *plaintext, char *cipher) {
...
cipher[i] = (plaintext[i] - 'A' + key) % 26 + 'A';
}
// sample call
char plain[] = "Hello";
char cipher[sizeof plain];
int key = 1;
encrypt(key, plain, cipher)
'\0' termination
Append a null character to the destination
// after the loop
cipher[i] = '\0';
Advanced: Reduce key
With int key, trouble occurs when key < 0 or is near INT_MAX. Reduce it to [0...26) before the loop.
key %= 26;
if (key < 0) key += 26;
Tip: this allows decryption using the same function by calling with -key.
Minor: Look for the null character
Simplify code, use the right type for array indexing to handle long strings.
//int length = strlen(plaintext);
...
// for (int i = 0; i < length; i++)
size_t i;
for (i = 0; plaintext[i] != '\0'; i++)
Advanced: Other
Only listed for reference, but not detailed.
locale
Non-ASCII
negative char

How to Append a character to a string literal in C

So I have seen that some people do not recommend using String literals to create a char in C. However, I have found this to be the most useful method and I have a char set as
char a[] = "456";
I understand that the memory is fixed in this data type. However, in my assignment I believe that I need to be able to reallocate memory for my char value since I am adding integers that are represented as strings. For example:
char b[] = "500";
char c[] = "501";
//add function for adding b and c. have a char d[] equal to "1000".
I am using long addition to accomplish this. I have tried experimenting with the realloc function but it did not work. How would I continuously append new characters onto a string?
For your assignment, you must define a destination array with enough space to hold the result, which for an addition is easy to determine: it is the length of the longest argument plus one character for a possible extra digit plus one character for the null terminator.
You can allocate this array with malloc() and return a pointer.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *bigadd(const char *a, const char *b) {
size_t alen = strlen(a);
size_t blen = strlen(b);
size_t clen = (alen > blen) ? alen : blen;
size_t mlen = (alen > blen) ? blen : alen;
char *c = malloc(clen + 2);
if (c != NULL) {
size_t i;
int carry = 0;
c[clen] = '\0';
for (i = 1; i <= mlen; i++) {
carry += a[alen - i] - '0' + b[blen - i] - '0';
c[clen - i] = '0' + carry % 10;
carry /= 10;
}
for (; i <= alen; i++) {
carry += a[alen - i] - '0';
c[clen - i] = '0' + carry % 10;
carry /= 10;
}
for (; i <= blen; i++) {
carry += b[blen - i] - '0';
c[clen - i] = '0' + carry % 10;
carry /= 10;
}
if (carry) {
memmove(c + 1, c, clen + 1);
c[0] = (char)('0' + carry);
}
}
return c;
}
int main(int argc, char *argv[]) {
const char *a = argc > 1 ? argv[1] : "123456890123456890123456890";
const char *b = argc > 2 ? argv[2] : "2035864230956204598237409822324";
char *c = bigadd(a, b);
printf("%s + %s = %s\n", a, b, c);
free(c);
return 0;
}
so the way I see it is by typing:
char a[] = "456";
you initialise a character array of size 4 (3 chars +'\0'). storing anything longer in the same array could cause an undefined behavior and must be avoided. long story short: you can modify the value of this array, as long as the size of it doesn't change. You can initialise an array like this:
char a[100] = "456";
to leave some extra space for any possible additions to the string, but that's about it, since a size of the array is known at compiling, and doesn't ever change.
also please note that this won't work:
char * a = "456";
it's a read-only string literal which cannot be modified or realloced.
PS: I'm a novice, please correct me if I'm wrong!

Exception thrown: read access violation

i'm a beginner and my english is not well so sorry first. im trying to sum the numbers in a string (for a14fg5pk145 it returns 14+5+145), and it doesn't work:
"Exception thrown: read access violation.
str was 0x61."
this i my code:
void main()
{
int x, i;
char* pp;
char buffer[SIZE];
printf("Please enter numbers and letters:\n");
gets(buffer);
pp = buffer;
x = SumStr(*pp);
printf("%d", x);
}
int SumStr(char* str)
{
int sum=0, num=0, flag = 0;
while ((*str) != '\0')
{
while (((*str) > '1') && ((*str) < '9'))
{
if (flag == 0)
{
num += (*str);
flag = 1;
}
else if (flag == 1)
num = num * 10 + (*str);
str++;
}
if (flag == 0)
str++;
sum += num;
num = 0;
flag = 0;
}
return sum;
}
First problem with your code which is causing Exception.
x = SumStr(*pp);
it should be
x = SumStr(pp);
Because you should pass address of the string pointer not its first character by attaching asterix.
Second Issue that will not make it work is.
num += (*str);
and
num = num * 10 + (*str);
By (*str) you are actually adding the character ascii value instead of number.
This will solve the problem by changing the ascii value to number.
num += (*str) - '0';
num = num * 10 + (*str) - '0';
This may serve your purpose
#include<stdio.h>
#include<string.h>
int main()
{
int i, sum = 0, store;
char str[] = "a14fg5pk145asdasdad6";
int length = strlen(str);
for(i = 0; i < length; i++) {
store = 0;
while(isdigit(str[i])) {
store = (store * 10) + (str[i] - '0');
i++;
}
sum += store;
}
printf("%d\n", sum);
return 0;
}
output :
170
Pass pp, not *pp, to the function SumStr. *pp has the type char, and the function expects char *. In fact, you do not even need pp at all, just pass the buffer as the parameter.
Also:
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.

Caesar code in C extra letter for result

#include <stdio.h>
void caesar(char bemenet[], char eredmeny[], int n){
int i = 0;
for(i = 0; bemenet[i] != '\0'; i++) {
if(bemenet[i] == 'z') {
eredmeny[i] = 'a';
eredmeny[i] += n-1;
}
else
{
eredmeny[i] += n;
}
}
eredmeny[i] = '\0';
}
int main(){
char tomb1[]="caesarkodolas";
char tomb2[]="";
caesar(tomb1,tomb2,1);
printf("%s \n",tomb2);
return 0;
}
My out for the "eredmeny" (result) this:
"dbftbslpepmb" but tomb2=> ☺dbftbslpepmb it's not OK.. cause I have an extra char |☺|..
Allocate enough memory for the second parameter, and change this line
eredmeny[i] += n;
to this:
eredmeny[i] = bemenet[i] + n;
Note that this is not a bulletproof implementation of Caesar cipher: it would work for n==1, but it will break for larger n.
You need to think of a different way of implementing the "wrap-around": rather than testing for 'z' and replacing it with 'a', compute the new position of a letter modulo 26, and then add a to it:
void caesar(char bemenet[], char eredmeny[], int n){
int i;
for(i = 0; bemenet[i] != '\0'; i++) {
// Compute the position of the replacement letter
int pos = (bemenet[i] - 'a' + n) % 26;
// Place the letter into the output.
eredmeny[i] = 'a' + pos;
}
eredmeny[i] = '\0';
}
demo.
First of all you should have tomb2 big enough to store result.
For example, as mentioned above
char tomb2[255] = {0};
Also you have error here
else
{
eredmeny[i] += n;
}
You have to assign valid ASCII value to eredmeny[i] so change this string to
eredmeny[i] += bemenet[i] + n
Also it usually bad practice to pass a pointer on array without passing its size. Easy to get buffer overflow.
you're not doing the maths right.
if you are using just lower case letters then you need to add n, but then many letters will be "after" z, so you need to start again at a.
you want something more like this:
for(i = 0; bemenet[i] != '\0'; i++) {
int encrypted = bemenet[i] + n;
if (encrypted > 'z') encrypted = encrypted - 'z' + 'a';
eredmeny[i] = (char)encrypted;
}
(and also fix the output array size as described in other answers here).

what is wrong with my reverse function

I'm trying to writing a function to reverse a string: If the string input is "Hello World", the function should return "dlroW olleH". However, when I run my function the string stays the same:
void reversestring(char* s) {
char tmp; //tmp storing the character for swaping
int length; //the length of the given string
int i; //loop counter
//reverse the string of even length
length = strlen(s);
if (length % 2 == 0) { //if the length of the string is even
for(i = 0; i < (int) (length / 2);i++) {
tmp = s[length - i];
s[length - i] = s[i];
s[i] = tmp;
}
}
//reverse the string of odd length
if (length % 2 == 1) { //if the length of the string is odd
for(i = 0; i < (int) ((length + 1) / 2);i++) {
tmp = s[length + 1];
s[length + 1] = s[i];
s[i] = tmp;
}
}
}
You only need one loop to deal with strings. And the symmetric character of s[i] is s[length-i-1],
void reverse(char* s) {
char tmp; //tmp storing the character for swaping
int length; //the length of the given string
int i; //loop counter
//reverse the string of even length
length = strlen(s);
if (length < 2) return;
for(i = 0; i < (int) (length / 2);i++){
tmp = s[length - i - 1];
s[length - i - 1] = s[i];
s[i] = tmp;
}
}
Exemple:
abcde
01234
length is 5, length / 2 is 2 (integer division). length is odd, but you don't have to move the central character. Characters that need to be swapped
(0,4), (1,3)
Test:
int main () {
char x[] = "Hello World";
reverse(x);
printf("%s \n",x );
return 0;
}
prints
dlroW olleH
You are off by one in indexing. The symmetric of s[0] is not s[length- 0] , but s[length-0-1].
As for the odd case I don't get it what exactly you try to do but it seems you easily go out of bounds on each iteration.

Resources